Fixed schematic exporting (mostly)

This commit is contained in:
Jesse Boyd 2016-06-20 01:34:02 +10:00
parent 4c59ffc371
commit 706b44a26a
7 changed files with 303 additions and 9 deletions

View File

@ -16,6 +16,7 @@ import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.blocks.BaseBlock;
import java.awt.Color;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
@ -68,6 +69,8 @@ public class FaweCache {
*/
public final static PseudoRandom RANDOM = new PseudoRandom();
public final static Color[] CACHE_COLOR = new Color[Short.MAX_VALUE];
/**
* Get the cached BaseBlock object for an id/data<br>
* - The block is immutable
@ -106,6 +109,18 @@ public class FaweCache {
return getCombined(block.getId(), block.getData());
}
public static Color getColor(int id, int data) {
Color exact = CACHE_COLOR[getCombined(id, data)];
if (exact != null) {
return exact;
}
Color base = CACHE_COLOR[getCombined(id, 0)];
if (base != null) {
return base;
}
return CACHE_COLOR[0];
}
static {
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
@ -159,6 +174,75 @@ public class FaweCache {
}
};
}
CACHE_COLOR[getCombined(0, 0)] = new Color(128, 128, 128); //Air
CACHE_COLOR[getCombined(1, 0)] = new Color(180, 180, 180); //stone
CACHE_COLOR[getCombined(2, 0)] = new Color(0, 225, 0); //grass
CACHE_COLOR[getCombined(3, 0)] = new Color(168, 117, 68); //dirt
CACHE_COLOR[getCombined(4, 0)] = new Color(125, 125, 125); //cobblestone
CACHE_COLOR[getCombined(5, 0)] = new Color(185, 133, 83); //wood planks
CACHE_COLOR[getCombined(6, 0)] = new Color(0, 210, 0); //saplings
CACHE_COLOR[getCombined(7, 0)] = new Color(60, 60, 60); //bedrock
CACHE_COLOR[getCombined(8, 0)] = new Color(0, 0, 255); //water new Color(flowing)
CACHE_COLOR[getCombined(9, 0)] = new Color(0, 0, 235); //water new Color(stationary)
CACHE_COLOR[getCombined(10, 0)] = new Color(255, 155, 102); //lava new Color(flowing)
CACHE_COLOR[getCombined(11, 0)] = new Color(255, 129, 61); //lava new Color(stationary)
CACHE_COLOR[getCombined(12, 0)] = new Color(228, 216, 174); //sand
CACHE_COLOR[getCombined(13, 0)] = new Color(190, 190, 210); //gravel
CACHE_COLOR[getCombined(14, 0)] = new Color(245, 232, 73); //gold ore
CACHE_COLOR[getCombined(15, 0)] = new Color(211, 179, 160); //iron ore
CACHE_COLOR[getCombined(16, 0)] = new Color(61, 61, 61); //coal ore
CACHE_COLOR[getCombined(17, 0)] = new Color(165, 103, 53); //wood
CACHE_COLOR[getCombined(18, 0)] = new Color(76, 150, 24); //leaves
CACHE_COLOR[getCombined(20, 0)] = new Color(158, 255, 243); //glass
CACHE_COLOR[getCombined(24, 0)] = new Color(226, 206, 140); //sandstone
CACHE_COLOR[getCombined(31, 0)] = new Color(0, 210, 0); //long grass
CACHE_COLOR[getCombined(32, 0)] = new Color(224, 162, 64); //shrub
CACHE_COLOR[getCombined(37, 0)] = new Color(255, 248, 56); //yellow flower
CACHE_COLOR[getCombined(38, 0)] = new Color(225, 0, 0); //red rose
CACHE_COLOR[getCombined(41, 0)] = new Color(255, 215, 0); //gold block
CACHE_COLOR[getCombined(42, 0)] = new Color(135, 135, 135); //iron block
CACHE_COLOR[getCombined(44, 0)] = new Color(165, 165, 165); //step
CACHE_COLOR[getCombined(50, 0)] = new Color(255, 248, 56); //torch
CACHE_COLOR[getCombined(53, 0)] = new Color(185, 133, 83); //wood stairs
CACHE_COLOR[getCombined(59, 0)] = new Color(205, 222, 61); //wheat crops
CACHE_COLOR[getCombined(65, 0)] = new Color(185, 133, 83); //ladder
CACHE_COLOR[getCombined(67, 0)] = new Color(125, 125, 125); //cobblestone stairs
CACHE_COLOR[getCombined(78, 0)] = new Color(230, 255, 255); //snow layer
CACHE_COLOR[getCombined(79, 0)] = new Color(180, 255, 236); //ice
CACHE_COLOR[getCombined(81, 0)] = new Color(76, 150, 24); //cactus
CACHE_COLOR[getCombined(82, 0)] = new Color(150, 150, 180); //clay
CACHE_COLOR[getCombined(83, 0)] = new Color(89, 255, 89); //reed
CACHE_COLOR[getCombined(85, 0)] = new Color(185, 133, 83); //wood fence
CACHE_COLOR[getCombined(99, 0)] = new Color(168, 125, 99); //large brown mushroom
CACHE_COLOR[getCombined(100, 0)] = new Color(186, 27, 27); //large red mushroom
CACHE_COLOR[getCombined(102, 0)] = new Color(158, 255, 243); //glass pane
CACHE_COLOR[getCombined(106, 0)] = new Color(0, 150, 0); //vines
CACHE_COLOR[getCombined(110, 0)] = new Color(100, 90, 100); //mycelium
CACHE_COLOR[getCombined(111, 0)] = new Color(96, 188, 30); //lily pad
CACHE_COLOR[getCombined(128, 0)] = new Color(226, 206, 140); //sandstone stairs
CACHE_COLOR[getCombined(134, 0)] = new Color(185, 133, 83); //spruce wood stairs
CACHE_COLOR[getCombined(141, 0)] = new Color(205, 222, 61); //carrot crops
CACHE_COLOR[getCombined(142, 0)] = new Color(205, 222, 61); //potato crops
CACHE_COLOR[getCombined(161, 0)] = new Color(67, 132, 21); //dark oak leaves
CACHE_COLOR[getCombined(38, 8)] = new Color(255, 250, 155); //daisy flower
CACHE_COLOR[getCombined(175, 8)] = new Color(0, 200, 0); //double tall grass and flowers top
CACHE_COLOR[getCombined(35, 0)] = new Color(254, 254, 254); // White - Wools colors borrowed from Sk89q's draw script
CACHE_COLOR[getCombined(35, 1)] = new Color(255, 100, 0); // Orange
CACHE_COLOR[getCombined(35, 2)] = new Color(200, 0, 200); // Magenta
CACHE_COLOR[getCombined(35, 3)] = new Color(87, 132, 223); // Light blue
CACHE_COLOR[getCombined(35, 4)] = new Color(255, 255, 0); // Yellow
CACHE_COLOR[getCombined(35, 5)] = new Color(0, 255, 0); // Green
CACHE_COLOR[getCombined(35, 6)] = new Color(255, 180, 200); // Pink
CACHE_COLOR[getCombined(35, 7)] = new Color(72, 72, 72); // Gray
CACHE_COLOR[getCombined(35, 8)] = new Color(173, 173, 173); // Light grey
CACHE_COLOR[getCombined(35, 9)] = new Color(0, 100, 160); // Cyan
CACHE_COLOR[getCombined(35, 10)] = new Color(120, 0, 200); // Purple
CACHE_COLOR[getCombined(35, 11)] = new Color(0, 0, 175); // Blue
CACHE_COLOR[getCombined(35, 12)] = new Color(100, 60, 0); // Brown
CACHE_COLOR[getCombined(35, 13)] = new Color(48, 160, 0); // Cactus green
CACHE_COLOR[getCombined(35, 14)] = new Color(255, 0, 0); // Red
CACHE_COLOR[getCombined(35, 15)] = new Color(0, 0, 0); // Black
}
/**

View File

@ -94,15 +94,23 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
if (!air) {
continue;
}
for (int y2 = 0; y2 < 16; y2++) {
for (int y2 = 0; y2 < height; y2++) {
pos.x = x;
pos.z = z;
pos.y = y1 + y2;
int yy = y1 + y2;
if (yy >= height) {
break;
}
task.run(pos, EditSession.nullBlock);
}
continue;
}
for (int y2 = 0; y2 < idArray.length; y2++) {
int yy = y1 + y2;
if (yy >= height) {
break;
}
int id = idArray[y2] & 0xFF;
if (id == 0 && !air) {
continue;

View File

@ -0,0 +1,177 @@
package com.boydti.fawe.object.schematic;
import com.boydti.fawe.FaweCache;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.registry.WorldData;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
public class PNGWriter implements ClipboardWriter {
private final ImageOutputStream out;
public PNGWriter(OutputStream out) throws IOException {
this.out = ImageIO.createImageOutputStream(out);
}
public static Color getTopColor(int id, int data) {
return FaweCache.getColor(id, data);
}
public static Color getRightColor(int id, int data) {
return FaweCache.getColor(id, data).darker();
}
public static Color getLeftColor(int id, int data) {
return FaweCache.getColor(id, data).brighter();
}
@Override
public void write(Clipboard clipboard, WorldData data) throws IOException {
Region region = clipboard.getRegion();
int width = region.getWidth();
int height = region.getHeight();
int length = region.getLength();
int imageSize = 1080;
BufferedImage img = new BufferedImage(imageSize, imageSize, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
double d = Math.min((double) imageSize / length, (double) imageSize / width) / 3;
double d_2 = d/2;
double cx = (double) imageSize / 2;
double cy = (double) imageSize / 2;
int[] poly1X = new int[4];
int[] poly1Y = new int[4];
int[] poly2X = new int[4];
int[] poly2Y = new int[4];
int[] poly3X = new int[4];
int[] poly3Y = new int[4];
double[] dpxj = new double[length];
double[] dpxi = new double[Math.max(256, width)];
double[] dpyj = new double[length];
double[] dpyi = new double[Math.max(256, width)];
double[] hd = new double[256];
for (int i = 0; i < hd.length; i++) {
}
for (int j = 0; j < dpxj.length; j++) {
dpxj[j] = cx + j * d;
dpyj[j] = imageSize + d + j * d_2;
}
for (int i = 0; i < Math.max(256, dpxi.length); i++) {
dpxi[i] = i * d;
dpyi[i] = i * d_2;
}
g2.setColor(new Color(0, 0, 0));
g2.drawRect(0, 0, imageSize - 1, imageSize - 1);
boolean fill = length * 4 < imageSize && width * 4 < imageSize;
Vector mutable = new Vector(0, 0, 0);
Vector mutableTop = new Vector(0, 0, 0);
Vector mutableRight = new Vector(0, 0, 0);
Vector mutableLeft = new Vector(0, 0, 0);
Vector min = clipboard.getMinimumPoint();
int y0 = min.getBlockY();
int z0 = min.getBlockZ();
int x0 = min.getBlockX();
for (int x = x0; x < x0 + width; x++) {
mutable.x = x;
mutableTop.x = x;
mutableRight.x = x;
mutableLeft.x = x + 1;
int xx = x - x0;
double cpx1 = -dpxi[xx];
double cpy1 = dpyi[xx];
for (int z = z0; z < z0 + length; z++) {
mutable.z = z;
mutableTop.z = z;
mutableRight.z = z + 1;
mutableLeft.z = z;
int zz = z - z0;
double cpx = cpx1 + dpxj[zz];
double cpy2 = cpy1 + dpyj[zz];
for (int y = y0; y < y0 + height; y++) {
mutable.y = y;
BaseBlock block = clipboard.getBlock(mutable);
if (block == EditSession.nullBlock) {
continue;
}
mutableTop.y = y + 1;
mutableRight.y = y;
mutableLeft.y = y;
if (clipboard.getBlock(mutableTop) != EditSession.nullBlock && clipboard.getBlock(mutableRight) != EditSession.nullBlock && clipboard.getBlock(mutableLeft) != EditSession.nullBlock) {
continue;
}
double cpy = cpy2 - dpxi[y - y0];
poly1X[0] = (int) (cpx);
poly1Y[0] = (int) (cpy);
poly1X[1] = (int) (cpx - d);
poly1Y[1] = (int) (cpy - d_2);
poly1X[2] = (int) (cpx);
poly1Y[2] = (int) (cpy - d);
poly1X[3] = (int) (cpx + d);
poly1Y[3] = (int) (cpy - d_2);
poly2X[0] = (int) (cpx);
poly2Y[0] = (int) (cpy);
poly2X[1] = (int) (cpx + d);
poly2Y[1] = (int) (cpy - d_2);
poly2X[2] = (int) (cpx + d);
poly2Y[2] = (int) (cpy + d_2 + dpxi[0]);
poly2X[3] = (int) (cpx);
poly2Y[3] = (int) (cpy + dpxi[1]);
poly3X[0] = (int) (cpx);
poly3Y[0] = (int) (cpy);
poly3X[1] = (int) (cpx - d);
poly3Y[1] = (int) (cpy - d_2);
poly3X[2] = (int) (cpx - d);
poly3Y[2] = (int) (cpy + d_2 + dpxi[0]);
poly3X[3] = (int) (cpx);
poly3Y[3] = (int) (cpy + dpxi[1]);
Color colorTop = getTopColor(block.getId(), block.getData());
Color colorRight = getRightColor(block.getId(), block.getData());
Color colorLeft = getLeftColor(block.getId(), block.getData());
if (fill) {
g2.setColor(colorTop);
g2.fillPolygon(poly1X, poly1Y, 4);
g2.setColor(colorRight);
g2.fillPolygon(poly2X, poly2Y, 4);
g2.setColor(colorLeft);
g2.fillPolygon(poly3X, poly3Y, 4);
} else {
g2.setColor(colorTop);
g2.drawPolygon(poly1X, poly1Y, 4);
g2.setColor(colorRight);
g2.drawPolygon(poly2X, poly2Y, 4);
g2.setColor(colorLeft);
g2.drawPolygon(poly3X, poly3Y, 4);
}
}
}
}
ImageIO.write(img, "png", out);
}
@Override
public void close() throws IOException {
out.close();
}
}

View File

@ -86,8 +86,8 @@ public class FaweSchematicHandler extends SchematicHandler {
for (RegionWrapper region : regions) {
for (int z = region.minZ; z <= region.maxZ; z++) {
mutable.z = z - region.minZ;
for (int y = 0; y < 256; y++) {
mutable.y = y;
for (int y = region.minY; y <= Math.min(255, region.maxY); y++) {
mutable.y = y - region.minY;
for (int x = region.minX; x <= region.maxX; x++) {
mutable.x = x - region.minX;
BaseBlock block = editSession.getLazyBlock(x, y, z);

View File

@ -925,7 +925,6 @@ public class EditSession implements Extent {
@Nullable
public Entity createEntity(final com.sk89q.worldedit.util.Location location, final BaseEntity entity) {
Entity result = this.bypassNone.createEntity(location, entity);
System.out.println("RESULT: " + result);
return result;
}

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.extent.clipboard.io;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
import com.boydti.fawe.object.schematic.FaweFormat;
import com.boydti.fawe.object.schematic.PNGWriter;
import com.boydti.fawe.object.schematic.StructureFormat;
import com.boydti.fawe.util.MainUtil;
import com.sk89q.jnbt.NBTConstants;
@ -137,6 +138,28 @@ public enum ClipboardFormat {
}
},
PNG("png") {
@Override
public ClipboardReader getReader(InputStream inputStream) throws IOException {
return null;
}
@Override
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
return new PNGWriter(outputStream);
}
@Override
public String getExtension() {
return "png";
}
@Override
public boolean isFormat(File file) {
return file.getName().endsWith(".png");
}
},
/**
* The FAWE file format:
* - Streamable for known dimensions with mode 0

View File

@ -129,6 +129,9 @@ public class SchematicWriter implements ClipboardWriter {
throw new IllegalArgumentException("Length of region too large for a .schematic");
}
System.out.println(clipboard.getMinimumPoint());
System.out.println(clipboard.getMaximumPoint());
// ====================================================================
// Metadata
// ====================================================================
@ -152,11 +155,11 @@ public class SchematicWriter implements ClipboardWriter {
// Precalculate index vars
int area = width * length;
final int[] yarea = new int[height];
final int[] zwidth = new int[width];
final int[] zwidth = new int[length];
for (int i = 0; i < height; i++) {
yarea[i] = i * area;
}
for (int i = 0; i < width; i++) {
for (int i = 0; i < length; i++) {
zwidth[i] = i * width;
}
if (clipboard instanceof BlockArrayClipboard) {
@ -165,9 +168,9 @@ public class SchematicWriter implements ClipboardWriter {
faweClip.forEach(forEach, false);
addBlocks = forEach.addBlocks;
} else {
final int mx = (int) min.x;
final int my = (int) min.y;
final int mz = (int) min.z;
final int mx = min.getBlockX();
final int my = min.getBlockY();
final int mz = min.getBlockZ();
Vector mutable = new Vector(0, 0, 0);
ForEach forEach = new ForEach(yarea, zwidth, blocks, blockData, tileEntities);
for (Vector point : region) {