mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-07-16 03:14:04 +00:00
Copy paste/merge FAWE classes to this WorldEdit fork
- so certain people can look at the diff and complain about my sloppy code :( Signed-off-by: Jesse Boyd <jessepaleg@gmail.com>
This commit is contained in:
@@ -19,53 +19,112 @@
|
||||
|
||||
package com.sk89q.worldedit.extent.clipboard;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
||||
import com.boydti.fawe.object.clipboard.FaweClipboard;
|
||||
import com.boydti.fawe.object.clipboard.MemoryOptimizedClipboard;
|
||||
import com.boydti.fawe.object.extent.LightingExtent;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MutableBlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Stores block data as a multi-dimensional array of {@link BaseBlock}s and
|
||||
* Stores block data as a multi-dimensional array of {@link BlockState}s and
|
||||
* other data as lists or maps.
|
||||
*/
|
||||
public class BlockArrayClipboard implements Clipboard {
|
||||
public class BlockArrayClipboard implements Clipboard, LightingExtent, Closeable {
|
||||
|
||||
private final Region region;
|
||||
private Region region;
|
||||
public FaweClipboard IMP;
|
||||
private Vector size;
|
||||
private int mx;
|
||||
private int my;
|
||||
private int mz;
|
||||
private Vector origin;
|
||||
private final BlockStateHolder[][][] blocks;
|
||||
private final List<ClipboardEntity> entities = new ArrayList<>();
|
||||
private MutableBlockVector mutable = new MutableBlockVector();
|
||||
|
||||
public BlockArrayClipboard(Region region) {
|
||||
checkNotNull(region);
|
||||
this.region = region.clone();
|
||||
this.size = getDimensions();
|
||||
this.IMP = Settings.IMP.CLIPBOARD.USE_DISK ? new DiskOptimizedClipboard(size.getBlockX(), size.getBlockY(), size.getBlockZ()) : new MemoryOptimizedClipboard(size.getBlockX(), size.getBlockY(), size.getBlockZ());
|
||||
this.origin = region.getMinimumPoint();
|
||||
this.mx = origin.getBlockX();
|
||||
this.my = origin.getBlockY();
|
||||
this.mz = origin.getBlockZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* <p>
|
||||
* <p>The origin will be placed at the region's lowest minimum point.</p>
|
||||
*
|
||||
* @param region the bounding region
|
||||
*/
|
||||
public BlockArrayClipboard(Region region) {
|
||||
public BlockArrayClipboard(Region region, UUID clipboardId) {
|
||||
checkNotNull(region);
|
||||
this.region = region.clone();
|
||||
this.size = getDimensions();
|
||||
this.IMP = Settings.IMP.CLIPBOARD.USE_DISK ? new DiskOptimizedClipboard(size.getBlockX(), size.getBlockY(), size.getBlockZ(), clipboardId) : new MemoryOptimizedClipboard(size.getBlockX(), size.getBlockY(), size.getBlockZ());
|
||||
this.origin = region.getMinimumPoint();
|
||||
this.mx = origin.getBlockX();
|
||||
this.my = origin.getBlockY();
|
||||
this.mz = origin.getBlockZ();
|
||||
}
|
||||
|
||||
Vector dimensions = getDimensions();
|
||||
blocks = new BlockStateHolder[dimensions.getBlockX()][dimensions.getBlockY()][dimensions.getBlockZ()];
|
||||
public BlockArrayClipboard(Region region, FaweClipboard clipboard) {
|
||||
checkNotNull(region);
|
||||
this.region = region.clone();
|
||||
this.size = getDimensions();
|
||||
this.origin = region.getMinimumPoint();
|
||||
this.mx = origin.getBlockX();
|
||||
this.my = origin.getBlockY();
|
||||
this.mz = origin.getBlockZ();
|
||||
this.IMP = clipboard;
|
||||
}
|
||||
|
||||
public void init(Region region, FaweClipboard fc) {
|
||||
checkNotNull(region);
|
||||
checkNotNull(fc);
|
||||
this.region = region.clone();
|
||||
this.size = getDimensions();
|
||||
this.IMP = fc;
|
||||
this.origin = region.getMinimumPoint();
|
||||
this.mx = origin.getBlockX();
|
||||
this.my = origin.getBlockY();
|
||||
this.mz = origin.getBlockZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
IMP.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,6 +140,7 @@ public class BlockArrayClipboard implements Clipboard {
|
||||
@Override
|
||||
public void setOrigin(Vector origin) {
|
||||
this.origin = origin;
|
||||
IMP.setOrigin(origin.subtract(region.getMinimumPoint()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,8 +160,8 @@ public class BlockArrayClipboard implements Clipboard {
|
||||
|
||||
@Override
|
||||
public List<? extends Entity> getEntities(Region region) {
|
||||
List<Entity> filtered = new ArrayList<>();
|
||||
for (Entity entity : entities) {
|
||||
List<Entity> filtered = new ArrayList<Entity>();
|
||||
for (Entity entity : getEntities()) {
|
||||
if (region.contains(entity.getLocation().toVector())) {
|
||||
filtered.add(entity);
|
||||
}
|
||||
@@ -111,62 +171,79 @@ public class BlockArrayClipboard implements Clipboard {
|
||||
|
||||
@Override
|
||||
public List<? extends Entity> getEntities() {
|
||||
return Collections.unmodifiableList(entities);
|
||||
return IMP.getEntities();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Entity createEntity(Location location, BaseEntity entity) {
|
||||
ClipboardEntity ret = new ClipboardEntity(location, entity);
|
||||
entities.add(ret);
|
||||
return ret;
|
||||
return IMP.createEntity(location.getExtent(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch(), entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(Vector position) {
|
||||
if (region.contains(position)) {
|
||||
Vector v = position.subtract(region.getMinimumPoint());
|
||||
BlockStateHolder block = blocks[v.getBlockX()][v.getBlockY()][v.getBlockZ()];
|
||||
if (block != null) {
|
||||
return block.toImmutableState();
|
||||
}
|
||||
int x = position.getBlockX() - mx;
|
||||
int y = position.getBlockY() - my;
|
||||
int z = position.getBlockZ() - mz;
|
||||
return IMP.getBlock(x, y, z);
|
||||
}
|
||||
return EditSession.nullBlock;
|
||||
}
|
||||
|
||||
return BlockTypes.AIR.getDefaultState();
|
||||
public BlockState getBlockAbs(int x, int y, int z) {
|
||||
return IMP.getBlock(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getFullBlock(Vector position) {
|
||||
if (region.contains(position)) {
|
||||
Vector v = position.subtract(region.getMinimumPoint());
|
||||
BlockStateHolder block = blocks[v.getBlockX()][v.getBlockY()][v.getBlockZ()];
|
||||
if (block != null) {
|
||||
return block.toBaseBlock();
|
||||
}
|
||||
}
|
||||
|
||||
return BlockTypes.AIR.getDefaultState().toBaseBlock();
|
||||
public BlockState getLazyBlock(Vector position) {
|
||||
return getBlock(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector position, BlockStateHolder block) throws WorldEditException {
|
||||
if (region.contains(position)) {
|
||||
Vector v = position.subtract(region.getMinimumPoint());
|
||||
blocks[v.getBlockX()][v.getBlockY()][v.getBlockZ()] = block;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
public BlockState getFullBlock(Vector position) {
|
||||
return getLazyBlock(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
|
||||
if (region.contains(location)) {
|
||||
final int x = location.getBlockX();
|
||||
final int y = location.getBlockY();
|
||||
final int z = location.getBlockZ();
|
||||
return setBlock(x, y, z, block);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean setTile(int x, int y, int z, CompoundTag tag) {
|
||||
x -= mx;
|
||||
y -= my;
|
||||
z -= mz;
|
||||
return IMP.setTile(x, y, z, tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, BlockStateHolder block) throws WorldEditException {
|
||||
x -= mx;
|
||||
y -= my;
|
||||
z -= mz;
|
||||
return IMP.setBlock(x, y, z, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBiome getBiome(Vector2D position) {
|
||||
return new BaseBiome(0);
|
||||
int x = position.getBlockX() - mx;
|
||||
int z = position.getBlockZ() - mz;
|
||||
return IMP.getBiome(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(Vector2D position, BaseBiome biome) {
|
||||
return false;
|
||||
int x = position.getBlockX() - mx;
|
||||
int z = position.getBlockZ() - mz;
|
||||
IMP.setBiome(x, z, biome.getId());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -175,24 +252,38 @@ public class BlockArrayClipboard implements Clipboard {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores entity data.
|
||||
*/
|
||||
private class ClipboardEntity extends StoredEntity {
|
||||
ClipboardEntity(Location location, BaseEntity entity) {
|
||||
super(location, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove() {
|
||||
return entities.remove(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getFacet(Class<? extends T> cls) {
|
||||
return null;
|
||||
}
|
||||
public static Class<?> inject() {
|
||||
return BlockArrayClipboard.class;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public int getLight(int x, int y, int z) {
|
||||
return getBlockLight(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockLight(int x, int y, int z) {
|
||||
return getBrightness(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity(int x, int y, int z) {
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
mutable.mutZ(z);
|
||||
return getBlock(mutable).getBlockType().getMaterial().getLightOpacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBrightness(int x, int y, int z) {
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
mutable.mutZ(z);
|
||||
return getBlock(mutable).getBlockType().getMaterial().getLightValue();
|
||||
}
|
||||
}
|
@@ -19,13 +19,13 @@
|
||||
|
||||
package com.sk89q.worldedit.extent.clipboard;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* An implementation of {@link Entity} that stores a {@link BaseEntity} with it.
|
||||
*
|
||||
|
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* 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.extent.clipboard.io;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.jnbt.NBTOutputStream;
|
||||
import com.sk89q.jnbt.NamedTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* A collection of supported clipboard formats.
|
||||
*/
|
||||
public enum BuiltInClipboardFormat implements ClipboardFormat {
|
||||
|
||||
/**
|
||||
* The Schematic format used by MCEdit.
|
||||
*/
|
||||
MCEDIT_SCHEMATIC("mcedit", "mce", "schematic") {
|
||||
|
||||
@Override
|
||||
public String getPrimaryFileExtension() {
|
||||
return "schematic";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipboardReader getReader(InputStream inputStream) throws IOException {
|
||||
NBTInputStream nbtStream = new NBTInputStream(new GZIPInputStream(inputStream));
|
||||
return new MCEditSchematicReader(nbtStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
|
||||
throw new IOException("This format does not support saving");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFormat(File file) {
|
||||
try (NBTInputStream str = new NBTInputStream(new GZIPInputStream(new FileInputStream(file)))) {
|
||||
NamedTag rootTag = str.readNamedTag();
|
||||
if (!rootTag.getName().equals("Schematic")) {
|
||||
return false;
|
||||
}
|
||||
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
|
||||
|
||||
// Check
|
||||
Map<String, Tag> schematic = schematicTag.getValue();
|
||||
if (!schematic.containsKey("Materials")) {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
SPONGE_SCHEMATIC("sponge", "schem") {
|
||||
|
||||
@Override
|
||||
public String getPrimaryFileExtension() {
|
||||
return "schem";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipboardReader getReader(InputStream inputStream) throws IOException {
|
||||
NBTInputStream nbtStream = new NBTInputStream(new GZIPInputStream(inputStream));
|
||||
return new SpongeSchematicReader(nbtStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
|
||||
NBTOutputStream nbtStream = new NBTOutputStream(new GZIPOutputStream(outputStream));
|
||||
return new SpongeSchematicWriter(nbtStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFormat(File file) {
|
||||
try (NBTInputStream str = new NBTInputStream(new GZIPInputStream(new FileInputStream(file)))) {
|
||||
NamedTag rootTag = str.readNamedTag();
|
||||
if (!rootTag.getName().equals("Schematic")) {
|
||||
return false;
|
||||
}
|
||||
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
|
||||
|
||||
// Check
|
||||
Map<String, Tag> schematic = schematicTag.getValue();
|
||||
if (!schematic.containsKey("Version")) {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private final ImmutableSet<String> aliases;
|
||||
|
||||
BuiltInClipboardFormat(String... aliases) {
|
||||
this.aliases = ImmutableSet.copyOf(aliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAliases() {
|
||||
return this.aliases;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getFileExtensions() {
|
||||
return ImmutableSet.of(getPrimaryFileExtension());
|
||||
}
|
||||
|
||||
}
|
@@ -19,30 +19,425 @@
|
||||
|
||||
package com.sk89q.worldedit.extent.clipboard.io;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Set;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.clipboard.*;
|
||||
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.PNGWriter;
|
||||
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.*;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
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.block.BlockTypes;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.util.*;
|
||||
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;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* A collection of supported clipboard formats.
|
||||
*/
|
||||
public interface ClipboardFormat {
|
||||
public enum ClipboardFormat {
|
||||
|
||||
/**
|
||||
* Returns the name of this format.
|
||||
*
|
||||
* @return The name of the format
|
||||
* The Schematic format used by many software.
|
||||
*/
|
||||
String getName();
|
||||
@Deprecated
|
||||
SCHEMATIC(new AbstractClipboardFormat("SCHEMATIC", "mcedit", "mce", "schematic") {
|
||||
@Override
|
||||
public ClipboardReader getReader(InputStream inputStream) throws IOException {
|
||||
if (inputStream instanceof FileInputStream) {
|
||||
inputStream = new ResettableFileInputStream((FileInputStream) inputStream);
|
||||
}
|
||||
BufferedInputStream buffered = new BufferedInputStream(inputStream);
|
||||
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
|
||||
SchematicReader input = new SchematicReader(nbtStream);
|
||||
input.setUnderlyingStream(inputStream);
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
|
||||
throw new UnsupportedOperationException("No longer supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFormat(File file) {
|
||||
DataInputStream str = null;
|
||||
try {
|
||||
str = new DataInputStream(new GZIPInputStream(new FileInputStream(file)));
|
||||
if ((str.readByte() & 0xFF) != NBTConstants.TYPE_COMPOUND) {
|
||||
return false;
|
||||
}
|
||||
byte[] nameBytes = new byte[str.readShort() & 0xFFFF];
|
||||
str.readFully(nameBytes);
|
||||
String name = new String(nameBytes, NBTConstants.CHARSET);
|
||||
return name.equals("Schematic");
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
} finally {
|
||||
if (str != null) {
|
||||
try {
|
||||
str.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return "schematic";
|
||||
}
|
||||
}),
|
||||
|
||||
@Deprecated
|
||||
SPONGE_SCHEMATIC(new AbstractClipboardFormat("SPONGE", "sponge", "schem") {
|
||||
@Override
|
||||
public ClipboardReader getReader(InputStream inputStream) throws IOException {
|
||||
if (inputStream instanceof FileInputStream) {
|
||||
inputStream = new ResettableFileInputStream((FileInputStream) inputStream);
|
||||
}
|
||||
BufferedInputStream buffered = new BufferedInputStream(inputStream);
|
||||
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
|
||||
SpongeSchematicReader input = new SpongeSchematicReader(nbtStream);
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
|
||||
OutputStream gzip;
|
||||
if (outputStream instanceof PGZIPOutputStream || outputStream instanceof GZIPOutputStream) {
|
||||
gzip = outputStream;
|
||||
} else {
|
||||
outputStream = new BufferedOutputStream(outputStream);
|
||||
PGZIPOutputStream pigz = new PGZIPOutputStream(outputStream);
|
||||
gzip = pigz;
|
||||
}
|
||||
NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip));
|
||||
return new SpongeSchematicWriter(nbtStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFormat(File file) {
|
||||
DataInputStream str = null;
|
||||
try {
|
||||
str = new DataInputStream(new GZIPInputStream(new FileInputStream(file)));
|
||||
if ((str.readByte() & 0xFF) != NBTConstants.TYPE_COMPOUND) {
|
||||
return false;
|
||||
}
|
||||
byte[] nameBytes = new byte[str.readShort() & 0xFFFF];
|
||||
str.readFully(nameBytes);
|
||||
String name = new String(nameBytes, NBTConstants.CHARSET);
|
||||
return name.equals("Schematic");
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
} finally {
|
||||
if (str != null) {
|
||||
try {
|
||||
str.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return "schem";
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* The structure block format:
|
||||
* http://minecraft.gamepedia.com/Structure_block_file_format
|
||||
*/
|
||||
STRUCTURE(new AbstractClipboardFormat("STRUCTURE", "structure", "nbt") {
|
||||
@Override
|
||||
public ClipboardReader getReader(InputStream inputStream) throws IOException {
|
||||
inputStream = new BufferedInputStream(inputStream);
|
||||
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(inputStream)));
|
||||
return new StructureFormat(nbtStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
|
||||
outputStream = new BufferedOutputStream(outputStream);
|
||||
OutputStream gzip;
|
||||
if (outputStream instanceof PGZIPOutputStream || outputStream instanceof GZIPOutputStream) {
|
||||
gzip = outputStream;
|
||||
} else {
|
||||
PGZIPOutputStream pigz = new PGZIPOutputStream(outputStream);
|
||||
gzip = pigz;
|
||||
}
|
||||
NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip));
|
||||
return new StructureFormat(nbtStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFormat(File file) {
|
||||
return file.getName().endsWith(".nbt");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return "nbt";
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Isometric PNG writer
|
||||
*/
|
||||
PNG(new AbstractClipboardFormat("PNG", "png", "image") {
|
||||
|
||||
@Override
|
||||
public ClipboardReader getReader(InputStream inputStream) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
|
||||
return new PNGWriter(new BufferedOutputStream(outputStream));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFormat(File file) {
|
||||
return file.getName().endsWith(".png");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return "png";
|
||||
}
|
||||
}),
|
||||
|
||||
;
|
||||
|
||||
private static final Map<String, ClipboardFormat> aliasMap;
|
||||
|
||||
static {
|
||||
aliasMap = new ConcurrentHashMap<>(8, 0.9f, 1);
|
||||
for (ClipboardFormat emum : ClipboardFormat.values()) {
|
||||
for (String alias : emum.getAliases()) {
|
||||
aliasMap.put(alias, emum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IClipboardFormat format;
|
||||
|
||||
ClipboardFormat() {
|
||||
|
||||
}
|
||||
|
||||
ClipboardFormat(IClipboardFormat format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
public URL uploadPublic(final Clipboard clipboard, String category, String user) {
|
||||
// summary
|
||||
// blocks
|
||||
HashMap<String, Object> map = new HashMap<String, Object>();
|
||||
Vector dimensions = clipboard.getDimensions();
|
||||
map.put("width", dimensions.getX());
|
||||
map.put("height", dimensions.getY());
|
||||
map.put("length", dimensions.getZ());
|
||||
map.put("creator", user);
|
||||
if (clipboard instanceof BlockArrayClipboard) {
|
||||
FaweClipboard fc = ((BlockArrayClipboard) clipboard).IMP;
|
||||
final int[] ids = new int[BlockTypes.size()];
|
||||
fc.streamCombinedIds(new NBTStreamer.ByteReader() {
|
||||
@Override
|
||||
public void run(int index, int byteValue) {
|
||||
ids[byteValue & BlockTypes.BIT_MASK]++;
|
||||
}
|
||||
});
|
||||
Map<String, Integer> blocks = new HashMap<String, Integer>();
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
if (ids[i] != 0) {
|
||||
blocks.put(BlockTypes.get(i).getId(), ids[i]);
|
||||
}
|
||||
}
|
||||
map.put("blocks", blocks);
|
||||
}
|
||||
Gson gson = new Gson();
|
||||
String json = gson.toJson(map);
|
||||
return MainUtil.upload(Settings.IMP.WEB.ASSETS, false, json, category, null, new RunnableVal<OutputStream>() {
|
||||
@Override
|
||||
public void run(OutputStream value) {
|
||||
write(value, clipboard);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public MultiClipboardHolder loadAllFromInput(Actor player, String input, boolean message) throws IOException {
|
||||
checkNotNull(player);
|
||||
checkNotNull(input);
|
||||
WorldEdit worldEdit = WorldEdit.getInstance();
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
if (input.startsWith("url:")) {
|
||||
URL base = new URL(Settings.IMP.WEB.URL);
|
||||
input = new URL(base, "uploads/" + input.substring(4) + ".schematic").toString();
|
||||
}
|
||||
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;
|
||||
}
|
||||
MultiClipboardHolder clipboards = loadAllFromUrl(url);
|
||||
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()) {
|
||||
dir = new File(dir + "." + getExtension());
|
||||
}
|
||||
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 = new File(dir + "." + getExtension());
|
||||
}
|
||||
}
|
||||
if (!dir.exists()) {
|
||||
if (message) BBC.SCHEMATIC_NOT_FOUND.send(player, input);
|
||||
return null;
|
||||
}
|
||||
if (!dir.isDirectory()) {
|
||||
ByteSource source = Files.asByteSource(dir);
|
||||
URI uri = dir.toURI();
|
||||
return new MultiClipboardHolder(uri, new LazyClipboardHolder(dir.toURI(), source, this, null));
|
||||
}
|
||||
URIClipboardHolder[] clipboards = loadAllFromDirectory(dir);
|
||||
if (clipboards.length < 1) {
|
||||
if (message) BBC.SCHEMATIC_NOT_FOUND.send(player, input);
|
||||
return null;
|
||||
}
|
||||
return new MultiClipboardHolder(dir.toURI(), clipboards);
|
||||
}
|
||||
}
|
||||
|
||||
public URIClipboardHolder[] loadAllFromDirectory(File dir) {
|
||||
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(file.toURI(), source, this, null);
|
||||
}
|
||||
return clipboards;
|
||||
}
|
||||
|
||||
public MultiClipboardHolder loadAllFromUrl(URL url) 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(url.toURI(), source, this, null);
|
||||
clipboards.add(clipboard);
|
||||
}
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
LazyClipboardHolder[] arr = clipboards.toArray(new LazyClipboardHolder[clipboards.size()]);
|
||||
try {
|
||||
MultiClipboardHolder multi = new MultiClipboardHolder(url.toURI());
|
||||
for (LazyClipboardHolder h : arr) multi.add(h);
|
||||
return multi;
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void write(OutputStream value, Clipboard clipboard) {
|
||||
try {
|
||||
try (PGZIPOutputStream gzip = new PGZIPOutputStream(value)) {
|
||||
try (ClipboardWriter writer = format.getWriter(gzip)) {
|
||||
writer.write(clipboard);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public URL uploadAnonymous(final Clipboard clipboard) {
|
||||
return MainUtil.upload(null, null, format.getExtension(), new RunnableVal<OutputStream>() {
|
||||
@Override
|
||||
public void run(OutputStream value) {
|
||||
write(value, clipboard);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public IClipboardFormat getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of aliases.
|
||||
*
|
||||
* @return a set of aliases
|
||||
*/
|
||||
Set<String> getAliases();
|
||||
public Set<String> getAliases() {
|
||||
return format.getAliases();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a reader.
|
||||
@@ -51,7 +446,9 @@ public interface ClipboardFormat {
|
||||
* @return a reader
|
||||
* @throws IOException thrown on I/O error
|
||||
*/
|
||||
ClipboardReader getReader(InputStream inputStream) throws IOException;
|
||||
public ClipboardReader getReader(InputStream inputStream) throws IOException {
|
||||
return format.getReader(inputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a writer.
|
||||
@@ -60,7 +457,57 @@ public interface ClipboardFormat {
|
||||
* @return a writer
|
||||
* @throws IOException thrown on I/O error
|
||||
*/
|
||||
ClipboardWriter getWriter(OutputStream outputStream) throws IOException;
|
||||
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
|
||||
return format.getWriter(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the player's clipboard
|
||||
* @param player
|
||||
* @param uri
|
||||
* @param in
|
||||
* @return the held clipboard
|
||||
* @throws IOException
|
||||
*/
|
||||
public ClipboardHolder hold(Player player, URI uri, InputStream in) throws IOException {
|
||||
checkNotNull(player);
|
||||
checkNotNull(uri);
|
||||
checkNotNull(in);
|
||||
|
||||
final ClipboardReader reader = getReader(in);
|
||||
|
||||
final Clipboard clipboard;
|
||||
|
||||
LocalSession session = WorldEdit.getInstance().getSessionManager().get(player);
|
||||
session.setClipboard(null);
|
||||
if (reader instanceof SchematicReader) {
|
||||
clipboard = ((SchematicReader) reader).read(player.getUniqueId());
|
||||
} else if (reader instanceof StructureFormat) {
|
||||
clipboard = ((StructureFormat) reader).read(player.getUniqueId());
|
||||
} else {
|
||||
clipboard = reader.read();
|
||||
}
|
||||
URIClipboardHolder holder = new URIClipboardHolder(uri, clipboard);
|
||||
session.setClipboard(holder);
|
||||
return holder;
|
||||
}
|
||||
|
||||
public Schematic load(File file) throws IOException {
|
||||
return load(new FileInputStream(file));
|
||||
}
|
||||
|
||||
public Schematic load(InputStream stream) throws IOException {
|
||||
return new Schematic(this.getReader(stream).read());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file extension used
|
||||
*
|
||||
* @return file extension string
|
||||
*/
|
||||
public String getExtension() {
|
||||
return format.getExtension();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given file is of this format.
|
||||
@@ -68,20 +515,50 @@ public interface ClipboardFormat {
|
||||
* @param file the file
|
||||
* @return true if the given file is of this format
|
||||
*/
|
||||
boolean isFormat(File file);
|
||||
public boolean isFormat(File file) {
|
||||
return format.isFormat(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file extension this format primarily uses.
|
||||
* Find the clipboard format named by the given alias.
|
||||
*
|
||||
* @return The primary file extension
|
||||
* @param alias the alias
|
||||
* @return the format, otherwise null if none is matched
|
||||
*/
|
||||
String getPrimaryFileExtension();
|
||||
@Nullable
|
||||
public static ClipboardFormat findByAlias(String alias) {
|
||||
checkNotNull(alias);
|
||||
return aliasMap.get(alias.toLowerCase().trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file extensions this format is commonly known to use. This should
|
||||
* include {@link #getPrimaryFileExtension()}.
|
||||
* Detect the format given a file.
|
||||
*
|
||||
* @return The file extensions this format might be known by
|
||||
* @param file the file
|
||||
* @return the format, otherwise null if one cannot be detected
|
||||
*/
|
||||
Set<String> getFileExtensions();
|
||||
}
|
||||
@Nullable
|
||||
public static ClipboardFormat findByFile(File file) {
|
||||
checkNotNull(file);
|
||||
for (ClipboardFormat format : EnumSet.allOf(ClipboardFormat.class)) {
|
||||
if (format.isFormat(file)) {
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ClipboardFormat addFormat(IClipboardFormat instance) {
|
||||
ClipboardFormat newEnum = ReflectionUtils.addEnum(ClipboardFormat.class, instance.getName());
|
||||
newEnum.format = instance;
|
||||
for (String alias : newEnum.getAliases()) {
|
||||
aliasMap.put(alias, newEnum);
|
||||
}
|
||||
return newEnum;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return ClipboardFormat.class;
|
||||
}
|
||||
}
|
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* 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.extent.clipboard.io;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ClipboardFormats {
|
||||
|
||||
private static final Map<String, ClipboardFormat> aliasMap = new HashMap<>();
|
||||
private static final Multimap<String, ClipboardFormat> fileExtensionMap = HashMultimap.create();
|
||||
private static final List<ClipboardFormat> registeredFormats = new ArrayList<>();
|
||||
|
||||
public static void registerClipboardFormat(ClipboardFormat format) {
|
||||
checkNotNull(format);
|
||||
|
||||
for (String key : format.getAliases()) {
|
||||
String lowKey = key.toLowerCase(Locale.ENGLISH);
|
||||
ClipboardFormat old = aliasMap.put(lowKey, format);
|
||||
if (old != null) {
|
||||
aliasMap.put(lowKey, old);
|
||||
WorldEdit.logger.warning(format.getClass().getName() + " cannot override existing alias '" + lowKey + "' used by " + old.getClass().getName());
|
||||
}
|
||||
}
|
||||
for (String ext : format.getFileExtensions()) {
|
||||
String lowExt = ext.toLowerCase(Locale.ENGLISH);
|
||||
fileExtensionMap.put(lowExt, format);
|
||||
}
|
||||
registeredFormats.add(format);
|
||||
}
|
||||
|
||||
static {
|
||||
for (BuiltInClipboardFormat format : BuiltInClipboardFormat.values()) {
|
||||
registerClipboardFormat(format);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the clipboard format named by the given alias.
|
||||
*
|
||||
* @param alias
|
||||
* the alias
|
||||
* @return the format, otherwise null if none is matched
|
||||
*/
|
||||
@Nullable
|
||||
public static ClipboardFormat findByAlias(String alias) {
|
||||
checkNotNull(alias);
|
||||
return aliasMap.get(alias.toLowerCase(Locale.ENGLISH).trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the format of given a file.
|
||||
*
|
||||
* @param file
|
||||
* the file
|
||||
* @return the format, otherwise null if one cannot be detected
|
||||
*/
|
||||
@Nullable
|
||||
public static ClipboardFormat findByFile(File file) {
|
||||
checkNotNull(file);
|
||||
|
||||
for (ClipboardFormat format : registeredFormats) {
|
||||
if (format.isFormat(file)) {
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a multimap from a file extension to the potential matching formats.
|
||||
*/
|
||||
public static Multimap<String, ClipboardFormat> getFileExtensionMap() {
|
||||
return Multimaps.unmodifiableMultimap(fileExtensionMap);
|
||||
}
|
||||
|
||||
public static Collection<ClipboardFormat> getAll() {
|
||||
return Collections.unmodifiableCollection(registeredFormats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not public API, only used by SchematicCommands.
|
||||
* It is not in SchematicCommands because it may rely on internal register calls.
|
||||
*/
|
||||
public static String[] getFileExtensionArray() {
|
||||
return fileExtensionMap.keySet().toArray(new String[fileExtensionMap.keySet().size()]);
|
||||
}
|
||||
|
||||
private ClipboardFormats() {
|
||||
}
|
||||
|
||||
}
|
@@ -20,6 +20,7 @@
|
||||
package com.sk89q.worldedit.extent.clipboard.io;
|
||||
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.world.registry.Registries;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
@@ -1,318 +0,0 @@
|
||||
/*
|
||||
* 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.extent.clipboard.io;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.jnbt.ByteArrayTag;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.jnbt.NamedTag;
|
||||
import com.sk89q.jnbt.ShortTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.NBTCompatibilityHandler;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.SignCompatibilityHandler;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.entity.EntityType;
|
||||
import com.sk89q.worldedit.world.entity.EntityTypes;
|
||||
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
||||
import com.sk89q.worldedit.world.storage.NBTConversions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Reads schematic files that are compatible with MCEdit and other editors.
|
||||
*/
|
||||
public class MCEditSchematicReader extends NBTSchematicReader {
|
||||
|
||||
private static final List<NBTCompatibilityHandler> COMPATIBILITY_HANDLERS = new ArrayList<>();
|
||||
|
||||
static {
|
||||
COMPATIBILITY_HANDLERS.add(new SignCompatibilityHandler());
|
||||
// TODO Add a handler for skulls, flower pots, note blocks, etc.
|
||||
}
|
||||
|
||||
private static final Logger log = Logger.getLogger(MCEditSchematicReader.class.getCanonicalName());
|
||||
private final NBTInputStream inputStream;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param inputStream the input stream to read from
|
||||
*/
|
||||
public MCEditSchematicReader(NBTInputStream inputStream) {
|
||||
checkNotNull(inputStream);
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard read() throws IOException {
|
||||
// Schematic tag
|
||||
NamedTag rootTag = inputStream.readNamedTag();
|
||||
if (!rootTag.getName().equals("Schematic")) {
|
||||
throw new IOException("Tag 'Schematic' does not exist or is not first");
|
||||
}
|
||||
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
|
||||
|
||||
// Check
|
||||
Map<String, Tag> schematic = schematicTag.getValue();
|
||||
if (!schematic.containsKey("Blocks")) {
|
||||
throw new IOException("Schematic file is missing a 'Blocks' tag");
|
||||
}
|
||||
|
||||
// Check type of Schematic
|
||||
String materials = requireTag(schematic, "Materials", StringTag.class).getValue();
|
||||
if (!materials.equals("Alpha")) {
|
||||
throw new IOException("Schematic file is not an Alpha schematic");
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
// Metadata
|
||||
// ====================================================================
|
||||
|
||||
Vector origin;
|
||||
Region region;
|
||||
|
||||
// Get information
|
||||
short width = requireTag(schematic, "Width", ShortTag.class).getValue();
|
||||
short height = requireTag(schematic, "Height", ShortTag.class).getValue();
|
||||
short length = requireTag(schematic, "Length", ShortTag.class).getValue();
|
||||
|
||||
try {
|
||||
int originX = requireTag(schematic, "WEOriginX", IntTag.class).getValue();
|
||||
int originY = requireTag(schematic, "WEOriginY", IntTag.class).getValue();
|
||||
int originZ = requireTag(schematic, "WEOriginZ", IntTag.class).getValue();
|
||||
Vector min = new Vector(originX, originY, originZ);
|
||||
|
||||
int offsetX = requireTag(schematic, "WEOffsetX", IntTag.class).getValue();
|
||||
int offsetY = requireTag(schematic, "WEOffsetY", IntTag.class).getValue();
|
||||
int offsetZ = requireTag(schematic, "WEOffsetZ", IntTag.class).getValue();
|
||||
Vector offset = new Vector(offsetX, offsetY, offsetZ);
|
||||
|
||||
origin = min.subtract(offset);
|
||||
region = new CuboidRegion(min, min.add(width, height, length).subtract(Vector.ONE));
|
||||
} catch (IOException ignored) {
|
||||
origin = new Vector(0, 0, 0);
|
||||
region = new CuboidRegion(origin, origin.add(width, height, length).subtract(Vector.ONE));
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
// Blocks
|
||||
// ====================================================================
|
||||
|
||||
// Get blocks
|
||||
byte[] blockId = requireTag(schematic, "Blocks", ByteArrayTag.class).getValue();
|
||||
byte[] blockData = requireTag(schematic, "Data", ByteArrayTag.class).getValue();
|
||||
byte[] addId = new byte[0];
|
||||
short[] blocks = new short[blockId.length]; // Have to later combine IDs
|
||||
|
||||
// We support 4096 block IDs using the same method as vanilla Minecraft, where
|
||||
// the highest 4 bits are stored in a separate byte array.
|
||||
if (schematic.containsKey("AddBlocks")) {
|
||||
addId = requireTag(schematic, "AddBlocks", ByteArrayTag.class).getValue();
|
||||
}
|
||||
|
||||
// Combine the AddBlocks data with the first 8-bit block ID
|
||||
for (int index = 0; index < blockId.length; index++) {
|
||||
if ((index >> 1) >= addId.length) { // No corresponding AddBlocks index
|
||||
blocks[index] = (short) (blockId[index] & 0xFF);
|
||||
} else {
|
||||
if ((index & 1) == 0) {
|
||||
blocks[index] = (short) (((addId[index >> 1] & 0x0F) << 8) + (blockId[index] & 0xFF));
|
||||
} else {
|
||||
blocks[index] = (short) (((addId[index >> 1] & 0xF0) << 4) + (blockId[index] & 0xFF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Need to pull out tile entities
|
||||
List<Tag> tileEntities = requireTag(schematic, "TileEntities", ListTag.class).getValue();
|
||||
Map<BlockVector, Map<String, Tag>> tileEntitiesMap = new HashMap<>();
|
||||
|
||||
for (Tag tag : tileEntities) {
|
||||
if (!(tag instanceof CompoundTag)) continue;
|
||||
CompoundTag t = (CompoundTag) tag;
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
|
||||
Map<String, Tag> values = new HashMap<>();
|
||||
|
||||
for (Map.Entry<String, Tag> entry : t.getValue().entrySet()) {
|
||||
switch (entry.getKey()) {
|
||||
case "x":
|
||||
if (entry.getValue() instanceof IntTag) {
|
||||
x = ((IntTag) entry.getValue()).getValue();
|
||||
}
|
||||
break;
|
||||
case "y":
|
||||
if (entry.getValue() instanceof IntTag) {
|
||||
y = ((IntTag) entry.getValue()).getValue();
|
||||
}
|
||||
break;
|
||||
case "z":
|
||||
if (entry.getValue() instanceof IntTag) {
|
||||
z = ((IntTag) entry.getValue()).getValue();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
int index = y * width * length + z * width + x;
|
||||
BlockState block = LegacyMapper.getInstance().getBlockFromLegacy(blocks[index], blockData[index]);
|
||||
if (block != null) {
|
||||
for (NBTCompatibilityHandler handler : COMPATIBILITY_HANDLERS) {
|
||||
if (handler.isAffectedBlock(block)) {
|
||||
handler.updateNBT(block, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BlockVector vec = new BlockVector(x, y, z);
|
||||
tileEntitiesMap.put(vec, values);
|
||||
}
|
||||
|
||||
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
|
||||
clipboard.setOrigin(origin);
|
||||
|
||||
// Don't log a torrent of errors
|
||||
int failedBlockSets = 0;
|
||||
|
||||
for (int x = 0; x < width; ++x) {
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int z = 0; z < length; ++z) {
|
||||
int index = y * width * length + z * width + x;
|
||||
BlockVector pt = new BlockVector(x, y, z);
|
||||
BlockState state = LegacyMapper.getInstance().getBlockFromLegacy(blocks[index], blockData[index]);
|
||||
|
||||
try {
|
||||
if (state != null) {
|
||||
if (tileEntitiesMap.containsKey(pt)) {
|
||||
clipboard.setBlock(region.getMinimumPoint().add(pt), state.toBaseBlock(new CompoundTag(tileEntitiesMap.get(pt))));
|
||||
} else {
|
||||
clipboard.setBlock(region.getMinimumPoint().add(pt), state);
|
||||
}
|
||||
} else {
|
||||
log.warning("Unknown block when pasting schematic: " + blocks[index] + ":" + blockData[index] + ". Please report this issue.");
|
||||
}
|
||||
} catch (WorldEditException e) {
|
||||
switch (failedBlockSets) {
|
||||
case 0:
|
||||
log.log(Level.WARNING, "Failed to set block on a Clipboard", e);
|
||||
break;
|
||||
case 1:
|
||||
log.log(Level.WARNING, "Failed to set block on a Clipboard (again) -- no more messages will be logged", e);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
failedBlockSets++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
// Entities
|
||||
// ====================================================================
|
||||
|
||||
try {
|
||||
List<Tag> entityTags = requireTag(schematic, "Entities", ListTag.class).getValue();
|
||||
|
||||
for (Tag tag : entityTags) {
|
||||
if (tag instanceof CompoundTag) {
|
||||
CompoundTag compound = (CompoundTag) tag;
|
||||
String id = convertEntityId(compound.getString("id"));
|
||||
Location location = NBTConversions.toLocation(clipboard, compound.getListTag("Pos"), compound.getListTag("Rotation"));
|
||||
|
||||
if (!id.isEmpty()) {
|
||||
EntityType entityType = EntityTypes.get(id.toLowerCase());
|
||||
if (entityType != null) {
|
||||
BaseEntity state = new BaseEntity(entityType, compound);
|
||||
clipboard.createEntity(location, state);
|
||||
} else {
|
||||
log.warning("Unknown entity when pasting schematic: " + id.toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ignored) { // No entities? No problem
|
||||
}
|
||||
|
||||
return clipboard;
|
||||
}
|
||||
|
||||
private String convertEntityId(String id) {
|
||||
switch(id) {
|
||||
case "xp_orb":
|
||||
return "experience_orb";
|
||||
case "xp_bottle":
|
||||
return "experience_bottle";
|
||||
case "eye_of_ender_signal":
|
||||
return "eye_of_ender";
|
||||
case "ender_crystal":
|
||||
return "end_crystal";
|
||||
case "fireworks_rocket":
|
||||
return "firework_rocket";
|
||||
case "commandblock_minecart":
|
||||
return "command_block_minecart";
|
||||
case "snowman":
|
||||
return "snow_golem";
|
||||
case "villager_golem":
|
||||
return "iron_golem";
|
||||
case "evocation_fangs":
|
||||
return "evoker_fangs";
|
||||
case "evocation_illager":
|
||||
return "evoker";
|
||||
case "vindication_illager":
|
||||
return "vindicator";
|
||||
case "illusion_illager":
|
||||
return "illusioner";
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
@@ -60,4 +60,4 @@ public abstract class NBTSchematicReader implements ClipboardReader {
|
||||
|
||||
return expected.cast(test);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.extent.clipboard.io;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.jnbt.CorruptSchematicStreamer;
|
||||
import com.boydti.fawe.jnbt.SchematicStreamer;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Reads schematic files based that are compatible with MCEdit and other editors.
|
||||
*/
|
||||
public class SchematicReader implements ClipboardReader {
|
||||
|
||||
private static final Logger log = Logger.getLogger(SchematicReader.class.getCanonicalName());
|
||||
private NBTInputStream inputStream;
|
||||
private InputStream rootStream;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param inputStream the input stream to read from
|
||||
*/
|
||||
public SchematicReader(NBTInputStream inputStream) {
|
||||
checkNotNull(inputStream);
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
public void setUnderlyingStream(InputStream in) {
|
||||
this.rootStream = in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard read() throws IOException {
|
||||
return read(UUID.randomUUID());
|
||||
}
|
||||
|
||||
public Clipboard read(final UUID clipboardId) throws IOException {
|
||||
try {
|
||||
return new SchematicStreamer(inputStream, clipboardId).getClipboard();
|
||||
} catch (Exception e) {
|
||||
Fawe.debug("Input is corrupt!");
|
||||
e.printStackTrace();
|
||||
return new CorruptSchematicStreamer(rootStream, clipboardId).recover();
|
||||
}
|
||||
}
|
||||
|
||||
private static <T extends Tag> T requireTag(Map<String, Tag> items, String key, Class<T> expected) throws IOException {
|
||||
if (!items.containsKey(key)) {
|
||||
throw new IOException("Schematic file is missing a \"" + key + "\" tag");
|
||||
}
|
||||
|
||||
Tag tag = items.get(key);
|
||||
if (!expected.isInstance(tag)) {
|
||||
throw new IOException(key + " tag is not of tag type " + expected.getName());
|
||||
}
|
||||
|
||||
return expected.cast(tag);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static <T extends Tag> T getTag(CompoundTag tag, Class<T> expected, String key) {
|
||||
Map<String, Tag> items = tag.getValue();
|
||||
|
||||
if (!items.containsKey(key)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Tag test = items.get(key);
|
||||
if (!expected.isInstance(test)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return expected.cast(test);
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return SchematicReader.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
@@ -21,6 +21,7 @@ package com.sk89q.worldedit.extent.clipboard.io;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.sk89q.jnbt.ByteArrayTag;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@@ -35,7 +36,8 @@ import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
@@ -43,8 +45,9 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.NBTCompatibilityHandler;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -141,12 +144,7 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
||||
|
||||
for (String palettePart : paletteObject.keySet()) {
|
||||
int id = requireTag(paletteObject, palettePart, IntTag.class).getValue();
|
||||
BlockState state;
|
||||
try {
|
||||
state = WorldEdit.getInstance().getBlockFactory().parseFromInput(palettePart, parserContext).toImmutableState();
|
||||
} catch (InputParseException e) {
|
||||
throw new IOException("Invalid BlockState in schematic: " + palettePart + ". Are you missing a mod of using a schematic made in a newer version of Minecraft?");
|
||||
}
|
||||
BlockState state = BlockState.get(palettePart);
|
||||
palette.put(id, state);
|
||||
}
|
||||
|
||||
@@ -154,10 +152,9 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
||||
|
||||
Map<BlockVector, Map<String, Tag>> tileEntitiesMap = new HashMap<>();
|
||||
try {
|
||||
List<Map<String, Tag>> tileEntityTags = requireTag(schematic, "TileEntities", ListTag.class).getValue().stream()
|
||||
.map(tag -> (CompoundTag) tag)
|
||||
.map(CompoundTag::getValue)
|
||||
.collect(Collectors.toList());
|
||||
List<Map<String, Tag>> tileEntityTags = ((ListTag<CompoundTag>) requireTag(schematic, "TileEntities", ListTag.class)).getValue().stream()
|
||||
.map(CompoundTag::getValue)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (Map<String, Tag> tileEntity : tileEntityTags) {
|
||||
int[] pos = requireTag(tileEntity, "Pos", IntArrayTag.class).getValue();
|
||||
@@ -196,7 +193,7 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
||||
BlockState state = palette.get(value);
|
||||
BlockVector pt = new BlockVector(x, y, z);
|
||||
try {
|
||||
if (tileEntitiesMap.containsKey(pt)) {
|
||||
if (state.getBlockType().getMaterial().hasContainer() && tileEntitiesMap.containsKey(pt)) {
|
||||
Map<String, Tag> values = Maps.newHashMap(tileEntitiesMap.get(pt));
|
||||
for (NBTCompatibilityHandler handler : COMPATIBILITY_HANDLERS) {
|
||||
if (handler.isAffectedBlock(state)) {
|
||||
@@ -209,7 +206,7 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
||||
values.put("id", values.get("Id"));
|
||||
values.remove("Id");
|
||||
values.remove("Pos");
|
||||
clipboard.setBlock(pt, state.toBaseBlock(new CompoundTag(values)));
|
||||
clipboard.setBlock(pt, new BaseBlock(state, new CompoundTag(values)));
|
||||
} else {
|
||||
clipboard.setBlock(pt, state);
|
||||
}
|
||||
@@ -227,4 +224,4 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
||||
public void close() throws IOException {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
@@ -32,9 +32,11 @@ import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -128,7 +130,7 @@ public class SpongeSchematicWriter implements ClipboardWriter {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int x0 = min.getBlockX() + x;
|
||||
BlockVector point = new BlockVector(x0, y0, z0);
|
||||
BaseBlock block = clipboard.getFullBlock(point);
|
||||
BlockStateHolder block = clipboard.getFullBlock(point);
|
||||
if (block.getNbtData() != null) {
|
||||
Map<String, Tag> values = new HashMap<>();
|
||||
for (Map.Entry<String, Tag> entry : block.getNbtData().getValue().entrySet()) {
|
||||
@@ -187,4 +189,4 @@ public class SpongeSchematicWriter implements ClipboardWriter {
|
||||
public void close() throws IOException {
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,557 @@
|
||||
package com.sk89q.worldedit.extent.clipboard.io;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.object.collection.SoftHashMap;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
public class WavefrontReader implements ClipboardReader {
|
||||
private final InputStream inputStream;
|
||||
private final File root;
|
||||
|
||||
private final Map<String, BufferedImage> textures = new SoftHashMap<>();
|
||||
private final Map<String, Map<String, Material>> materialFiles = new HashMap<>();
|
||||
private final Map<String, Material> materials = new HashMap<>();
|
||||
|
||||
public WavefrontReader(File file) throws FileNotFoundException {
|
||||
this.inputStream = new BufferedInputStream(new FileInputStream(file));
|
||||
File parent = file.getParentFile();
|
||||
this.root = parent == null ? new File(".") : parent;
|
||||
}
|
||||
|
||||
private final static double parse(String s) {
|
||||
int len = s.length();
|
||||
int index;
|
||||
int numIndex = 1;
|
||||
|
||||
double neg;
|
||||
|
||||
if (s.charAt(0) == '-') {
|
||||
neg = -1;
|
||||
index = 1;
|
||||
} else {
|
||||
index = 0;
|
||||
neg = 1;
|
||||
}
|
||||
double val = 0;
|
||||
outer:
|
||||
for (; index < len; index++) {
|
||||
char c = s.charAt(index);
|
||||
switch (c) {
|
||||
case ' ': break outer;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
val = val * 10 + (c - 48);
|
||||
continue;
|
||||
case '.': {
|
||||
double factor = 0.1;
|
||||
for (; index < len; index++) {
|
||||
c = s.charAt(index);
|
||||
switch (c) {
|
||||
case ' ': break outer;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
val += ((c - 48) * factor);
|
||||
factor *= 0.1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return val * neg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard read() throws IOException {
|
||||
try (InputStream finalStream = inputStream) {
|
||||
load(finalStream);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final BufferedImage getTexture(String file) throws IOException {
|
||||
BufferedImage texture = textures.get(file);
|
||||
if (texture == null) {
|
||||
texture = ImageIO.read(new File(root, file));
|
||||
textures.put(file, texture);
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
private void readLines(InputStream stream, Consumer<String> onEachLine, boolean nullTerminate) throws IOException {
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
|
||||
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
|
||||
if (line.isEmpty() || line.charAt(0) == '#') continue;
|
||||
onEachLine.accept(line);
|
||||
}
|
||||
if (nullTerminate) onEachLine.accept(null);
|
||||
}
|
||||
}
|
||||
|
||||
private final int toIntColor(float color) {
|
||||
return (int) (color * 256 + 0.5);
|
||||
}
|
||||
|
||||
private String getFileName(String arg) {
|
||||
String[] pathSplit = arg.split("[/|\\\\]");
|
||||
return pathSplit[pathSplit.length - 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
|
||||
}
|
||||
|
||||
private class Material {
|
||||
private double dissolve = 1;
|
||||
private int color = Integer.MIN_VALUE;
|
||||
private String texture;
|
||||
}
|
||||
|
||||
private final void loadMaterials(String fileName) throws IOException {
|
||||
File file = new File(root, fileName);
|
||||
if (!file.exists()) {
|
||||
Fawe.debug(".mtl not found: " + fileName);
|
||||
return;
|
||||
}
|
||||
Map<String, Material> mtl = materialFiles.get(fileName);
|
||||
if (mtl == null) {
|
||||
final Map<String, Material> tmp = mtl = new HashMap<>();
|
||||
materialFiles.put(fileName, tmp);
|
||||
readLines(new FileInputStream(file), new Consumer<String>() {
|
||||
|
||||
private String name;
|
||||
private Material material;
|
||||
private int index;
|
||||
|
||||
private void add() {
|
||||
if (material != null) {
|
||||
if (material.color == Integer.MIN_VALUE) {
|
||||
material.color = -1;
|
||||
}
|
||||
tmp.put(name, material);
|
||||
material = null;
|
||||
name = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(String s) {
|
||||
if (s == null) {
|
||||
add();
|
||||
return;
|
||||
}
|
||||
String[] args = s.split("[ ]+");
|
||||
switch (args[0]) {
|
||||
// Name
|
||||
case "newmtl": {
|
||||
add();
|
||||
material = new Material();
|
||||
name = args[1];
|
||||
break;
|
||||
}
|
||||
// Color
|
||||
case "Ka":
|
||||
if (material.color != Integer.MIN_VALUE) break;
|
||||
case "Kd": {
|
||||
float r = Float.parseFloat(args[1]);
|
||||
float g = Float.parseFloat(args[2]);
|
||||
float b = Float.parseFloat(args[3]);
|
||||
material.color = (toIntColor(r) << 16) + (toIntColor(g) << 8) + toIntColor(b);
|
||||
break;
|
||||
}
|
||||
// Density
|
||||
case "d": {
|
||||
material.dissolve = Double.parseDouble(args[1]);
|
||||
break;
|
||||
}
|
||||
case "Tr": {
|
||||
material.dissolve = 1.0 - Double.parseDouble(args[1]);
|
||||
break;
|
||||
}
|
||||
case "map_Ka":
|
||||
if (material.texture != null) break;
|
||||
case "map_Kd": {
|
||||
material.texture = getFileName(args[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
materials.putAll(mtl);
|
||||
}
|
||||
|
||||
private final Material getMaterial(String name) {
|
||||
Material mtl = materials.get(name);
|
||||
return mtl != null ? mtl : new Material();
|
||||
}
|
||||
|
||||
private void load(InputStream in) throws IOException {
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
|
||||
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
|
||||
if (line.isEmpty()) continue;
|
||||
char char0 = line.charAt(0);
|
||||
switch (char0) {
|
||||
case '#': continue;
|
||||
case 'v':
|
||||
switch (line.charAt(1)) {
|
||||
case ' ':
|
||||
case 'n': {
|
||||
Double.parseDouble("");
|
||||
break;
|
||||
}
|
||||
case 't': {
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'f': {
|
||||
|
||||
break;
|
||||
}
|
||||
case 'l':
|
||||
case 's':
|
||||
case 'o':
|
||||
case 'g':
|
||||
// Ignore
|
||||
break;
|
||||
default:
|
||||
String[] args = line.split(" ");
|
||||
switch (args[0]) {
|
||||
case "mtllib": {
|
||||
String[] pathSplit = args[1].split("[/|\\\\]");
|
||||
String fileName = pathSplit[pathSplit.length - 1];
|
||||
loadMaterials(fileName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// final File directory = file.getParentFile();
|
||||
// final Map<String, SimpleMaterial> materials = new HashMap<String, SimpleMaterial>();
|
||||
// final Map<Face, BufferedImage> textures = new HashMap<Face, BufferedImage>();
|
||||
// final Map<Face, Color> colors = new HashMap<Face, Color>();
|
||||
// final List<Vertex> v = new LinkedList<Vertex>();
|
||||
// final List<VertexTexture> vt = new LinkedList<VertexTexture>();
|
||||
// final List<Vertex> vn = new LinkedList<Vertex>();
|
||||
// final List<Face> f = new LinkedList<Face>();
|
||||
// final List<String[]> obj = new LinkedList<String[]>();
|
||||
// for (final String[] entry : obj) {
|
||||
// if (entry[0].equals("v") || entry[0].equals("vn")) {
|
||||
// if (entry.length == 1) {
|
||||
// VLogger.log("[ERROR] Invalid vertex or vertex normal entry found (no data)");
|
||||
// return null;
|
||||
// }
|
||||
// double x;
|
||||
// double y;
|
||||
// double z;
|
||||
// try {
|
||||
// x = Double.parseDouble(entry[1]);
|
||||
// y = Double.parseDouble(entry[2]);
|
||||
// z = Double.parseDouble(entry[3]);
|
||||
// }
|
||||
// catch (NumberFormatException | ArrayIndexOutOfBoundsException ex8) {
|
||||
// final RuntimeException ex5;
|
||||
// final RuntimeException ex = ex5;
|
||||
// VLogger.log("[ERROR] Invalid vertex or vertex normal entry found (not parseable data)");
|
||||
// return null;
|
||||
// }
|
||||
// if (entry[0].equals("v")) {
|
||||
// if (entry.length >= 6) {
|
||||
// try {
|
||||
// final float r = Float.parseFloat(entry[4]);
|
||||
// final float g = Float.parseFloat(entry[5]);
|
||||
// final float b = Float.parseFloat(entry[6]);
|
||||
// final Color c = new Color(r, g, b);
|
||||
// v.add(new Vertex(x, y, z, v.size() + 1, c));
|
||||
// continue;
|
||||
// }
|
||||
// catch (NumberFormatException | ArrayIndexOutOfBoundsException ex9) {
|
||||
// final RuntimeException ex6;
|
||||
// final RuntimeException ex = ex6;
|
||||
// VLogger.log("[ERROR] Invalid vertex color (not parseable data)");
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
// v.add(new Vertex(x, y, z, v.size() + 1));
|
||||
// }
|
||||
// else {
|
||||
// vn.add(new Vertex(x, y, z, vn.size() + 1));
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// if (!entry[0].equals("vt")) {
|
||||
// continue;
|
||||
// }
|
||||
// if (entry.length == 1) {
|
||||
// VLogger.log("[ERROR] Invalid vertex texture entry found (no data)");
|
||||
// return null;
|
||||
// }
|
||||
// double vt_u;
|
||||
// double vt_v;
|
||||
// try {
|
||||
// vt_u = Double.parseDouble(entry[1]);
|
||||
// vt_v = Double.parseDouble(entry[2]);
|
||||
// if (vt_u < 0.0 || vt_v < 0.0 || vt_u > 1.0 || vt_v > 1.0) {
|
||||
// VLogger.log("[ERROR] UV of vertex texture out of bounds");
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
// catch (NumberFormatException | ArrayIndexOutOfBoundsException ex10) {
|
||||
// final RuntimeException ex7;
|
||||
// final RuntimeException ex2 = ex7;
|
||||
// VLogger.log("[ERROR] Invalid vertex texture entry found (not parseable data)");
|
||||
// return null;
|
||||
// }
|
||||
// vt.add(new VertexTexture(vt_u, vt_v, vn.size() + 1));
|
||||
// }
|
||||
// }
|
||||
// VLogger.log("[IMPORT] Loaded " + v.size() + " vertexes");
|
||||
// VLogger.log("[IMPORT] Loaded " + vt.size() + " vertex textures");
|
||||
// VLogger.log("[IMPORT] Loaded " + vn.size() + " vertex normals");
|
||||
// BufferedImage usemtl_texture = null;
|
||||
// Color usemtl_color = null;
|
||||
// for (final String[] entry2 : obj) {
|
||||
// if (entry2[0].equals("usemtl")) {
|
||||
// if (entry2.length == 1) {
|
||||
// VLogger.log("[ERROR] Invalid usemtl entry");
|
||||
// return null;
|
||||
// }
|
||||
// SimpleMaterial material = (SimpleMaterial)materials.get(entry2[1]);
|
||||
// if (material == null) {
|
||||
// VLogger.log("[WARN] Material '" + entry2[1] + "' does not exist");
|
||||
// material = getFallbackMaterial();
|
||||
// VLogger.log("[WARN] Replacing with fallback material");
|
||||
// }
|
||||
// usemtl_texture = material.texture;
|
||||
// usemtl_color = material.color;
|
||||
// VLogger.log("[IMPORT] Now using material '" + entry2[1] + "'");
|
||||
// }
|
||||
// else {
|
||||
// if (!entry2[0].equals("f")) {
|
||||
// continue;
|
||||
// }
|
||||
// if (entry2.length == 1) {
|
||||
// VLogger.log("[ERROR] Invalid face entry (no arguments)");
|
||||
// return null;
|
||||
// }
|
||||
// if (usemtl_texture == null && usemtl_color == null) {
|
||||
// VLogger.log("[WARN] Current Material has neither a texture nor a color");
|
||||
// usemtl_color = Colors.getGray(1.0f);
|
||||
// VLogger.log("[WARN] Using fallback color");
|
||||
// }
|
||||
// final Collection<FacePoint> points = new LinkedList<FacePoint>();
|
||||
// for (int i = 1; i < entry2.length; ++i) {
|
||||
// final String[] comp = entry2[i].split("/");
|
||||
// Integer comp_v;
|
||||
// Integer comp_vt;
|
||||
// Integer comp_vn;
|
||||
// try {
|
||||
// comp_v = Integer.parseInt(comp[0]);
|
||||
// comp_vt = ((comp.length <= 1 || comp[1].isEmpty()) ? null : Integer.parseInt(comp[1]));
|
||||
// comp_vn = ((comp.length <= 2 || comp[2].isEmpty()) ? null : Integer.parseInt(comp[2]));
|
||||
// }
|
||||
// catch (NumberFormatException ex3) {
|
||||
// final StringBuilder debug = new StringBuilder();
|
||||
// String[] array;
|
||||
// for (int length = (array = comp).length, j = 0; j < length; ++j) {
|
||||
// final String segment = array[j];
|
||||
// debug.append(segment);
|
||||
// debug.append("/");
|
||||
// }
|
||||
// VLogger.log("[ERROR] Face point failed to load (" + (Object)debug + ")");
|
||||
// return null;
|
||||
// }
|
||||
// try {
|
||||
// final FacePoint point = new FacePoint();
|
||||
// point.v = v.get((int)comp_v - 1);
|
||||
// point.vt = ((comp_vt == null) ? null : ((VertexTexture)vt.get((int)comp_vt - 1)));
|
||||
// point.vn = ((comp_vn == null) ? null : ((Vertex)vn.get((int)comp_vn - 1)));
|
||||
// points.add(point);
|
||||
// }
|
||||
// catch (IndexOutOfBoundsException ex4) {
|
||||
// VLogger.log("[ERROR] Face point reference to missing vertex");
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
// final Face face = new Face(points);
|
||||
// f.add(face);
|
||||
// if (usemtl_texture != null) {
|
||||
// textures.put(face, usemtl_texture);
|
||||
// }
|
||||
// if (usemtl_color == null) {
|
||||
// continue;
|
||||
// }
|
||||
// colors.put(face, usemtl_color);
|
||||
// }
|
||||
// }
|
||||
// double minX = Double.MAX_VALUE;
|
||||
// double minY = Double.MAX_VALUE;
|
||||
// double minZ = Double.MAX_VALUE;
|
||||
// double maxX = -1.7976931348623157E308;
|
||||
// double maxY = -1.7976931348623157E308;
|
||||
// double maxZ = -1.7976931348623157E308;
|
||||
// for (final Face face2 : f) {
|
||||
// for (final FacePoint point2 : face2.points) {
|
||||
// final double x2 = point2.v.getX();
|
||||
// final double y2 = point2.v.getY();
|
||||
// final double z2 = point2.v.getZ();
|
||||
// if (x2 < minX) {
|
||||
// minX = x2;
|
||||
// }
|
||||
// else if (x2 > maxX) {
|
||||
// maxX = x2;
|
||||
// }
|
||||
// if (y2 < minY) {
|
||||
// minY = y2;
|
||||
// }
|
||||
// else if (y2 > maxY) {
|
||||
// maxY = y2;
|
||||
// }
|
||||
// if (z2 < minZ) {
|
||||
// minZ = z2;
|
||||
// }
|
||||
// else {
|
||||
// if (z2 <= maxZ) {
|
||||
// continue;
|
||||
// }
|
||||
// maxZ = z2;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// final double size = Math.max(maxX - minX, Math.max(maxY - minY, maxZ - minZ));
|
||||
// final double scale = size / (resolution - 1.0);
|
||||
// final List<Face> polygons = new LinkedList<Face>();
|
||||
// for (final Face face3 : f) {
|
||||
// polygons.addAll(shatterFace(face3, colors, textures));
|
||||
// }
|
||||
// VLogger.log("[IMPORT] " + f.size() + " faces -> " + polygons.size() + " polygons");
|
||||
// final Map<Position3D, Color> colormap = new HashMap<Position3D, Color>();
|
||||
// for (final Face poly : polygons) {
|
||||
// final FacePoint a = (FacePoint)poly.points.get(0);
|
||||
// final FacePoint b2 = (FacePoint)poly.points.get(1);
|
||||
// final FacePoint c2 = (FacePoint)poly.points.get(2);
|
||||
// final Vector3D vAB = new Vector3D((Point3D)a.v, (Point3D)b2.v);
|
||||
// final Vector3D vAC = new Vector3D((Point3D)a.v, (Point3D)c2.v);
|
||||
// final float lAB = (float)vAB.length();
|
||||
// final float lAC = (float)vAC.length();
|
||||
// double[] array3;
|
||||
// if (a.vt == null || b2.vt == null) {
|
||||
// final double[] array2 = array3 = new double[2];
|
||||
// array2[1] = (array2[0] = 0.0);
|
||||
// }
|
||||
// else {
|
||||
// final double[] array4 = array3 = new double[2];
|
||||
// array4[0] = b2.vt.u - a.vt.u;
|
||||
// array4[1] = b2.vt.v - a.vt.v;
|
||||
// }
|
||||
// final double[] uvAB = array3;
|
||||
// double[] array6;
|
||||
// if (a.vt == null || c2.vt == null) {
|
||||
// final double[] array5 = array6 = new double[2];
|
||||
// array5[1] = (array5[0] = 0.0);
|
||||
// }
|
||||
// else {
|
||||
// final double[] array7 = array6 = new double[2];
|
||||
// array7[0] = c2.vt.u - a.vt.u;
|
||||
// array7[1] = c2.vt.v - a.vt.v;
|
||||
// }
|
||||
// final double[] uvAC = array6;
|
||||
// double[] array9;
|
||||
// if (a.vt == null) {
|
||||
// final double[] array8 = array9 = new double[2];
|
||||
// array8[1] = (array8[0] = 0.0);
|
||||
// }
|
||||
// else {
|
||||
// final double[] array10 = array9 = new double[2];
|
||||
// array10[0] = a.vt.u;
|
||||
// array10[1] = a.vt.v;
|
||||
// }
|
||||
// final double[] uvA = array9;
|
||||
// final Vector3D i2 = vAB.clone();
|
||||
// i2.normalize();
|
||||
// i2.multiply(scale);
|
||||
// final Vector3D i3 = vAC.clone();
|
||||
// i3.normalize();
|
||||
// i3.multiply(scale);
|
||||
// final BufferedImage texture = (BufferedImage)textures.get(poly);
|
||||
// final Color poly_color = (Color)colors.get(poly);
|
||||
// final int maxW = (texture == null) ? 0 : (texture.getWidth() - 1);
|
||||
// final int maxH = (texture == null) ? 0 : (texture.getHeight() - 1);
|
||||
// final double l = scale / 2.0;
|
||||
// for (float aloop = 0.0f; aloop < lAB; aloop += l) {
|
||||
// for (float bloop = 0.0f; bloop < lAC; bloop += l) {
|
||||
// final float ratio1 = aloop / lAB;
|
||||
// final float ratio2 = bloop / lAC;
|
||||
// if (ratio1 + ratio2 > 1.0f) {
|
||||
// break;
|
||||
// }
|
||||
// final Point3D point3 = a.v.clone();
|
||||
// point3.add(vAB.clone().multiply((double)ratio1));
|
||||
// point3.add(vAC.clone().multiply((double)ratio2));
|
||||
// final double colorU = uvA[0] + uvAB[0] * ratio1 + uvAC[0] * ratio2;
|
||||
// final double colorV = uvA[1] + uvAB[1] * ratio1 + uvAC[1] * ratio2;
|
||||
// Color pointcolor = null;
|
||||
// if (texture == null) {
|
||||
// if (poly.hasVertexColors()) {
|
||||
// final WeightedColor cA = new WeightedColor(a.v.getColor().getRGB(), 1.0f - ratio1 - ratio2);
|
||||
// final WeightedColor cB = new WeightedColor(b2.v.getColor().getRGB(), ratio1);
|
||||
// final WeightedColor cC = new WeightedColor(c2.v.getColor().getRGB(), ratio2);
|
||||
// pointcolor = Colors.blendColors(new WeightedColor[] { cA, cB, cC });
|
||||
// }
|
||||
// else {
|
||||
// pointcolor = poly_color;
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// pointcolor = new Color(texture.getRGB((int)Math.floor((double)maxW * colorU), (int)Math.floor((double)maxH - maxH * colorV)), true);
|
||||
// }
|
||||
// if (pointcolor.getAlpha() != 0) {
|
||||
// point3.divide(scale);
|
||||
// colormap.put(point3.toPositionRound(), pointcolor);
|
||||
// colormap.put(point3.toPositionFloor(), pointcolor);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// VLogger.log("[IMPORT] Import complete, loaded " + f.size() + " faces");
|
||||
// VLogger.log("[IMPORT] Import complete, created " + colormap.size() + " voxels");
|
||||
// return new VoxelBox(colormap);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -20,6 +20,8 @@
|
||||
package com.sk89q.worldedit.extent.clipboard.io.legacycompat;
|
||||
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
import java.util.Map;
|
||||
|
@@ -26,6 +26,8 @@ import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
|
Reference in New Issue
Block a user