Various minor

re-implement forge/sponge modules
Fix NBT copy error
Fix entity/tile error
Some work on multi-clipboards
This commit is contained in:
Jesse Boyd 2017-11-09 07:18:16 +11:00
parent 7a4b7be26a
commit b020e3ebe6
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
45 changed files with 968 additions and 212 deletions

View File

@ -54,7 +54,7 @@ public class BukkitImageListener implements Listener {
Bukkit.getPluginManager().registerEvents(this, plugin); Bukkit.getPluginManager().registerEvents(this, plugin);
} }
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onPlayerInteractEntity(AsyncPlayerChatEvent event) { public void onPlayerInteractEntity(AsyncPlayerChatEvent event) {
Set<Player> recipients = event.getRecipients(); Set<Player> recipients = event.getRecipients();
Iterator<Player> iter = recipients.iterator(); Iterator<Player> iter = recipients.iterator();

View File

@ -21,8 +21,12 @@ import com.boydti.fawe.util.chat.ChatManager;
import com.boydti.fawe.util.chat.PlainChatManager; import com.boydti.fawe.util.chat.PlainChatManager;
import com.boydti.fawe.util.cui.CUI; import com.boydti.fawe.util.cui.CUI;
import com.boydti.fawe.util.metrics.BStats; import com.boydti.fawe.util.metrics.BStats;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.CompoundTagBuilder;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.BlockVector; import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.BlockWorldVector; import com.sk89q.worldedit.BlockWorldVector;
import com.sk89q.worldedit.CuboidClipboard; import com.sk89q.worldedit.CuboidClipboard;
@ -118,6 +122,8 @@ import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.runtime.ExpressionEnvironment; import com.sk89q.worldedit.internal.expression.runtime.ExpressionEnvironment;
import com.sk89q.worldedit.internal.expression.runtime.For; import com.sk89q.worldedit.internal.expression.runtime.For;
import com.sk89q.worldedit.internal.expression.runtime.Functions; import com.sk89q.worldedit.internal.expression.runtime.Functions;
import com.sk89q.worldedit.internal.expression.runtime.SimpleFor;
import com.sk89q.worldedit.internal.expression.runtime.While;
import com.sk89q.worldedit.math.convolution.HeightMap; import com.sk89q.worldedit.math.convolution.HeightMap;
import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation; import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation;
import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.AffineTransform;
@ -647,6 +653,8 @@ public class Fawe {
Expression.inject(); // Optimizations Expression.inject(); // Optimizations
Functions.inject(); // Optimizations Functions.inject(); // Optimizations
For.inject(); // Fixes For.inject(); // Fixes
SimpleFor.inject(); // Fixes
While.inject(); // Fixes
// BlockData // BlockData
BlockData.inject(); // Temporary fix for 1.9.4 BlockData.inject(); // Temporary fix for 1.9.4
BundledBlockData.inject(); // Add custom rotation BundledBlockData.inject(); // Add custom rotation
@ -663,6 +671,10 @@ public class Fawe {
// NBT // NBT
NBTInputStream.inject(); // Add actual streaming + Optimizations + New methods NBTInputStream.inject(); // Add actual streaming + Optimizations + New methods
NBTOutputStream.inject(); // New methods NBTOutputStream.inject(); // New methods
Tag.inject(); // Expose raw data
CompoundTag.inject(); // Expose raw data
CompoundTagBuilder.inject(); // make accessible
ListTag.inject(); // Expose raw data
// Math // Math
KochanekBartelsInterpolation.inject(); // Optimizations KochanekBartelsInterpolation.inject(); // Optimizations
AffineTransform.inject(); // Optimizations AffineTransform.inject(); // Optimizations

View File

@ -7,6 +7,7 @@ import com.boydti.fawe.config.Commands;
import com.boydti.fawe.jnbt.anvil.HeightMapMCAGenerator; import com.boydti.fawe.jnbt.anvil.HeightMapMCAGenerator;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.boydti.fawe.util.CleanTextureUtil; import com.boydti.fawe.util.CleanTextureUtil;
import com.boydti.fawe.util.FilteredTextureUtil; import com.boydti.fawe.util.FilteredTextureUtil;
import com.boydti.fawe.util.ImgurUtility; import com.boydti.fawe.util.ImgurUtility;
@ -452,14 +453,14 @@ public class CFICommands extends MethodCommands {
World world = fp.getWorld(); World world = fp.getWorld();
WorldData wd = world.getWorldData(); WorldData wd = world.getWorldData();
ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(fp.getPlayer(), wd, schematic, true); MultiClipboardHolder multi = ClipboardFormat.SCHEMATIC.loadAllFromInput(fp.getPlayer(), wd, schematic, true);
if (clipboards == null) { if (multi == null) {
return; return;
} }
if (imageMask == null) { if (imageMask == null) {
gen.addSchems(mask, wd, clipboards, rarity, distance, rotate); gen.addSchems(mask, wd, multi.getHolders(), rarity, distance, rotate);
} else { } else {
gen.addSchems(imageMask, mask, wd, clipboards, rarity, distance, rotate); gen.addSchems(imageMask, mask, wd, multi.getHolders(), rarity, distance, rotate);
} }
msg("Added schematics!").send(fp); msg("Added schematics!").send(fp);
populate(fp); populate(fp);

View File

@ -194,6 +194,7 @@ public enum BBC {
SCHEMATIC_LIST("Available files (Filename: Format) [%s0/%s1]:", "Worldedit.Schematic"), SCHEMATIC_LIST("Available files (Filename: Format) [%s0/%s1]:", "Worldedit.Schematic"),
SCHEMATIC_LIST_ELEM("&8 - &a%s0 &8- &7%s1", "Worldedit.Schematic"), SCHEMATIC_LIST_ELEM("&8 - &a%s0 &8- &7%s1", "Worldedit.Schematic"),
CLIPBOARD_URI_NOT_FOUND("You do not have %s0 loaded", "WorldEdit.Clipboard"),
CLIPBOARD_CLEARED("Clipboard cleared", "WorldEdit.Clipboard"), CLIPBOARD_CLEARED("Clipboard cleared", "WorldEdit.Clipboard"),
CLIPBOARD_INVALID_FORMAT("Unknown clipboard format: %s0", "WorldEdit.Clipboard"), CLIPBOARD_INVALID_FORMAT("Unknown clipboard format: %s0", "WorldEdit.Clipboard"),

View File

@ -34,6 +34,7 @@ import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
public class HeightMapMCAGenerator extends MCAWriter implements Extent { public class HeightMapMCAGenerator extends MCAWriter implements Extent {
private final MutableBlockVector mutable = new MutableBlockVector(); private final MutableBlockVector mutable = new MutableBlockVector();
@ -238,13 +239,13 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
@Deprecated @Deprecated
public void addSchems(Mask mask, WorldData worldData, ClipboardHolder[] clipboards, int rarity, boolean rotate) throws WorldEditException { public void addSchems(Mask mask, WorldData worldData, List<ClipboardHolder> clipboards, int rarity, boolean rotate) throws WorldEditException {
CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(getWidth(), 255, getLength())); CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(getWidth(), 255, getLength()));
addSchems(region, mask, worldData, clipboards, rarity, rotate); addSchems(region, mask, worldData, clipboards, rarity, rotate);
update(); update();
} }
public void addSchems(BufferedImage img, Mask mask, WorldData worldData, ClipboardHolder[] clipboards, int rarity, int distance, boolean randomRotate) throws WorldEditException { public void addSchems(BufferedImage img, Mask mask, WorldData worldData, List<ClipboardHolder> clipboards, int rarity, int distance, boolean randomRotate) throws WorldEditException {
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) if (img.getWidth() != getWidth() || img.getHeight() != getLength())
throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
double doubleRarity = rarity / 100d; double doubleRarity = rarity / 100d;
@ -268,7 +269,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
continue; continue;
} }
placed.add(x, z); placed.add(x, z);
ClipboardHolder holder = clipboards[PseudoRandom.random.random(clipboards.length)]; ClipboardHolder holder = clipboards.get(PseudoRandom.random.random(clipboards.size()));
if (randomRotate) { if (randomRotate) {
int rotate = PseudoRandom.random.random(4) * 90; int rotate = PseudoRandom.random.random(4) * 90;
if (rotate != 0) { if (rotate != 0) {
@ -296,7 +297,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
update(); update();
} }
public void addSchems(Mask mask, WorldData worldData, ClipboardHolder[] clipboards, int rarity, int distance, boolean randomRotate) throws WorldEditException { public void addSchems(Mask mask, WorldData worldData, List<ClipboardHolder> clipboards, int rarity, int distance, boolean randomRotate) throws WorldEditException {
int scaledRarity = (256 * rarity) / 100; int scaledRarity = (256 * rarity) / 100;
int index = 0; int index = 0;
AffineTransform identity = new AffineTransform(); AffineTransform identity = new AffineTransform();
@ -318,7 +319,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
mutable.mutY(y + 1); mutable.mutY(y + 1);
placed.add(x, z); placed.add(x, z);
ClipboardHolder holder = clipboards[PseudoRandom.random.random(clipboards.length)]; ClipboardHolder holder = clipboards.get(PseudoRandom.random.random(clipboards.size()));
if (randomRotate) { if (randomRotate) {
int rotate = PseudoRandom.random.random(4) * 90; int rotate = PseudoRandom.random.random(4) * 90;
if (rotate != 0) { if (rotate != 0) {

View File

@ -11,18 +11,19 @@ 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.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.registry.WorldData; import com.sk89q.worldedit.world.registry.WorldData;
import java.util.List;
public class SchemGen extends Resource { public class SchemGen extends Resource {
private final Extent extent; private final Extent extent;
private final WorldData worldData; private final WorldData worldData;
private final ClipboardHolder[] clipboards; private final List<ClipboardHolder> clipboards;
private final boolean randomRotate; private final boolean randomRotate;
private final Mask mask; private final Mask mask;
private MutableBlockVector mutable = new MutableBlockVector(); private MutableBlockVector mutable = new MutableBlockVector();
public SchemGen(Mask mask, Extent extent, WorldData worldData, ClipboardHolder[] clipboards, boolean randomRotate) { public SchemGen(Mask mask, Extent extent, WorldData worldData, List<ClipboardHolder> clipboards, boolean randomRotate) {
this.mask = mask; this.mask = mask;
this.extent = extent; this.extent = extent;
this.worldData = worldData; this.worldData = worldData;
@ -41,7 +42,7 @@ public class SchemGen extends Resource {
return false; return false;
} }
mutable.mutY(y + 1); mutable.mutY(y + 1);
ClipboardHolder holder = clipboards[PseudoRandom.random.random(clipboards.length)]; ClipboardHolder holder = clipboards.get(PseudoRandom.random.random(clipboards.size()));
if (randomRotate) { if (randomRotate) {
holder.setTransform(new AffineTransform().rotateY(PseudoRandom.random.random(4) * 90)); holder.setTransform(new AffineTransform().rotateY(PseudoRandom.random.random(4) * 90));
} }

View File

@ -11,14 +11,15 @@ import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import java.util.List;
public class PopulateSchem implements Brush { public class PopulateSchem implements Brush {
private final Mask mask; private final Mask mask;
private final boolean randomRotate; private final boolean randomRotate;
private final ClipboardHolder[] clipboards; private final List<ClipboardHolder> clipboards;
private final int rarity; private final int rarity;
public PopulateSchem(Mask mask, ClipboardHolder[] clipboards, int rarity, boolean randomRotate) { public PopulateSchem(Mask mask, List<ClipboardHolder> clipboards, int rarity, boolean randomRotate) {
this.mask = mask; this.mask = mask;
this.clipboards = clipboards; this.clipboards = clipboards;
this.rarity = rarity; this.rarity = rarity;

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object.brush.scroll; package com.boydti.fawe.object.brush.scroll;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
@ -11,7 +12,6 @@ import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; 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.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.session.ClipboardHolder;
import java.io.IOException; import java.io.IOException;
public abstract class ScrollAction implements ScrollTool { public abstract class ScrollAction implements ScrollTool {
@ -34,11 +34,11 @@ public abstract class ScrollAction implements ScrollTool {
} }
String filename = split[1]; String filename = split[1];
try { try {
ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), filename, message); MultiClipboardHolder multi = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), filename, message);
if (clipboards == null) { if (multi == null) {
return null; return null;
} }
return (new ScrollClipboard(tool, session, clipboards)); return (new ScrollClipboard(tool, session, multi.getHolders()));
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View File

@ -5,13 +5,14 @@ import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.command.tool.BrushTool; import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import java.util.List;
public class ScrollClipboard extends ScrollAction { public class ScrollClipboard extends ScrollAction {
private final ClipboardHolder[] clipboards; private final List<ClipboardHolder> clipboards;
private final LocalSession session; private final LocalSession session;
int index = 0; int index = 0;
public ScrollClipboard(BrushTool tool, LocalSession session, ClipboardHolder[] clipboards) { public ScrollClipboard(BrushTool tool, LocalSession session, List<ClipboardHolder> clipboards) {
super(tool); super(tool);
this.clipboards = clipboards; this.clipboards = clipboards;
this.session = session; this.session = session;
@ -19,8 +20,8 @@ public class ScrollClipboard extends ScrollAction {
@Override @Override
public boolean increment(Player player, int amount) { public boolean increment(Player player, int amount) {
index = MathMan.wrap(index + amount, 0, clipboards.length - 1); index = MathMan.wrap(index + amount, 0, clipboards.size() - 1);
ClipboardHolder clipboard = clipboards[index]; ClipboardHolder clipboard = clipboards.get(index);
session.setClipboard(clipboard); session.setClipboard(clipboard);
return true; return true;
} }

View File

@ -88,6 +88,10 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
} }
} }
public File getFile() {
return file;
}
private void init() throws IOException { private void init() throws IOException {
if (this.fc == null) { if (this.fc == null) {
this.fc = braf.getChannel(); this.fc = braf.getChannel();
@ -280,6 +284,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
@Override @Override
public void close() { public void close() {
MainUtil.stacktrace();
try { try {
if (mbb != null) { if (mbb != null) {
mbb.force(); mbb.force();

View File

@ -13,7 +13,7 @@ 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.util.Location;
import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayList; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -26,17 +26,17 @@ public class EmptyClipboard implements Clipboard {
@Override @Override
public Region getRegion() { public Region getRegion() {
return new CuboidRegion(new Vector(), new Vector()); return new CuboidRegion(Vector.ZERO, Vector.ZERO);
} }
@Override @Override
public Vector getDimensions() { public Vector getDimensions() {
return new Vector(); return Vector.ZERO;
} }
@Override @Override
public Vector getOrigin() { public Vector getOrigin() {
return new Vector(); return Vector.ZERO;
} }
@Override @Override
@ -45,22 +45,22 @@ public class EmptyClipboard implements Clipboard {
@Override @Override
public Vector getMinimumPoint() { public Vector getMinimumPoint() {
return new Vector(); return Vector.ZERO;
} }
@Override @Override
public Vector getMaximumPoint() { public Vector getMaximumPoint() {
return new Vector(); return Vector.ZERO;
} }
@Override @Override
public List<? extends Entity> getEntities(Region region) { public List<? extends Entity> getEntities(Region region) {
return new ArrayList<>(); return Collections.emptyList();
} }
@Override @Override
public List<? extends Entity> getEntities() { public List<? extends Entity> getEntities() {
return new ArrayList<>(); return Collections.emptyList();
} }
@Nullable @Nullable

View File

@ -2,16 +2,17 @@ package com.boydti.fawe.object.clipboard;
import com.boydti.fawe.object.schematic.StructureFormat; import com.boydti.fawe.object.schematic.StructureFormat;
import com.google.common.io.ByteSource; import com.google.common.io.ByteSource;
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.ClipboardReader; import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
import com.sk89q.worldedit.extent.clipboard.io.SchematicReader; import com.sk89q.worldedit.extent.clipboard.io.SchematicReader;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.registry.WorldData; import com.sk89q.worldedit.world.registry.WorldData;
import java.io.InputStream; import java.io.InputStream;
import java.net.URI;
import java.util.UUID; import java.util.UUID;
public class LazyClipboardHolder extends ClipboardHolder { public class LazyClipboardHolder extends URIClipboardHolder {
private final ByteSource source; private final ByteSource source;
private final ClipboardFormat format; private final ClipboardFormat format;
private final UUID uuid; private final UUID uuid;
@ -22,16 +23,20 @@ public class LazyClipboardHolder extends ClipboardHolder {
* *
* @param worldData the mapping of blocks, entities, and so on * @param worldData the mapping of blocks, entities, and so on
*/ */
public LazyClipboardHolder(ByteSource source, ClipboardFormat format, WorldData worldData, UUID uuid) { public LazyClipboardHolder(URI uri, ByteSource source, ClipboardFormat format, WorldData worldData, UUID uuid) {
super(EmptyClipboard.INSTANCE, worldData); super(uri, EmptyClipboard.INSTANCE, worldData);
this.source = source; this.source = source;
this.format = format; this.format = format;
this.uuid = uuid != null ? uuid : UUID.randomUUID(); this.uuid = uuid != null ? uuid : UUID.randomUUID();
} }
@Override
public boolean contains(Clipboard clipboard) {
return this.clipboard == clipboard;
}
@Override @Override
public Clipboard getClipboard() { public synchronized Clipboard getClipboard() {
if (clipboard == null) { if (clipboard == null) {
try { try {
try (InputStream in = source.openBufferedStream()) { try (InputStream in = source.openBufferedStream()) {
@ -51,4 +56,12 @@ public class LazyClipboardHolder extends ClipboardHolder {
} }
return clipboard; return clipboard;
} }
@Override
public synchronized void close() {
if (clipboard instanceof BlockArrayClipboard) {
((BlockArrayClipboard) clipboard).close();
}
clipboard = null;
}
} }

View File

@ -1,43 +1,149 @@
package com.boydti.fawe.object.clipboard; package com.boydti.fawe.object.clipboard;
import com.boydti.fawe.object.PseudoRandom; import com.boydti.fawe.object.PseudoRandom;
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.math.transform.Transform;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.registry.WorldData; import com.sk89q.worldedit.world.registry.WorldData;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class MultiClipboardHolder extends ClipboardHolder {
private final ClipboardHolder[] holders;
private ClipboardHolder holder; import static com.google.common.base.Preconditions.checkNotNull;
public MultiClipboardHolder(WorldData worldData, ClipboardHolder... holders) { public class MultiClipboardHolder extends URIClipboardHolder {
super(holders[0].getClipboard(), worldData); private final List<URIClipboardHolder> holders;
holder = holders[0]; private Clipboard[] cached;
this.holders = holders;
public MultiClipboardHolder(WorldData worldData) {
this(URI.create(""), worldData);
} }
public MultiClipboardHolder(URI uri, WorldData worldData) {
super(uri, EmptyClipboard.INSTANCE, worldData);
holders = new ArrayList<>();
}
public MultiClipboardHolder(URI uri, WorldData worldData, URIClipboardHolder... addHolders) {
this(uri, worldData);
for (URIClipboardHolder h : addHolders) add(h);
}
public MultiClipboardHolder(Clipboard clipboard, WorldData worldData) {
super(URI.create(""), EmptyClipboard.INSTANCE, worldData);
holders = new ArrayList<>();
URI uri = URI.create("");
if (clipboard instanceof BlockArrayClipboard) {
FaweClipboard fc = ((BlockArrayClipboard) clipboard).IMP;
if (fc instanceof DiskOptimizedClipboard) {
uri = ((DiskOptimizedClipboard) fc).getFile().toURI();
}
}
add(uri, clipboard);
}
public void remove(URI uri) {
cached = null;
if (getUri().equals(uri)) {
for (ClipboardHolder holder : holders) holder.close();
holders.clear();
return;
}
for (int i = holders.size() - 1; i >= 0; i--) {
URIClipboardHolder holder = holders.get(i);
if (holder.contains(uri)) {
if (holder instanceof MultiClipboardHolder) {
((MultiClipboardHolder) holder).remove(uri);
} else {
holders.remove(i).close();
}
}
}
}
public void add(URIClipboardHolder holder) {
add((ClipboardHolder) holder);
}
@Override
public boolean contains(Clipboard clipboard) {
for (ClipboardHolder holder : holders) {
if (holder.contains(clipboard)) return true;
}
return false;
}
@Deprecated
public void add(ClipboardHolder holder) {
checkNotNull(holder);
if (holder instanceof URIClipboardHolder) {
holders.add((URIClipboardHolder) holder);
} else {
URI uri = URI.create(UUID.randomUUID().toString());
if (!contains(uri)) {
holders.add(new URIClipboardHolder(uri, holder.getClipboard(), holder.getWorldData()));
}
}
cached = null;
}
public void add(URI uri, Clipboard clip) {
checkNotNull(clip);
checkNotNull(uri);
add(new URIClipboardHolder(uri, clip, getWorldData()));
}
@Override
public List<Clipboard> getClipboards() {
ArrayList<Clipboard> all = new ArrayList<>();
for (ClipboardHolder holder : holders) {
all.addAll(holder.getClipboards());
}
return all;
}
@Override
public List<ClipboardHolder> getHolders() {
ArrayList<ClipboardHolder> holders = new ArrayList<>();
for (ClipboardHolder holder : holders) {
holders.addAll(holder.getHolders());
}
return holders;
}
@Override
public boolean contains(URI uri) {
if (getUri().equals(uri)) {
return true;
}
for (URIClipboardHolder uch : holders) {
if (uch.contains(uri)) return true;
}
return false;
}
@Override @Override
public Clipboard getClipboard() { public Clipboard getClipboard() {
holder = holders[PseudoRandom.random.nextInt(holders.length)]; Clipboard[] available = cached;
return holder.getClipboard(); if (available == null) {
} cached = available = getClipboards().toArray(new Clipboard[0]);
}
switch (available.length) {
case 0: return EmptyClipboard.INSTANCE;
case 1: return available[0];
}
@Override int index = PseudoRandom.random.nextInt(available.length);
public Transform getTransform() { return available[index];
return holder.getTransform();
}
@Override
public void setTransform(Transform transform) {
holder.setTransform(transform);
} }
@Override @Override
public void close() { public void close() {
cached = null;
for (ClipboardHolder holder : holders) { for (ClipboardHolder holder : holders) {
if (holder != null) holder.close(); holder.close();
} }
} }
} }

View File

@ -0,0 +1,33 @@
package com.boydti.fawe.object.clipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.registry.WorldData;
import java.net.URI;
import static com.google.common.base.Preconditions.checkNotNull;
public class URIClipboardHolder extends ClipboardHolder {
private final URI uri;
public URIClipboardHolder(URI uri, Clipboard clipboard, WorldData worldData) {
super(clipboard, worldData);
checkNotNull(uri);
this.uri = uri;
}
public boolean contains(URI uri) {
checkNotNull(uri);
return this.uri.equals(uri);
}
/**
* @deprecated If a holder has multiple sources, this will return an empty URI
* @return The original source of this clipboard (usually a file or url)
*/
@Deprecated
public URI getUri() {
return uri;
}
}

View File

@ -15,19 +15,20 @@ import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.registry.WorldData; import com.sk89q.worldedit.world.registry.WorldData;
import java.io.IOException; import java.io.IOException;
import java.io.NotSerializableException; import java.io.NotSerializableException;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
public class RandomFullClipboardPattern extends AbstractPattern { public class RandomFullClipboardPattern extends AbstractPattern {
private final Extent extent; private final Extent extent;
private final ClipboardHolder[] clipboards;
private final MutableBlockVector mutable = new MutableBlockVector(); private final MutableBlockVector mutable = new MutableBlockVector();
private final List<ClipboardHolder> clipboards;
private boolean randomRotate; private boolean randomRotate;
private boolean randomFlip; private boolean randomFlip;
private WorldData worldData; private WorldData worldData;
public RandomFullClipboardPattern(Extent extent, WorldData worldData, ClipboardHolder[] clipboards, boolean randomRotate, boolean randomFlip) { public RandomFullClipboardPattern(Extent extent, WorldData worldData, List<ClipboardHolder> clipboards, boolean randomRotate, boolean randomFlip) {
checkNotNull(clipboards); checkNotNull(clipboards);
this.clipboards = clipboards; this.clipboards = clipboards;
this.extent = extent; this.extent = extent;
@ -37,7 +38,7 @@ public class RandomFullClipboardPattern extends AbstractPattern {
@Override @Override
public boolean apply(Extent extent, Vector setPosition, Vector getPosition) throws WorldEditException { public boolean apply(Extent extent, Vector setPosition, Vector getPosition) throws WorldEditException {
ClipboardHolder holder = clipboards[PseudoRandom.random.random(clipboards.length)]; ClipboardHolder holder = clipboards.get(PseudoRandom.random.random(clipboards.size()));
AffineTransform transform = new AffineTransform(); AffineTransform transform = new AffineTransform();
if (randomRotate) { if (randomRotate) {
transform = transform.rotateY(PseudoRandom.random.random(4) * 90); transform = transform.rotateY(PseudoRandom.random.random(4) * 90);

View File

@ -67,6 +67,10 @@ public class ReflectionUtils {
} }
} }
public static <T> T as(Class<T> t, Object o) {
return t.isInstance(o) ? t.cast(o) : null;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T extends Enum<?>> T addEnum(Class<T> enumType, String enumName) { public static <T extends Enum<?>> T addEnum(Class<T> enumType, String enumName) {
@ -186,6 +190,7 @@ public class ReflectionUtils {
public static <T> List<T> getList(List<T> list) { public static <T> List<T> getList(List<T> list) {
try { try {
Class<? extends List> clazz = (Class<? extends List>) Class.forName("java.util.Collections$UnmodifiableList"); Class<? extends List> clazz = (Class<? extends List>) Class.forName("java.util.Collections$UnmodifiableList");
if (!clazz.isInstance(list)) return list;
Field m = clazz.getDeclaredField("list"); Field m = clazz.getDeclaredField("list");
m.setAccessible(true); m.setAccessible(true);
return (List<T>) m.get(list); return (List<T>) m.get(list);

View File

@ -47,6 +47,10 @@ public class Message {
return this; return this;
} }
public boolean supportsInteraction() {
return active;
}
public Message text(BBC caption, Object... args) { public Message text(BBC caption, Object... args) {
return text(caption.format(args)); return text(caption.format(args));
} }

View File

@ -80,8 +80,8 @@ public class ImageUtil {
throw new IOException("Failed to read " + url + ", please try again later"); throw new IOException("Failed to read " + url + ", please try again later");
} }
return img; return img;
} else if (arg.startsWith("file://")) { } else if (arg.startsWith("file:/")) {
arg = arg.substring(7); arg = arg.replaceFirst("file:/+", "");
File file = MainUtil.getFile(MainUtil.getFile(Fawe.imp().getDirectory(), com.boydti.fawe.config.Settings.IMP.PATHS.HEIGHTMAP), arg); File file = MainUtil.getFile(MainUtil.getFile(Fawe.imp().getDirectory(), com.boydti.fawe.config.Settings.IMP.PATHS.HEIGHTMAP), arg);
return MainUtil.readImage(file); return MainUtil.readImage(file);
} else { } else {

View File

@ -1,5 +1,6 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import com.sk89q.worldedit.function.entity.ExtentEntityCopy;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -406,4 +407,7 @@ public final class CompoundTag extends Tag {
return bldr.toString(); return bldr.toString();
} }
public static Class<?> inject() {
return CompoundTag.class;
}
} }

View File

@ -201,4 +201,7 @@ public class CompoundTagBuilder {
return new CompoundTagBuilder(); return new CompoundTagBuilder();
} }
public static Class<?> inject() {
return CompoundTagBuilder.class;
}
} }

View File

@ -419,4 +419,8 @@ public final class ListTag<T extends Tag> extends Tag {
return bldr.toString(); return bldr.toString();
} }
public static Class<?> inject() {
return ListTag.class;
}
} }

View File

@ -5,9 +5,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* Some data with a name * Some data with a name
*/ */
public class NamedData { public class NamedData<T> {
private final String name; private final String name;
private final Object data; private final T data;
/** /**
* Create a new named tag. * Create a new named tag.
@ -15,7 +15,7 @@ public class NamedData {
* @param name the name * @param name the name
* @param data the data * @param data the data
*/ */
public NamedData(String name, Object data) { public NamedData(String name, T data) {
checkNotNull(name); checkNotNull(name);
this.name = name; this.name = name;
this.data = data; this.data = data;
@ -35,7 +35,7 @@ public class NamedData {
* *
* @return the tag * @return the tag
*/ */
public Object getValue() { public T getValue() {
return data; return data;
} }
} }

View File

@ -35,4 +35,7 @@ public abstract class Tag {
return getValue(); return getValue();
} }
public static Class<?> inject() {
return Tag.class;
}
} }

View File

@ -789,8 +789,12 @@ public class LocalSession {
* @param clipboard the clipboard, or null if the clipboard is to be cleared * @param clipboard the clipboard, or null if the clipboard is to be cleared
*/ */
public void setClipboard(@Nullable ClipboardHolder clipboard) { public void setClipboard(@Nullable ClipboardHolder clipboard) {
if (this.clipboard == clipboard) return;
if (this.clipboard != null) { if (this.clipboard != null) {
this.clipboard.close(); if (clipboard == null || !clipboard.contains(this.clipboard.getClipboard())) {
this.clipboard.close();
}
} }
this.clipboard = clipboard; this.clipboard = clipboard;
} }

View File

@ -51,6 +51,7 @@ import com.boydti.fawe.object.brush.SurfaceSphereBrush;
import com.boydti.fawe.object.brush.SurfaceSpline; import com.boydti.fawe.object.brush.SurfaceSpline;
import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap; import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap;
import com.boydti.fawe.object.brush.sweep.SweepBrush; import com.boydti.fawe.object.brush.sweep.SweepBrush;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.boydti.fawe.object.mask.IdMask; import com.boydti.fawe.object.mask.IdMask;
import com.boydti.fawe.util.ColorUtil; import com.boydti.fawe.util.ColorUtil;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
@ -471,12 +472,12 @@ public class BrushCommands extends MethodCommands {
try { try {
ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), clipboard, true); MultiClipboardHolder clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), clipboard, true);
if (clipboards == null) { if (clipboards == null) {
return null; return null;
} }
return get(context) return get(context)
.setBrush(new PopulateSchem(mask, clipboards, (int) density, rotate)) .setBrush(new PopulateSchem(mask, clipboards.getHolders(), (int) density, rotate))
.setSize(radius); .setSize(radius);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);

View File

@ -437,7 +437,10 @@ public class ClipboardCommands extends MethodCommands {
@Switch('a') final boolean ignoreAirBlocks, @Switch('o') boolean atOrigin, @Switch('a') final boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
@Switch('s') boolean selectPasted) throws WorldEditException { @Switch('s') boolean selectPasted) throws WorldEditException {
ClipboardHolder holder = session.getClipboard(); ClipboardHolder holder = session.getClipboard();
System.out.println(holder);
final Clipboard clipboard = holder.getClipboard(); final Clipboard clipboard = holder.getClipboard();
System.out.println(clipboard.getDimensions());
System.out.println(clipboard.getClass());
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);
@ -500,6 +503,7 @@ public class ClipboardCommands extends MethodCommands {
BBC.COMMAND_FLIPPED.send(player); BBC.COMMAND_FLIPPED.send(player);
} }
@Deprecated // See SchematicCommands#clear
@Command( @Command(
aliases = {"clearclipboard"}, aliases = {"clearclipboard"},
usage = "", usage = "",

View File

@ -3,6 +3,7 @@ package com.sk89q.worldedit.command;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.DataAnglePattern; import com.boydti.fawe.object.DataAnglePattern;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.boydti.fawe.object.collection.RandomCollection; import com.boydti.fawe.object.collection.RandomCollection;
import com.boydti.fawe.object.pattern.AngleColorPattern; import com.boydti.fawe.object.pattern.AngleColorPattern;
import com.boydti.fawe.object.pattern.AverageColorPattern; import com.boydti.fawe.object.pattern.AverageColorPattern;
@ -59,6 +60,8 @@ import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.BaseBiome;
import java.awt.Color; import java.awt.Color;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Set; import java.util.Set;
@Command(aliases = {"patterns"}, @Command(aliases = {"patterns"},
@ -209,7 +212,7 @@ public class PatternCommands extends MethodCommands {
max = 2 max = 2
) )
public Pattern fullcopy(Player player, Extent extent, LocalSession session, @Optional("#copy") String location, @Optional("false") boolean rotate, @Optional("false") boolean flip) throws EmptyClipboardException, InputParseException, IOException { public Pattern fullcopy(Player player, Extent extent, LocalSession session, @Optional("#copy") String location, @Optional("false") boolean rotate, @Optional("false") boolean flip) throws EmptyClipboardException, InputParseException, IOException {
ClipboardHolder[] clipboards; List<ClipboardHolder> clipboards;
switch (location.toLowerCase()) { switch (location.toLowerCase()) {
case "#copy": case "#copy":
case "#clipboard": case "#clipboard":
@ -220,10 +223,11 @@ public class PatternCommands extends MethodCommands {
if (!rotate && !flip) { if (!rotate && !flip) {
return new FullClipboardPattern(extent, clipboard.getClipboard()); return new FullClipboardPattern(extent, clipboard.getClipboard());
} }
clipboards = new ClipboardHolder[]{clipboard}; clipboards = Collections.singletonList(clipboard);
break; break;
default: default:
clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), location, true); MultiClipboardHolder multi = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), location, true);
clipboards = multi != null ? multi.getHolders() : null;
break; break;
} }
if (clipboards == null) { if (clipboards == null) {

View File

@ -23,8 +23,11 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Commands; import com.boydti.fawe.config.Commands;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.clipboard.remap.ClipboardRemapper; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal3;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder; import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.boydti.fawe.object.clipboard.URIClipboardHolder;
import com.boydti.fawe.object.clipboard.remap.ClipboardRemapper;
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.chat.Message; import com.boydti.fawe.util.chat.Message;
@ -56,6 +59,8 @@ import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
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;
@ -65,10 +70,13 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static com.boydti.fawe.util.ReflectionUtils.as;
/** /**
* Commands that work with schematic files. * Commands that work with schematic files.
*/ */
@Command(aliases = {"schematic", "schem", "/schematic", "/schem"}, desc = "Commands that work with schematic files") @Command(aliases = {"schematic", "schem", "/schematic", "/schem", "clipboard", "/clipboard"}, desc = "Commands that work with schematic files")
public class SchematicCommands extends MethodCommands { public class SchematicCommands extends MethodCommands {
private static final Logger log = Logger.getLogger(SchematicCommands.class.getCanonicalName()); private static final Logger log = Logger.getLogger(SchematicCommands.class.getCanonicalName());
@ -99,10 +107,22 @@ public class SchematicCommands extends MethodCommands {
} }
try { try {
WorldData wd = player.getWorld().getWorldData(); WorldData wd = player.getWorld().getWorldData();
session.setClipboard(null);
ClipboardHolder[] all = format.loadAllFromInput(player, wd, filename, true); MultiClipboardHolder all = format.loadAllFromInput(player, wd, filename, true);
if (all != null) { if (all != null) {
MultiClipboardHolder multi = new MultiClipboardHolder(wd, all); ClipboardHolder existing = session.getExistingClipboard();
MultiClipboardHolder multi;
if (existing instanceof MultiClipboardHolder) {
multi = (MultiClipboardHolder) existing;
for (ClipboardHolder holder : all.getHolders()) {
multi.add(holder);
}
} else {
multi = all;
if (existing != null) {
multi.add(existing);
}
}
session.setClipboard(multi); session.setClipboard(multi);
BBC.SCHEMATIC_LOADED.send(player, filename); BBC.SCHEMATIC_LOADED.send(player, filename);
} }
@ -111,6 +131,57 @@ public class SchematicCommands extends MethodCommands {
} }
} }
@Command(
aliases = {"clear"},
usage = "",
desc = "Clear your clipboard",
min = 0,
max = 0
)
@CommandPermissions({"worldedit.clipboard.clear", "worldedit.schematic.clear"})
public void clear(Player player, LocalSession session) throws WorldEditException {
session.setClipboard(null);
BBC.CLIPBOARD_CLEARED.send(player);
}
@Command(
aliases = {"unload"},
usage = "[file]",
desc = "Remove a clipboard from your multi-clipboard",
min = 1,
max = 1
)
@CommandPermissions({"worldedit.clipboard.clear", "worldedit.schematic.clear"})
public void unload(Player player, LocalSession session, String fileName) throws WorldEditException {
URI uri;
if (fileName.startsWith("file:/") || fileName.startsWith("http://") || fileName.startsWith("https://")) {
uri = URI.create(fileName);
} else {
final LocalConfiguration config = this.worldEdit.getConfiguration();
File working = this.worldEdit.getWorkingDirectoryFile(config.saveDir);
File root = Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS ? new File(working, player.getUniqueId().toString()) : working;
uri = new File(root, fileName).toURI();
}
boolean removed = false;
ClipboardHolder clipboard = session.getClipboard();
if (clipboard instanceof URIClipboardHolder) {
URIClipboardHolder identifiable = (URIClipboardHolder) clipboard;
if (identifiable.contains(uri)) {
if (identifiable instanceof MultiClipboardHolder) {
MultiClipboardHolder multi = (MultiClipboardHolder) identifiable;
multi.remove(uri);
if (multi.getHolders().isEmpty()) session.setClipboard(null);
} else {
session.setClipboard(null);
}
BBC.CLIPBOARD_CLEARED.send(player);
return;
}
}
BBC.CLIPBOARD_URI_NOT_FOUND.send(player, fileName);
}
@Command( @Command(
aliases = {"remap"}, aliases = {"remap"},
help = "Remap a clipboard between MCPE/PC values\n", help = "Remap a clipboard between MCPE/PC values\n",
@ -119,12 +190,15 @@ public class SchematicCommands extends MethodCommands {
@Deprecated @Deprecated
@CommandPermissions({"worldedit.schematic.remap"}) @CommandPermissions({"worldedit.schematic.remap"})
public void remap(final Player player, final LocalSession session) throws WorldEditException { public void remap(final Player player, final LocalSession session) throws WorldEditException {
ClipboardHolder holder = session.getClipboard(); ClipboardRemapper remapper;
Clipboard clipboard = holder.getClipboard();
if (Fawe.imp().getPlatform().equalsIgnoreCase("nukkit")) { if (Fawe.imp().getPlatform().equalsIgnoreCase("nukkit")) {
new ClipboardRemapper(ClipboardRemapper.RemapPlatform.PC, ClipboardRemapper.RemapPlatform.PE).apply(clipboard); remapper = new ClipboardRemapper(ClipboardRemapper.RemapPlatform.PC, ClipboardRemapper.RemapPlatform.PE);
} else { } else {
new ClipboardRemapper(ClipboardRemapper.RemapPlatform.PE, ClipboardRemapper.RemapPlatform.PC).apply(clipboard); remapper = new ClipboardRemapper(ClipboardRemapper.RemapPlatform.PE, ClipboardRemapper.RemapPlatform.PC);
}
for (Clipboard clip : session.getClipboard().getClipboards()) {
remapper.apply(clip);
} }
player.print(BBC.getPrefix() + "Remapped schematic"); player.print(BBC.getPrefix() + "Remapped schematic");
} }
@ -141,6 +215,7 @@ public class SchematicCommands extends MethodCommands {
} }
InputStream in = null; InputStream in = null;
try { try {
URI uri;
if (filename.startsWith("url:")) { if (filename.startsWith("url:")) {
if (!player.hasPermission("worldedit.schematic.upload")) { if (!player.hasPermission("worldedit.schematic.upload")) {
BBC.NO_PERM.send(player, "worldedit.schematic.upload"); BBC.NO_PERM.send(player, "worldedit.schematic.upload");
@ -151,6 +226,7 @@ public class SchematicCommands extends MethodCommands {
URL url = new URL(base, "uploads/" + uuid + ".schematic"); URL url = new URL(base, "uploads/" + uuid + ".schematic");
ReadableByteChannel rbc = Channels.newChannel(url.openStream()); ReadableByteChannel rbc = Channels.newChannel(url.openStream());
in = Channels.newInputStream(rbc); in = Channels.newInputStream(rbc);
uri = url.toURI();
} else { } else {
if (!player.hasPermission("worldedit.schematic.load") && !player.hasPermission("worldedit.clipboard.load")) { if (!player.hasPermission("worldedit.schematic.load") && !player.hasPermission("worldedit.clipboard.load")) {
BBC.NO_PERM.send(player, "worldedit.clipboard.load"); BBC.NO_PERM.send(player, "worldedit.clipboard.load");
@ -195,6 +271,8 @@ public class SchematicCommands extends MethodCommands {
return; return;
} }
in = new FileInputStream(f); in = new FileInputStream(f);
uri = f.toURI();
} }
final ClipboardReader reader = format.getReader(in); final ClipboardReader reader = format.getReader(in);
final WorldData worldData = player.getWorld().getWorldData(); final WorldData worldData = player.getWorld().getWorldData();
@ -207,11 +285,11 @@ public class SchematicCommands extends MethodCommands {
} else { } else {
clipboard = reader.read(player.getWorld().getWorldData()); clipboard = reader.read(player.getWorld().getWorldData());
} }
session.setClipboard(new ClipboardHolder(clipboard, worldData)); session.setClipboard(new URIClipboardHolder(uri, clipboard, worldData));
BBC.SCHEMATIC_LOADED.send(player, filename); BBC.SCHEMATIC_LOADED.send(player, filename);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
player.printError("Unknown filename: " + filename); player.printError("Unknown filename: " + filename);
} catch (IOException e) { } catch (URISyntaxException | IOException e) {
player.printError("File could not be read or it does not exist: " + e.getMessage()); player.printError("File could not be read or it does not exist: " + e.getMessage());
log.log(Level.WARNING, "Failed to load a saved clipboard", e); log.log(Level.WARNING, "Failed to load a saved clipboard", e);
} finally { } finally {
@ -345,12 +423,10 @@ public class SchematicCommands extends MethodCommands {
m.send(actor); m.send(actor);
} }
// schem list all|mine|global page
@Command( @Command(
aliases = {"list", "all", "ls"}, aliases = {"list", "ls", "all"},
desc = "List saved schematics", desc = "List saved schematics",
usage = "[mine|<filter>] [page=1]", usage = "[global|mine|<filter>] [page=1]",
min = 0, min = 0,
max = -1, max = -1,
flags = "dnp", flags = "dnp",
@ -359,10 +435,69 @@ public class SchematicCommands extends MethodCommands {
" -f <format> restricts by format\n" " -f <format> restricts by format\n"
) )
@CommandPermissions("worldedit.schematic.list") @CommandPermissions("worldedit.schematic.list")
public void list(Actor actor, CommandContext args, @Switch('p') @Optional("1") int page, @Switch('f') String formatName) throws WorldEditException { public void list(FawePlayer fp, Actor actor, CommandContext args, @Switch('p') @Optional("1") int page, @Switch('f') String formatName) throws WorldEditException {
String baseCmd = Commands.getAlias(SchematicCommands.class, "schematic") + " " + Commands.getAlias(SchematicCommands.class, "load"); if (args.argsLength() == 0) {
File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().saveDir); BBC.COMMAND_SYNTAX.send(fp, getCommand().usage());
UtilityCommands.list(dir, actor, args, page, formatName, Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS, baseCmd); return;
}
LocalConfiguration config = worldEdit.getConfiguration();
String prefix = config.noDoubleSlash ? "" : "/";
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
String schemCmd = prefix + Commands.getAlias(SchematicCommands.class, "schematic");
String loadSingle = schemCmd + " " + Commands.getAlias(SchematicCommands.class, "load");
String loadMulti = schemCmd + " " + Commands.getAlias(SchematicCommands.class, "loadall");
String unload = schemCmd + " " + Commands.getAlias(SchematicCommands.class, "unload");
String delete = schemCmd + " " + Commands.getAlias(SchematicCommands.class, "delete");
String list = schemCmd + " " + Commands.getAlias(SchematicCommands.class, "list");
URIClipboardHolder multi = as(URIClipboardHolder.class, fp.getSession().getExistingClipboard());
UtilityCommands.list(dir, actor, args, page, formatName, Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS, new RunnableVal3<Message, URI, String>() {
@Override
public void run(Message msg, URI uri, String relFilePath) {
boolean isDir = false;
boolean loaded = multi != null && multi.contains(uri);
String name = relFilePath;
String color;
String uriStr = uri.toString();
if (uriStr.startsWith("file:/")) {
File file = new File(uri.getPath());
name = file.getName();
if (file.isDirectory()) {
isDir = true;
color = "&6";
} else {
color = "&a";
}
} else if (uriStr.startsWith("http://") || uriStr.startsWith("https://")) {
// url
color = "&9";
} else {
color = "&7";
}
msg.text("&8 - ");
if (msg.supportsInteraction()) {
if (loaded) {
msg.text("&7[&c-&7]").command(unload + " " + relFilePath).tooltip("Unload this schematic");
} else {
msg.text("&7[&a+&7]").command(loadMulti + " " + relFilePath).tooltip("(WIP) Append this to your clipboard");
}
if (!isDir) msg.text("&7[&cX&7]").suggestTip("/" + delete + " " + relFilePath);
msg.text(color + relFilePath);
if (isDir) {
msg.cmdTip(list + " " + args.getJoinedStrings(0) + " " + relFilePath);
} else {
msg.cmdTip(loadSingle + " " + relFilePath);
}
} else {
msg.text(color).text(name);
}
}
});
} }
public static Class<?> inject() { public static Class<?> inject() {

View File

@ -21,6 +21,7 @@ package com.sk89q.worldedit.command;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.clipboard.URIClipboardHolder;
import com.boydti.fawe.object.mask.IdMask; import com.boydti.fawe.object.mask.IdMask;
import com.boydti.fawe.object.regions.selector.FuzzyRegionSelector; import com.boydti.fawe.object.regions.selector.FuzzyRegionSelector;
import com.boydti.fawe.object.regions.selector.PolyhedralRegionSelector; import com.boydti.fawe.object.regions.selector.PolyhedralRegionSelector;
@ -62,6 +63,10 @@ import com.sk89q.worldedit.util.formatting.StyledFragment;
import com.sk89q.worldedit.util.formatting.component.CommandListBox; import com.sk89q.worldedit.util.formatting.component.CommandListBox;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.storage.ChunkStore; import com.sk89q.worldedit.world.storage.ChunkStore;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -578,16 +583,44 @@ public class SelectionCommands {
@CommandPermissions("worldedit.selection.size") @CommandPermissions("worldedit.selection.size")
public void size(Player player, LocalSession session, CommandContext args) throws WorldEditException { public void size(Player player, LocalSession session, CommandContext args) throws WorldEditException {
if (args.hasFlag('c')) { if (args.hasFlag('c')) {
ClipboardHolder holder = session.getClipboard(); ClipboardHolder root = session.getClipboard();
Clipboard clipboard = holder.getClipboard(); // Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion(); int index = 0;
Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint()); for (ClipboardHolder holder : root.getHolders()) {
Vector origin = clipboard.getOrigin(); Clipboard clipboard = holder.getClipboard();
String name;
if (holder instanceof URIClipboardHolder) {
URI uri = ((URIClipboardHolder) holder).getUri();
if (uri.toString().startsWith("file:/")) {
name = new File(uri.getPath()).getName();
} else {
name = uri.getFragment();
}
} else {
name = Integer.toString(index);
}
player.print(BBC.getPrefix() + "Cuboid dimensions (max - min): " + size); Region region = clipboard.getRegion();
player.print(BBC.getPrefix() + "Offset: " + origin); Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(Vector.ONE);
player.print(BBC.getPrefix() + "Cuboid distance: " + size.distance(Vector.ONE)); Vector origin = clipboard.getOrigin();
player.print(BBC.getPrefix() + "# of blocks: " + (int) (size.getX() * size.getY() * size.getZ()));
String sizeStr = size.getBlockX() + "*" + size.getBlockY() + "*" + size.getBlockZ();
String originStr = origin.getBlockX() + "," + origin.getBlockY() + "," + origin.getBlockZ();
long numBlocks = ((long) size.getBlockX() * size.getBlockY() * size.getBlockZ());
String msg = String.format("%1$s: %2$s @ %3$s (%4$d blocks)", name, sizeStr, originStr, numBlocks);
player.print(BBC.getPrefix() + msg);
index++;
}
// player.print(BBC.getPrefix() + "Cuboid dimensions (max - min): " + size);
// player.print(BBC.getPrefix() + "Offset: " + origin);
// player.print(BBC.getPrefix() + "Cuboid distance: " + size.distance(Vector.ONE));
// player.print(BBC.getPrefix() + "# of blocks: " + (int) (size.getX() * size.getY() * size.getZ()));
return; return;
} }

View File

@ -19,11 +19,13 @@
package com.sk89q.worldedit.command; package com.sk89q.worldedit.command;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI; import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Commands; import com.boydti.fawe.config.Commands;
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.RunnableVal3;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.StringMan; import com.boydti.fawe.util.StringMan;
import com.boydti.fawe.util.chat.Message; import com.boydti.fawe.util.chat.Message;
@ -75,6 +77,7 @@ import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.util.command.parametric.ParametricCallable; import com.sk89q.worldedit.util.command.parametric.ParametricCallable;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import java.io.File; import java.io.File;
import java.io.FileFilter;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -87,7 +90,13 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.*; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -632,43 +641,98 @@ public class UtilityCommands extends MethodCommands {
} }
public static void list(File dir, Actor actor, CommandContext args, @Range(min = 0) int page, String formatName, boolean playerFolder, String onClickCmd) { public static void list(File dir, Actor actor, CommandContext args, @Range(min = 0) int page, String formatName, boolean playerFolder, String onClickCmd) {
List<File> fileList = new ArrayList<>(); list(dir, actor, args, page, formatName, playerFolder, new RunnableVal3<Message, URI, String>() {
@Override
public void run(Message m, URI uri, String fileName) {
m.text(BBC.SCHEMATIC_LIST_ELEM, fileName, "");
if (onClickCmd != null) m.cmdTip(onClickCmd + " " + fileName);
}
});
}
public static void list(File dir, Actor actor, CommandContext args, @Range(min = 0) int page, String formatName, boolean playerFolder, RunnableVal3<Message, URI, String> eachMsg) {
int len = args.argsLength(); int len = args.argsLength();
List<String> filters = new ArrayList<>(); List<String> filters = new ArrayList<>();
boolean mine = false;
String dirFilter = File.separator;
boolean listMine = false;
boolean listGlobal = false;
if (len > 0) { if (len > 0) {
int max = len; int max = len;
if (MathMan.isInteger(args.getString(len - 1))) { if (MathMan.isInteger(args.getString(len - 1))) {
page = args.getInteger(--len); page = args.getInteger(--len);
} }
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
switch (args.getString(i).toLowerCase()) { String arg = args.getString(i);
switch (arg.toLowerCase()) {
case "me": case "me":
case "mine": case "mine":
mine = true; case "local":
case "private":
listMine = true;
break;
case "public":
case "global":
listGlobal = true;
break;
case "all":
listMine = true;
listGlobal = true;
break; break;
default: default:
filters.add(args.getString(i)); if (arg.endsWith("/") || arg.endsWith(File.separator)) {
arg = arg.replace("/", File.separator);
String newDirFilter = dirFilter + arg;
boolean exists = new File(dir, newDirFilter).exists() || playerFolder && new File(dir, actor.getUniqueId() + newDirFilter).exists();
if (!exists) {
arg = arg.substring(0, arg.length() - File.separator.length());
if (arg.length() > 3 && arg.length() <= 16) {
UUID fromName = Fawe.imp().getUUID(arg);
if (fromName != null) {
newDirFilter = dirFilter + fromName + File.separator;
listGlobal = true;
}
}
}
dirFilter = newDirFilter;
}
else {
filters.add(arg);
}
break; break;
} }
} }
} }
if (!listMine && !listGlobal) {
listMine = true;
}
FileFilter ignoreUUIDs = f -> {
try {
if (f.isDirectory()) {
UUID uuid = UUID.fromString(f.getName());
return false;
}
} catch (IllegalArgumentException exception) {}
return true;
};
List<File> fileList = new ArrayList<>();
if (playerFolder) { if (playerFolder) {
File playerDir = new File(dir, actor.getUniqueId().toString()); if (listMine) {
if (playerDir.exists()) { File playerDir = new File(dir, actor.getUniqueId() + dirFilter);
fileList.addAll(allFiles(playerDir, true)); if (playerDir.exists()) fileList.addAll(allFiles(playerDir.listFiles(), false));
} }
if (!mine) { if (listGlobal) {
fileList.addAll(allFiles(dir, false)); File rel = new File(dir, dirFilter);
if (rel.exists()) fileList.addAll(allFiles(rel.listFiles(ignoreUUIDs), false));
} }
} else { } else {
fileList.addAll(allFiles(dir, true)); File rel = new File(dir, dirFilter);
} if (rel.exists()) fileList.addAll(allFiles(rel.listFiles(), false));
if (!filters.isEmpty()) {
for (String filter : filters) {
fileList.removeIf(file -> !file.getPath().contains(filter));
}
} }
if (fileList.isEmpty()) { if (fileList.isEmpty()) {
BBC.SCHEMATIC_NONE.send(actor); BBC.SCHEMATIC_NONE.send(actor);
return; return;
@ -680,10 +744,10 @@ public class UtilityCommands extends MethodCommands {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
File[] files = new File[fileList.size()]; fileList = filter(fileList, filters);
fileList.toArray(files);
final int perPage = actor instanceof Player ? 12 : 20; // More pages for console final int perPage = actor instanceof Player ? 12 : 20; // More pages for console
int pageCount = (files.length + perPage - 1) / perPage; int pageCount = (fileList.size() + perPage - 1) / perPage;
if (page < 1) { if (page < 1) {
BBC.SCHEMATIC_PAGE.send(actor, ">0"); BBC.SCHEMATIC_PAGE.send(actor, ">0");
return; return;
@ -695,9 +759,12 @@ public class UtilityCommands extends MethodCommands {
final int sortType = args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0; final int sortType = args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0;
// cleanup file list // cleanup file list
Arrays.sort(files, new Comparator<File>() { Collections.sort(fileList, new Comparator<File>() {
@Override @Override
public int compare(File f1, File f2) { public int compare(File f1, File f2) {
boolean dir1 = f1.isDirectory();
boolean dir2 = f2.isDirectory();
if (dir1 != dir2) return dir1 ? -1 : 1;
int res; int res;
if (sortType == 0) { // use name by default if (sortType == 0) { // use name by default
int p = f1.getParent().compareTo(f2.getParent()); int p = f1.getParent().compareTo(f2.getParent());
@ -714,10 +781,9 @@ public class UtilityCommands extends MethodCommands {
} }
}); });
List<String[]> schematics = listFiles(dir, files, playerFolder ? actor.getUniqueId() : null);
int offset = (page - 1) * perPage; int offset = (page - 1) * perPage;
int limit = Math.min(offset + perPage, schematics.size()); int limit = Math.min(offset + perPage, fileList.size());
String fullArgs = (String) args.getLocals().get("arguments"); String fullArgs = (String) args.getLocals().get("arguments");
String baseCmd = null; String baseCmd = null;
@ -726,12 +792,11 @@ public class UtilityCommands extends MethodCommands {
} }
Message m = new Message(BBC.SCHEMATIC_LIST, page, pageCount); Message m = new Message(BBC.SCHEMATIC_LIST, page, pageCount);
UUID uuid = playerFolder ? actor.getUniqueId() : null;
for (int i = offset; i < limit; i++) { for (int i = offset; i < limit; i++) {
String[] fileinfo = schematics.get(i); m.newline();
String fileName = fileinfo[0]; File file = fileList.get(i);
String fileFormat = fileinfo[1]; eachMsg.run(m, file.toURI(), getPath(dir, file, uuid));
m.newline().text(BBC.SCHEMATIC_LIST_ELEM, fileName, fileFormat);
if (onClickCmd != null) m.cmdTip(onClickCmd + " " + fileName);
} }
if (baseCmd != null) { if (baseCmd != null) {
m.newline().paginate(baseCmd, page, pageCount); m.newline().paginate(baseCmd, page, pageCount);
@ -739,16 +804,57 @@ public class UtilityCommands extends MethodCommands {
m.send(actor); m.send(actor);
} }
private static List<File> allFiles(File root, boolean recursive) { private static List<File> filter(List<File> fileList, List<String> filters) {
File[] files = root.listFiles();
if (files == null) return new ArrayList<>(); String[] normalizedNames = new String[fileList.size()];
for (int i = 0; i < fileList.size(); i++) {
String normalized = fileList.get(i).getName().toLowerCase();
if (normalized.startsWith("../")) normalized = normalized.substring(3);
normalizedNames[i] = normalized.replace("/", File.separator);
}
for (String filter : filters) {
if (fileList.isEmpty()) return fileList;
String lowerFilter = filter.toLowerCase().replace("/", File.separator);
List<File> newList = new ArrayList<>();
for (int i = 0; i < normalizedNames.length; i++) {
if (normalizedNames[i].startsWith(lowerFilter)) newList.add(fileList.get(i));
}
if (newList.isEmpty()) {
for (int i = 0; i < normalizedNames.length; i++) {
if (normalizedNames[i].contains(lowerFilter)) newList.add(fileList.get(i));
}
if (newList.isEmpty()) {
String checkName = filter.replace("\\", "/").split("/")[0];
if (checkName.length() > 3 && checkName.length() <= 16) {
UUID fromName = Fawe.imp().getUUID(checkName);
if (fromName != null) {
lowerFilter = filter.replaceFirst(checkName, fromName.toString()).toLowerCase();
for (int i = 0; i < normalizedNames.length; i++) {
if (normalizedNames[i].startsWith(lowerFilter)) newList.add(fileList.get(i));
}
}
}
}
}
fileList = newList;
}
return fileList;
}
private static List<File> allFiles(File[] files, boolean recursive) {
if (files == null || files.length == 0) return Arrays.asList();
List<File> fileList = new ArrayList<File>(); List<File> fileList = new ArrayList<File>();
for (File f : files) { for (File f : files) {
if (f.isDirectory()) { if (f.isDirectory()) {
if (recursive) { if (recursive) {
List<File> subFiles = allFiles(f, recursive); List<File> subFiles = allFiles(f.listFiles(), recursive);
if (subFiles == null || subFiles.isEmpty()) continue; // empty subdir if (subFiles == null || subFiles.isEmpty()) continue; // empty subdir
fileList.addAll(subFiles); fileList.addAll(subFiles);
} else {
fileList.add(f);
} }
} else { } else {
fileList.add(f); fileList.add(f);
@ -757,34 +863,23 @@ public class UtilityCommands extends MethodCommands {
return fileList; return fileList;
} }
private static List<String[]> listFiles(File root, File[] files, UUID uuid) { private static String getPath(File root, File file, UUID uuid) {
// List Elem [ File Name, Format Name ]
File dir; File dir;
if (uuid != null) { if (uuid != null) {
dir = new File(root, uuid.toString()); dir = new File(root, uuid.toString());
} else { } else {
dir = root; dir = root;
} }
List<String[]> result = new ArrayList<>();
for (File file : files) { ClipboardFormat format = ClipboardFormat.findByFile(file);
ClipboardFormat format = ClipboardFormat.findByFile(file); URI relative = dir.toURI().relativize(file.toURI());
URI relative = dir.toURI().relativize(file.toURI()); StringBuilder name = new StringBuilder();
String name = ""; if (relative.isAbsolute()) {
if (relative.isAbsolute()) { relative = root.toURI().relativize(file.toURI());
relative = root.toURI().relativize(file.toURI()); name.append("../");
name += "../";
}
name += relative.getPath();
String formatName;
if (format == null) {
String[] split = file.getName().split("\\.");
formatName = split.length > 1 ? split[split.length - 1].toUpperCase() : "Unknown";
} else {
formatName = format.toString();
}
result.add(new String[] {name, formatName} );
} }
return result; name.append(relative.getPath());
return name.toString();
} }
public static void help(CommandContext args, WorldEdit we, Actor actor) { public static void help(CommandContext args, WorldEdit we, Actor actor) {

View File

@ -207,7 +207,6 @@ public class WorldEditCommands {
min = 0, min = 0,
max = -1 max = -1
) )
@CommandPermissions("worldedit.help")
public void help(Actor actor, CommandContext args) throws WorldEditException { public void help(Actor actor, CommandContext args) throws WorldEditException {
UtilityCommands.help(args, we, actor); UtilityCommands.help(args, we, actor);
} }

View File

@ -152,7 +152,7 @@ public interface Extent extends InputExtent, OutputExtent {
} }
} }
default public void addSchems(Region region, Mask mask, WorldData worldData, ClipboardHolder[] clipboards, int rarity, boolean rotate) throws WorldEditException { default public void addSchems(Region region, Mask mask, WorldData worldData, List<ClipboardHolder> clipboards, int rarity, boolean rotate) throws WorldEditException {
spawnResource(region, new SchemGen(mask, this, worldData, clipboards, rotate), rarity, 1); spawnResource(region, new SchemGen(mask, this, worldData, clipboards, rotate), rarity, 1);
} }

View File

@ -29,6 +29,8 @@ 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.clipboard.LazyClipboardHolder;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.boydti.fawe.object.clipboard.URIClipboardHolder;
import com.boydti.fawe.object.io.FastByteArrayOutputStream; 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;
@ -50,7 +52,6 @@ import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.platform.Actor; 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 com.sk89q.worldedit.world.registry.WorldData;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
@ -61,6 +62,8 @@ 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.URI;
import java.net.URISyntaxException;
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;
@ -315,7 +318,7 @@ public enum ClipboardFormat {
}); });
} }
public ClipboardHolder[] loadAllFromInput(Actor player, WorldData worldData, String input, boolean message) throws IOException { public MultiClipboardHolder loadAllFromInput(Actor player, WorldData worldData, String input, boolean message) throws IOException {
checkNotNull(player); checkNotNull(player);
checkNotNull(input); checkNotNull(input);
WorldEdit worldEdit = WorldEdit.getInstance(); WorldEdit worldEdit = WorldEdit.getInstance();
@ -327,7 +330,7 @@ public enum ClipboardFormat {
if (message) BBC.WEB_UNAUTHORIZED.send(player, url); if (message) BBC.WEB_UNAUTHORIZED.send(player, url);
return null; return null;
} }
ClipboardHolder[] clipboards = loadAllFromUrl(url, worldData); MultiClipboardHolder clipboards = loadAllFromUrl(url, worldData);
return clipboards; return clipboards;
} else { } else {
if (input.contains("../") && !player.hasPermission("worldedit.schematic.load.other")) { if (input.contains("../") && !player.hasPermission("worldedit.schematic.load.other")) {
@ -353,18 +356,19 @@ public enum ClipboardFormat {
} }
if (!dir.isDirectory()) { if (!dir.isDirectory()) {
ByteSource source = Files.asByteSource(dir); ByteSource source = Files.asByteSource(dir);
return new ClipboardHolder[]{new LazyClipboardHolder(source, this, worldData, null)}; URI uri = dir.toURI();
return new MultiClipboardHolder(uri, worldData, new LazyClipboardHolder(dir.toURI(), source, this, worldData, null));
} }
ClipboardHolder[] clipboards = loadAllFromDirectory(dir, worldData); URIClipboardHolder[] clipboards = loadAllFromDirectory(dir, worldData);
if (clipboards.length < 1) { if (clipboards.length < 1) {
if (message) BBC.SCHEMATIC_NOT_FOUND.send(player, input); if (message) BBC.SCHEMATIC_NOT_FOUND.send(player, input);
return null; return null;
} }
return clipboards; return new MultiClipboardHolder(dir.toURI(), worldData, clipboards);
} }
} }
public ClipboardHolder[] loadAllFromDirectory(File dir, WorldData worldData) { public URIClipboardHolder[] loadAllFromDirectory(File dir, WorldData worldData) {
if (worldData == null) { if (worldData == null) {
try { try {
worldData = WorldEdit.getInstance().getServer().getWorlds().get(0).getWorldData(); worldData = WorldEdit.getInstance().getServer().getWorlds().get(0).getWorldData();
@ -381,12 +385,12 @@ public enum ClipboardFormat {
for (int i = 0; i < files.length; i++) { for (int i = 0; i < files.length; i++) {
File file = files[i]; File file = files[i];
ByteSource source = Files.asByteSource(file); ByteSource source = Files.asByteSource(file);
clipboards[i] = new LazyClipboardHolder(source, this, worldData, null); clipboards[i] = new LazyClipboardHolder(file.toURI(), source, this, worldData, null);
} }
return clipboards; return clipboards;
} }
public ClipboardHolder[] loadAllFromUrl(URL url, WorldData worldData) throws IOException { public MultiClipboardHolder loadAllFromUrl(URL url, WorldData worldData) throws IOException {
List<LazyClipboardHolder> clipboards = new ArrayList<>(); List<LazyClipboardHolder> clipboards = new ArrayList<>();
try (ReadableByteChannel rbc = Channels.newChannel(url.openStream())) { try (ReadableByteChannel rbc = Channels.newChannel(url.openStream())) {
try (InputStream in = Channels.newInputStream(rbc)) { try (InputStream in = Channels.newInputStream(rbc)) {
@ -402,14 +406,23 @@ public enum ClipboardFormat {
} }
byte[] array = out.toByteArray(); byte[] array = out.toByteArray();
ByteSource source = ByteSource.wrap(array); ByteSource source = ByteSource.wrap(array);
LazyClipboardHolder clipboard = new LazyClipboardHolder(source, this, worldData, null); LazyClipboardHolder clipboard = new LazyClipboardHolder(url.toURI(), source, this, worldData, null);
clipboards.add(clipboard); clipboards.add(clipboard);
} }
} }
} catch (URISyntaxException e) {
e.printStackTrace();
} }
} }
} }
return clipboards.toArray(new LazyClipboardHolder[clipboards.size()]); LazyClipboardHolder[] arr = clipboards.toArray(new LazyClipboardHolder[clipboards.size()]);
try {
MultiClipboardHolder multi = new MultiClipboardHolder(url.toURI(), worldData);
for (LazyClipboardHolder h : arr) multi.add(h);
return multi;
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
} }
private void write(OutputStream value, Clipboard clipboard) { private void write(OutputStream value, Clipboard clipboard) {

View File

@ -1,6 +1,5 @@
package com.sk89q.worldedit.internal.expression.runtime; package com.sk89q.worldedit.internal.expression.runtime;
import com.sk89q.worldedit.command.UtilityCommands;
import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.parser.ParserException; import com.sk89q.worldedit.internal.expression.parser.ParserException;
@ -31,7 +30,7 @@ public class For extends Node {
} }
if(Thread.currentThread().isInterrupted()){ if(Thread.currentThread().isInterrupted()){
throw new EvaluationException(this.getPosition(), "Thread has been interuppted."); throw new EvaluationException(this.getPosition(), "Thread has been interrupted.");
} }
++iterations; ++iterations;

View File

@ -0,0 +1,107 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.internal.expression.runtime;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.parser.ParserException;
/**
* A simple-style for loop.
*/
public class SimpleFor extends Node {
LValue counter;
RValue first;
RValue last;
RValue body;
public SimpleFor(int position, LValue counter, RValue first, RValue last, RValue body) {
super(position);
this.counter = counter;
this.first = first;
this.last = last;
this.body = body;
}
@Override
public double getValue() throws EvaluationException {
int iterations = 0;
double ret = 0.0;
double firstValue = first.getValue();
double lastValue = last.getValue();
for (double i = firstValue; i <= lastValue; ++i) {
if (iterations > 256) {
throw new EvaluationException(getPosition(), "Loop exceeded 256 iterations.");
}
if(Thread.currentThread().isInterrupted()){
throw new EvaluationException(this.getPosition(), "Thread has been interrupted.");
}
++iterations;
try {
counter.assign(i);
ret = body.getValue();
} catch (BreakException e) {
if (e.doContinue) {
//noinspection UnnecessaryContinue
continue;
} else {
break;
}
}
}
return ret;
}
@Override
public char id() {
return 'S';
}
@Override
public String toString() {
return "for (" + counter + " = " + first + ", " + last + ") { " + body + " }";
}
@Override
public RValue optimize() throws EvaluationException {
// TODO: unroll small loops into Sequences
return new SimpleFor(getPosition(), counter.optimize(), first.optimize(), last.optimize(), body.optimize());
}
@Override
public RValue bindVariables(Expression expression, boolean preferLValue) throws ParserException {
counter = counter.bindVariables(expression, true);
first = first.bindVariables(expression, false);
last = last.bindVariables(expression, false);
body = body.bindVariables(expression, false);
return this;
}
public static Class<SimpleFor> inject() {
return SimpleFor.class;
}
}

View File

@ -0,0 +1,136 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.internal.expression.runtime;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.parser.ParserException;
/**
* A while loop.
*/
public class While extends Node {
RValue condition;
RValue body;
boolean footChecked;
public While(int position, RValue condition, RValue body, boolean footChecked) {
super(position);
this.condition = condition;
this.body = body;
this.footChecked = footChecked;
}
@Override
public double getValue() throws EvaluationException {
int iterations = 0;
double ret = 0.0;
if (footChecked) {
do {
if (iterations > 256) {
throw new EvaluationException(getPosition(), "Loop exceeded 256 iterations.");
}
if(Thread.currentThread().isInterrupted()){
throw new EvaluationException(this.getPosition(), "Thread has been interrupted.");
}
++iterations;
try {
ret = body.getValue();
} catch (BreakException e) {
if (e.doContinue) {
continue;
} else {
break;
}
}
} while (condition.getValue() > 0.0);
} else {
while (condition.getValue() > 0.0) {
if (iterations > 256) {
throw new EvaluationException(getPosition(), "Loop exceeded 256 iterations.");
}
if(Thread.currentThread().isInterrupted()){
throw new EvaluationException(this.getPosition(), "Thread has been interrupted.");
}
++iterations;
try {
ret = body.getValue();
} catch (BreakException e) {
if (e.doContinue) {
//noinspection UnnecessaryContinue
continue;
} else {
break;
}
}
}
}
return ret;
}
@Override
public char id() {
return 'w';
}
@Override
public String toString() {
if (footChecked) {
return "do { " + body + " } while (" + condition + ")";
} else {
return "while (" + condition + ") { " + body + " }";
}
}
@Override
public RValue optimize() throws EvaluationException {
final RValue newCondition = condition.optimize();
if (newCondition instanceof Constant && newCondition.getValue() <= 0) {
// If the condition is always false, the loop can be flattened.
if (footChecked) {
// Foot-checked loops run at least once.
return body.optimize();
} else {
// Loops that never run always return 0.0.
return new Constant(getPosition(), 0.0);
}
}
return new While(getPosition(), newCondition, body.optimize(), footChecked);
}
@Override
public RValue bindVariables(Expression expression, boolean preferLValue) throws ParserException {
condition = condition.bindVariables(expression, false);
body = body.bindVariables(expression, false);
return this;
}
public static Class<While> inject() {
return While.class;
}
}

View File

@ -25,6 +25,8 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.transform.Identity; import com.sk89q.worldedit.math.transform.Identity;
import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.world.registry.WorldData; import com.sk89q.worldedit.world.registry.WorldData;
import java.util.Collections;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -33,7 +35,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
* Holds the clipboard and the current transform on the clipboard. * Holds the clipboard and the current transform on the clipboard.
*/ */
public class ClipboardHolder { public class ClipboardHolder {
private final WorldData worldData; private final WorldData worldData;
private Clipboard clipboard; private Clipboard clipboard;
private Transform transform = new Identity(); private Transform transform = new Identity();
@ -70,12 +71,36 @@ public class ClipboardHolder {
* If there is a transformation applied, the returned clipboard will * If there is a transformation applied, the returned clipboard will
* not contain its effect. * not contain its effect.
* *
* @deprecated FAWE supports multiple loaded schematics {@link #getClipboards()}
* @return the clipboard * @return the clipboard
*/ */
@Deprecated
public Clipboard getClipboard() { public Clipboard getClipboard() {
return clipboard; return clipboard;
} }
/**
* Get all currently held clipboards
* @return
*/
public List<Clipboard> getClipboards() {
return Collections.singletonList(getClipboard());
}
public boolean contains(Clipboard clipboard) {
return this.clipboard == clipboard;
}
/**
* Get all end ClipboardHolders<br/>
* - Usually this will return itself.<br/>
* - If this is a multi clipboard, it will return the children
* @return Set of end ClipboardHolders
*/
public List<ClipboardHolder> getHolders() {
return Collections.singletonList(this);
}
/** /**
* Set the transform. * Set the transform.
* *

View File

@ -164,7 +164,6 @@ public class LevelDBToMCAFile extends MapConverter {
case PendingTicks: case PendingTicks:
break; break;
case BlockExtraData: case BlockExtraData:
System.out.println("EXTRA " + chunk.getX() + "," + chunk.getZ());
break; break;
case LegacyTerrain: case LegacyTerrain:
case Data2DLegacy: case Data2DLegacy:

View File

@ -1,3 +1,3 @@
rootProject.name = 'FastAsyncWorldEdit' rootProject.name = 'FastAsyncWorldEdit'
include 'core', 'bukkit', 'favs', 'nukkit'//, 'forge1710', 'forge189', 'forge194', 'forge110', 'forge111', 'sponge', 'forge112', 'sponge111' include 'core', 'bukkit', 'favs', 'nukkit', 'forge1710', 'forge189', 'forge194', 'forge110', 'forge111', 'sponge', 'forge112', 'sponge111'

View File

@ -22,7 +22,7 @@ buildscript {
} }
plugins { plugins {
id 'org.spongepowered.plugin' version '0.6' id 'org.spongepowered.plugin' version '0.8.1'
} }
apply plugin: 'net.minecrell.vanilla.server.library' apply plugin: 'net.minecrell.vanilla.server.library'
@ -49,15 +49,14 @@ repositories {
dependencies { dependencies {
compile project(':core') compile project(':core')
compile 'org.spongepowered:spongeapi:6.1.0-SNAPSHOT' compile 'org.spongepowered:spongeapi:7.0.0-SNAPSHOT'
compile 'org.spongepowered:mixin:0.7-SNAPSHOT' compile name: 'worldedit-sponge-6.1.9-SNAPSHOT-dist'
compile 'com.sk89q.worldedit:worldedit-sponge:6.1.7-SNAPSHOT' compile name: 'worldedit-core-6.1.9-SNAPSHOT-dist'
compile name: 'worldedit-core-6.1.7-SNAPSHOT-dist'
} }
minecraft { minecraft {
version = "1.12" version = "1.12"
mappings = "snapshot_20170726" mappings = "snapshot_20170713"
runDir = 'run' runDir = 'run'
} }

Binary file not shown.

View File

@ -258,24 +258,26 @@ public class SpongeChunk_1_12 extends CharFaweChunk<Chunk, SpongeQueue_1_12> {
} }
// Trim tiles // Trim tiles
if (!tiles.isEmpty()) { if (!tiles.isEmpty()) {
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet(); synchronized (SpongeChunk_1_12.class) {
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator(); Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
while (iterator.hasNext()) { Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
Map.Entry<BlockPos, TileEntity> tile = iterator.next(); while (iterator.hasNext()) {
BlockPos pos = tile.getKey(); Map.Entry<BlockPos, TileEntity> tile = iterator.next();
int lx = pos.getX() & 15; BlockPos pos = tile.getKey();
int ly = pos.getY(); int lx = pos.getX() & 15;
int lz = pos.getZ() & 15; int ly = pos.getY();
int j = FaweCache.CACHE_I[ly][lz][lx]; int lz = pos.getZ() & 15;
char[] array = this.getIdArray(j); int j = FaweCache.CACHE_I[ly][lz][lx];
if (array == null) { char[] array = this.getIdArray(j);
continue; if (array == null) {
} continue;
int k = FaweCache.CACHE_J[ly][lz][lx]; }
if (array[k] != 0) { int k = FaweCache.CACHE_J[ly][lz][lx];
synchronized (SpongeChunk_1_12.class) { if (array[k] != 0) {
iterator.remove(); synchronized (SpongeChunk_1_12.class) {
tile.getValue().invalidate(); iterator.remove();
tile.getValue().invalidate();
}
} }
} }
} }

View File

@ -258,24 +258,26 @@ public class SpongeChunk_1_11 extends CharFaweChunk<Chunk, SpongeQueue_1_11> {
} }
// Trim tiles // Trim tiles
if (!tiles.isEmpty()) { if (!tiles.isEmpty()) {
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet(); synchronized (SpongeChunk_1_11.class) {
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator(); Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
while (iterator.hasNext()) { Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
Map.Entry<BlockPos, TileEntity> tile = iterator.next(); while (iterator.hasNext()) {
BlockPos pos = tile.getKey(); Map.Entry<BlockPos, TileEntity> tile = iterator.next();
int lx = pos.getX() & 15; BlockPos pos = tile.getKey();
int ly = pos.getY(); int lx = pos.getX() & 15;
int lz = pos.getZ() & 15; int ly = pos.getY();
int j = FaweCache.CACHE_I[ly][lz][lx]; int lz = pos.getZ() & 15;
char[] array = this.getIdArray(j); int j = FaweCache.CACHE_I[ly][lz][lx];
if (array == null) { char[] array = this.getIdArray(j);
continue; if (array == null) {
} continue;
int k = FaweCache.CACHE_J[ly][lz][lx]; }
if (array[k] != 0) { int k = FaweCache.CACHE_J[ly][lz][lx];
synchronized (SpongeChunk_1_11.class) { if (array[k] != 0) {
iterator.remove(); synchronized (SpongeChunk_1_11.class) {
tile.getValue().invalidate(); iterator.remove();
tile.getValue().invalidate();
}
} }
} }
} }