Optimize schem paste + add MCAWriter to anvil
This commit is contained in:
parent
11327d49e1
commit
bb56a39792
@ -19,6 +19,7 @@ import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BlockType;
|
||||
import com.sk89q.worldedit.blocks.ImmutableBlock;
|
||||
import com.sk89q.worldedit.blocks.ImmutableDatalessBlock;
|
||||
import com.sk89q.worldedit.blocks.ImmutableNBTBlock;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
||||
import java.awt.Color;
|
||||
@ -176,7 +177,9 @@ public class FaweCache {
|
||||
for (int i = 0; i < Character.MAX_VALUE; i++) {
|
||||
int id = i >> 4;
|
||||
int data = i & 0xf;
|
||||
if (FaweCache.hasData(id)) {
|
||||
if (FaweCache.hasNBT(id)) {
|
||||
CACHE_BLOCK[i] = new ImmutableNBTBlock(id, data);
|
||||
} else if (FaweCache.hasData(id)) {
|
||||
CACHE_BLOCK[i] = new ImmutableBlock(id, data);
|
||||
} else {
|
||||
CACHE_BLOCK[i] = new ImmutableDatalessBlock(id);
|
||||
|
@ -2,6 +2,8 @@ package com.boydti.fawe.jnbt;
|
||||
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
@ -2,8 +2,6 @@ package com.boydti.fawe.jnbt.anvil;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.object.io.BufferedRandomAccessFile;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MutableBlockVector;
|
||||
@ -22,17 +20,19 @@ import com.sk89q.worldedit.world.registry.WorldData;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
public class HeightMapMCAGenerator implements Extent {
|
||||
public class HeightMapMCAGenerator extends MCAWriter implements Extent {
|
||||
private final MutableBlockVector mutable = new MutableBlockVector();
|
||||
private final ForkJoinPool pool = new ForkJoinPool();
|
||||
|
||||
final Int2ObjectOpenHashMap<char[][][]> blocks = new Int2ObjectOpenHashMap<>();
|
||||
private final ThreadLocal<int[]> indexStore = new ThreadLocal<int[]>() {
|
||||
@Override
|
||||
protected int[] initialValue() {
|
||||
return new int[256];
|
||||
}
|
||||
};
|
||||
|
||||
private final Int2ObjectOpenHashMap<char[][][]> blocks = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
private final byte[] heights;
|
||||
private final byte[] biomes;
|
||||
@ -40,11 +40,6 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
private final char[] main;
|
||||
private char[] overlay;
|
||||
|
||||
private final File folder;
|
||||
private final int length;
|
||||
private final int width;
|
||||
private final int area;
|
||||
|
||||
private boolean modifiedMain = false;
|
||||
|
||||
public HeightMapMCAGenerator(BufferedImage img, File regionFolder) {
|
||||
@ -53,17 +48,12 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
}
|
||||
|
||||
public HeightMapMCAGenerator(int width, int length, File regionFolder) {
|
||||
if (!regionFolder.exists()) {
|
||||
regionFolder.mkdirs();
|
||||
}
|
||||
this.folder = regionFolder;
|
||||
this.width = width;
|
||||
this.length = length;
|
||||
this.area = width * length;
|
||||
heights = new byte[area];
|
||||
biomes = new byte[area];
|
||||
floor = new char[area];
|
||||
main = new char[area];
|
||||
super(width, length, regionFolder);
|
||||
int area = getArea();
|
||||
heights = new byte[getArea()];
|
||||
biomes = new byte[getArea()];
|
||||
floor = new char[getArea()];
|
||||
main = new char[getArea()];
|
||||
char stone = (char) FaweCache.getCombined(1, 0);
|
||||
char grass = (char) FaweCache.getCombined(2, 0);
|
||||
Arrays.fill(main, stone);
|
||||
@ -72,30 +62,30 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
|
||||
public void setHeight(BufferedImage img) {
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
heights[index] = (byte) img.getRGB(x, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addCaves() throws WorldEditException {
|
||||
CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(width, 255, length));
|
||||
CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(getWidth(), 255, getLength()));
|
||||
addCaves(region);
|
||||
}
|
||||
|
||||
public void addSchems(Mask mask, WorldData worldData, ClipboardHolder[] clipboards, int rarity, boolean rotate) throws WorldEditException{
|
||||
CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(width, 255, length));
|
||||
CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(getWidth(), 255, getLength()));
|
||||
addSchems(region, mask, worldData, clipboards, rarity, rotate);
|
||||
}
|
||||
|
||||
public void addOre(Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws WorldEditException {
|
||||
CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(width, 255, length));
|
||||
CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(getWidth(), 255, getLength()));
|
||||
addOre(region, mask, material, size, frequency, rarity, minY, maxY);
|
||||
}
|
||||
|
||||
public void addDefaultOres(Mask mask) throws WorldEditException {
|
||||
addOres(new CuboidRegion(new Vector(0, 0, 0), new Vector(width, 255, length)), mask);
|
||||
addOres(new CuboidRegion(new Vector(0, 0, 0), new Vector(getWidth(), 255, getLength())), mask);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -105,7 +95,7 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
|
||||
@Override
|
||||
public Vector getMaximumPoint() {
|
||||
return new Vector(width - 1, 255, length - 1);
|
||||
return new Vector(getWidth() - 1, 255, getLength() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -115,7 +105,7 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
|
||||
@Override
|
||||
public boolean setBiome(Vector2D position, BaseBiome biome) {
|
||||
int index = position.getBlockZ() * width + position.getBlockX();
|
||||
int index = position.getBlockZ() * getWidth() + position.getBlockX();
|
||||
if (index < 0 || index >= heights.length) return false;
|
||||
biomes[index] = (byte) biome.getId();
|
||||
return true;
|
||||
@ -123,14 +113,14 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {
|
||||
int index = z * width + x;
|
||||
int index = z * getWidth() + x;
|
||||
if (index < 0 || index >= heights.length) return false;
|
||||
int height = heights[index] & 0xFF;
|
||||
char combined = (char) FaweCache.getCombined(block);
|
||||
if (y > height) {
|
||||
if (y == height + 1) {
|
||||
if (overlay == null) {
|
||||
overlay = new char[area];
|
||||
overlay = new char[getArea()];
|
||||
}
|
||||
overlay[index] = combined;
|
||||
return true;
|
||||
@ -174,7 +164,7 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
|
||||
@Override
|
||||
public BaseBiome getBiome(Vector2D position) {
|
||||
int index = position.getBlockZ() * width + position.getBlockX();
|
||||
int index = position.getBlockZ() * getWidth() + position.getBlockX();
|
||||
if (index < 0 || index >= heights.length) return EditSession.nullBiome;
|
||||
return FaweCache.CACHE_BIOME[biomes[index] & 0xFF];
|
||||
}
|
||||
@ -191,7 +181,7 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
|
||||
@Override
|
||||
public BaseBlock getLazyBlock(int x, int y, int z) {
|
||||
int index = z * width + x;
|
||||
int index = z * getWidth() + x;
|
||||
if (index < 0 || index >= heights.length) return EditSession.nullBlock;
|
||||
int height = heights[index] & 0xFF;
|
||||
if (y > height) {
|
||||
@ -232,23 +222,23 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
|
||||
@Override
|
||||
public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) {
|
||||
int index = z * width + x;
|
||||
int index = z * getWidth() + x;
|
||||
if (index < 0 || index >= heights.length) return y;
|
||||
return ((heights[index] & 0xFF) << 3) + (floor[index] & 0xFF) + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) {
|
||||
int index = z * width + x;
|
||||
int index = z * getWidth() + x;
|
||||
if (index < 0 || index >= heights.length) return y;
|
||||
return heights[index] & 0xFF;
|
||||
}
|
||||
|
||||
public void setBiome(BufferedImage img, byte biome, boolean white) {
|
||||
if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int height = img.getRGB(x, z) & 0xFF;
|
||||
if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) {
|
||||
biomes[index] = biome;
|
||||
@ -258,11 +248,11 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
}
|
||||
|
||||
private void setOverlay(BufferedImage img, char combined, boolean white) {
|
||||
if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (overlay == null) overlay = new char[area];
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (overlay == null) overlay = new char[getArea()];
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int height = img.getRGB(x, z) & 0xFF;
|
||||
if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) {
|
||||
overlay[index] = combined;
|
||||
@ -272,11 +262,11 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
}
|
||||
|
||||
private void setMain(BufferedImage img, char combined, boolean white) {
|
||||
if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
modifiedMain = true;
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int height = img.getRGB(x, z) & 0xFF;
|
||||
if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) {
|
||||
main[index] = combined;
|
||||
@ -286,10 +276,10 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
}
|
||||
|
||||
private void setFloor(BufferedImage img, char combined, boolean white) {
|
||||
if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int height = img.getRGB(x, z) & 0xFF;
|
||||
if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) {
|
||||
floor[index] = combined;
|
||||
@ -299,11 +289,11 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
}
|
||||
|
||||
private void setColumn(BufferedImage img, char combined, boolean white) {
|
||||
if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
modifiedMain = true;
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int height = img.getRGB(x, z) & 0xFF;
|
||||
if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) {
|
||||
main[index] = combined;
|
||||
@ -315,9 +305,9 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
|
||||
public void setBiome(Mask mask, byte biome) {
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
@ -330,10 +320,10 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
|
||||
private void setOverlay(Mask mask, char combined) {
|
||||
int index = 0;
|
||||
if (overlay == null) overlay = new char[area];
|
||||
for (int z = 0; z < length; z++) {
|
||||
if (overlay == null) overlay = new char[getArea()];
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
@ -346,9 +336,9 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
|
||||
private void setFloor(Mask mask, char combined) {
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
@ -362,9 +352,9 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
private void setMain(Mask mask, char combined) {
|
||||
modifiedMain = true;
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
@ -378,9 +368,9 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
private void setColumn(Mask mask, char combined) {
|
||||
modifiedMain = true;
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
@ -397,12 +387,12 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
setOverlay(img, (char) ((BlockPattern) pattern).getBlock().getCombined(), white);
|
||||
return;
|
||||
}
|
||||
if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (overlay == null) overlay = new char[area];
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (overlay == null) overlay = new char[getArea()];
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int height = img.getRGB(x, z) & 0xFF;
|
||||
if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) {
|
||||
mutable.mutX(x);
|
||||
@ -418,12 +408,12 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
setMain(img, (char) ((BlockPattern) pattern).getBlock().getCombined(), white);
|
||||
return;
|
||||
}
|
||||
if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
modifiedMain = true;
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int height = img.getRGB(x, z) & 0xFF;
|
||||
if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) {
|
||||
mutable.mutX(x);
|
||||
@ -439,11 +429,11 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
setFloor(img, (char) ((BlockPattern) pattern).getBlock().getCombined(), white);
|
||||
return;
|
||||
}
|
||||
if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int height = img.getRGB(x, z) & 0xFF;
|
||||
if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) {
|
||||
mutable.mutX(x);
|
||||
@ -459,12 +449,12 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
setColumn(img, (char) ((BlockPattern) pattern).getBlock().getCombined(), white);
|
||||
return;
|
||||
}
|
||||
if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
modifiedMain = true;
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int height = img.getRGB(x, z) & 0xFF;
|
||||
if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) {
|
||||
mutable.mutX(x);
|
||||
@ -483,10 +473,10 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
return;
|
||||
}
|
||||
int index = 0;
|
||||
if (overlay == null) overlay = new char[area];
|
||||
for (int z = 0; z < length; z++) {
|
||||
if (overlay == null) overlay = new char[getArea()];
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
@ -503,9 +493,9 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
return;
|
||||
}
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
@ -523,9 +513,9 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
}
|
||||
modifiedMain = true;
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
@ -543,9 +533,9 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
}
|
||||
modifiedMain = true;
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++){
|
||||
for (int x = 0; x < getWidth(); x++, index++){
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
@ -577,7 +567,7 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
}
|
||||
|
||||
private void setOverlay(int value) {
|
||||
if (overlay == null) overlay = new char[area];
|
||||
if (overlay == null) overlay = new char[getArea()];
|
||||
Arrays.fill(overlay, (char) value);
|
||||
}
|
||||
|
||||
@ -587,9 +577,9 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
return;
|
||||
}
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++) {
|
||||
for (int x = 0; x < getWidth(); x++, index++) {
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
@ -604,9 +594,9 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
return;
|
||||
}
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++) {
|
||||
for (int x = 0; x < getWidth(); x++, index++) {
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
@ -623,9 +613,9 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
return;
|
||||
}
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++) {
|
||||
for (int x = 0; x < getWidth(); x++, index++) {
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
@ -635,15 +625,15 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
}
|
||||
|
||||
public void setOverlay(Pattern value) {
|
||||
if (overlay == null) overlay = new char[area];
|
||||
if (overlay == null) overlay = new char[getArea()];
|
||||
if (value instanceof BlockPattern) {
|
||||
setOverlay(((BlockPattern) value).getBlock().getCombined());
|
||||
return;
|
||||
}
|
||||
int index = 0;
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < width; x++, index++) {
|
||||
for (int x = 0; x < getWidth(); x++, index++) {
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
@ -656,321 +646,194 @@ public class HeightMapMCAGenerator implements Extent {
|
||||
Arrays.fill(heights, (byte) value);
|
||||
}
|
||||
|
||||
public void generate() throws IOException {
|
||||
int bcx = 0;
|
||||
int bcz = 0;
|
||||
int tcx = (width - 1) >> 4;
|
||||
int tcz = (length - 1) >> 4;
|
||||
final ThreadLocal<MCAChunk> chunkStore = new ThreadLocal<MCAChunk>() {
|
||||
@Override
|
||||
protected MCAChunk initialValue() {
|
||||
MCAChunk chunk = new MCAChunk(null, 0, 0);
|
||||
chunk.biomes = new byte[256];
|
||||
return chunk;
|
||||
@Override
|
||||
public boolean shouldWrite(int chunkX, int chunkZ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MCAChunk write(MCAChunk chunk, int csx, int cex, int csz, int cez) {
|
||||
int cx = chunk.getX();
|
||||
int cz = chunk.getZ();
|
||||
int[] indexes = indexStore.get();
|
||||
for (int i = 0; i < chunk.ids.length; i++) {
|
||||
byte[] idsArray = chunk.ids[i];
|
||||
if (idsArray != null) {
|
||||
Arrays.fill(idsArray, (byte) 0);
|
||||
Arrays.fill(chunk.data[i], (byte) 0);
|
||||
}
|
||||
};
|
||||
final ThreadLocal<byte[]> byteStore1 = new ThreadLocal<byte[]>() {
|
||||
@Override
|
||||
protected byte[] initialValue() {
|
||||
return new byte[500000];
|
||||
}
|
||||
int index = 0;
|
||||
int maxY = 0;
|
||||
int minY = Integer.MAX_VALUE;
|
||||
int[] heightMap = chunk.getHeightMapArray();
|
||||
int globalIndex;
|
||||
for (int z = csz; z <= cez; z++) {
|
||||
globalIndex = z * getWidth() + csx;
|
||||
for (int x = csx; x <= cex; x++, index++, globalIndex++) {
|
||||
indexes[index] = globalIndex;
|
||||
int height = heights[globalIndex] & 0xFF;
|
||||
heightMap[index] = height;
|
||||
maxY = Math.max(maxY, height);
|
||||
minY = Math.min(minY, height);
|
||||
}
|
||||
};
|
||||
final ThreadLocal<byte[]> byteStore2 = new ThreadLocal<byte[]>() {
|
||||
@Override
|
||||
protected byte[] initialValue() {
|
||||
return new byte[500000];
|
||||
}
|
||||
};
|
||||
final ThreadLocal<Deflater> deflateStore = new ThreadLocal<Deflater>() {
|
||||
@Override
|
||||
protected Deflater initialValue() {
|
||||
Deflater deflater = new Deflater(1, false);
|
||||
return deflater;
|
||||
}
|
||||
};
|
||||
final ThreadLocal<int[]> indexStore = new ThreadLocal<int[]>() {
|
||||
@Override
|
||||
protected int[] initialValue() {
|
||||
return new int[256];
|
||||
}
|
||||
};
|
||||
}
|
||||
boolean hasOverlay = this.overlay != null;
|
||||
byte[] fileBuf = new byte[1 << 16];
|
||||
for (int mcaZ = 0; mcaZ <= (length >> 9); mcaZ++) {
|
||||
for (int mcaX = 0; mcaX <= (width >> 9); mcaX++) {
|
||||
final int fmcaX = mcaX;
|
||||
final int fmcaZ = mcaZ;
|
||||
File file = new File(folder, "r." + mcaX + "." + mcaZ + ".mca");
|
||||
if (!file.exists()) {
|
||||
file.createNewFile();
|
||||
}
|
||||
final BufferedRandomAccessFile raf = new BufferedRandomAccessFile(file, "rw", fileBuf);
|
||||
final byte[] header = new byte[4096];
|
||||
final byte[][] compressed = new byte[1024][];
|
||||
int bx = mcaX << 9;
|
||||
int bz = mcaZ << 9;
|
||||
int scx = bx >> 4;
|
||||
int ecx = Math.min(scx + 31, tcx);
|
||||
int scz = bz >> 4;
|
||||
int ecz = Math.min(scz + 31, tcz);
|
||||
short pair = MathMan.pairByte(mcaX, mcaZ);
|
||||
for (int cz = scz; cz <= ecz; cz++) {
|
||||
final int csz = cz << 4;
|
||||
final int cez = Math.min(csz + 15, length - 1);
|
||||
for (int cx = scx; cx <= ecx; cx++) {
|
||||
final int csx = cx << 4;
|
||||
final int cex = Math.min(csx + 15, width - 1);
|
||||
final int fcx = cx;
|
||||
final int fcz = cz;
|
||||
int chunkPair = MathMan.pair((short) cx, (short) cz);
|
||||
final char[][][] localBlocks = blocks.get(chunkPair);
|
||||
pool.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
MCAChunk chunk = chunkStore.get();
|
||||
int[] indexes = indexStore.get();
|
||||
for (int i = 0; i < chunk.ids.length; i++) {
|
||||
byte[] idsArray = chunk.ids[i];
|
||||
if (idsArray != null) {
|
||||
Arrays.fill(idsArray, (byte) 0);
|
||||
}
|
||||
byte[] dataArray = chunk.data[i];
|
||||
if (dataArray != null) {
|
||||
Arrays.fill(dataArray, (byte) 0);
|
||||
}
|
||||
}
|
||||
int index = 0;
|
||||
int maxY = 0;
|
||||
int minY = Integer.MAX_VALUE;
|
||||
int[] heightMap = chunk.getHeightMapArray();
|
||||
int globalIndex;
|
||||
for (int z = csz; z <= cez; z++) {
|
||||
globalIndex = z * width + csx;
|
||||
for (int x = csx; x <= cex; x++, index++, globalIndex++) {
|
||||
indexes[index] = globalIndex;
|
||||
int height = heights[globalIndex] & 0xFF;
|
||||
heightMap[index] = height;
|
||||
maxY = Math.max(maxY, height);
|
||||
minY = Math.min(minY, height);
|
||||
}
|
||||
}
|
||||
if (hasOverlay) {
|
||||
maxY++;
|
||||
}
|
||||
int maxLayer = maxY >> 4;
|
||||
int fillLayers = Math.max(0, (minY - 1)) >> 4;
|
||||
for (int layer = 0; layer <= maxLayer; layer++) {
|
||||
if (chunk.ids[layer] == null) {
|
||||
chunk.ids[layer] = new byte[4096];
|
||||
chunk.data[layer] = new byte[2048];
|
||||
chunk.skyLight[layer] = new byte[2048];
|
||||
chunk.blockLight[layer] = new byte[2048];
|
||||
}
|
||||
}
|
||||
if (modifiedMain) { // If the main block is modified, we can't short circuit this
|
||||
for (int layer = 0; layer < fillLayers; layer++) {
|
||||
index = 0;
|
||||
byte[] layerIds = chunk.ids[layer];
|
||||
byte[] layerDatas = chunk.data[layer];
|
||||
for (int z = csz; z <= cez; z++) {
|
||||
for (int x = csx; x <= cex; x++, index++) {
|
||||
globalIndex = indexes[index];
|
||||
char mainCombined = main[globalIndex];
|
||||
byte id = (byte) FaweCache.getId(mainCombined);
|
||||
int data = FaweCache.getData(mainCombined);
|
||||
if (data != 0) {
|
||||
for (int y = 0; y < 16; y++) {
|
||||
int mainIndex = index + (y << 8);
|
||||
chunk.setNibble(mainIndex, layerDatas, data);
|
||||
}
|
||||
}
|
||||
for (int y = 0; y < 16; y++) {
|
||||
layerIds[index + (y << 8)] = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int layer = 0; layer < fillLayers; layer++) {
|
||||
Arrays.fill(chunk.ids[layer], (byte) 1);
|
||||
}
|
||||
}
|
||||
for (int layer = fillLayers; layer <= maxLayer; layer++) {
|
||||
Arrays.fill(chunk.skyLight[layer], (byte) 255);
|
||||
byte[] layerIds = chunk.ids[layer];
|
||||
byte[] layerDatas = chunk.data[layer];
|
||||
index = 0;
|
||||
int startY = layer << 4;
|
||||
int endY = startY + 15;
|
||||
for (int z = csz; z <= cez; z++) {
|
||||
for (int x = csx; x <= cex; x++, index++) {
|
||||
globalIndex = indexes[index];
|
||||
int height = heightMap[index];
|
||||
int diff;
|
||||
if (height > endY) {
|
||||
diff = 16;
|
||||
} else if (height >= startY) {
|
||||
diff = height - startY;
|
||||
char floorCombined = floor[globalIndex];
|
||||
int id = FaweCache.getId(floorCombined);
|
||||
int floorIndex = index + ((height & 15) << 8);
|
||||
layerIds[floorIndex] = (byte) id;
|
||||
int data = FaweCache.getData(floorCombined);
|
||||
if (data != 0) {
|
||||
chunk.setNibble(floorIndex, layerDatas, data);
|
||||
}
|
||||
if (hasOverlay && height >= startY - 1 && height < endY) {
|
||||
char overlayCombined = overlay[globalIndex];
|
||||
id = FaweCache.getId(overlayCombined);
|
||||
int overlayIndex = index + (((height + 1) & 15) << 8);
|
||||
layerIds[overlayIndex] = (byte) id;
|
||||
data = FaweCache.getData(overlayCombined);
|
||||
if (data != 0) {
|
||||
chunk.setNibble(overlayIndex, layerDatas, data);
|
||||
}
|
||||
}
|
||||
} else if (hasOverlay && height == startY - 1) {
|
||||
char overlayCombined = overlay[globalIndex];
|
||||
int id = FaweCache.getId(overlayCombined);
|
||||
int overlayIndex = index + (((height + 1) & 15) << 8);
|
||||
layerIds[overlayIndex] = (byte) id;
|
||||
int data = FaweCache.getData(overlayCombined);
|
||||
if (data != 0) {
|
||||
chunk.setNibble(overlayIndex, layerDatas, data);
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
char mainCombined = main[globalIndex];
|
||||
byte id = (byte) FaweCache.getId(mainCombined);
|
||||
int data = FaweCache.getData(mainCombined);
|
||||
if (data != 0) {
|
||||
for (int y = 0; y < diff; y++) {
|
||||
int mainIndex = index + (y << 8);
|
||||
chunk.setNibble(mainIndex, layerDatas, data);
|
||||
}
|
||||
}
|
||||
for (int y = 0; y < diff; y++) {
|
||||
layerIds[index + (y << 8)] = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int maxYMod = 15 + (maxLayer << 4);
|
||||
for (int layer = (maxY >> 4) + 1; layer < 16; layer++) {
|
||||
chunk.ids[layer] = null;
|
||||
chunk.data[layer] = null;
|
||||
}
|
||||
index = 0;
|
||||
{ // Bedrock
|
||||
byte[] layerIds = chunk.ids[0];
|
||||
for (int z = csz; z <= cez; z++) {
|
||||
for (int x = csx; x <= cex; x++) {
|
||||
layerIds[index++] = (byte) 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (localBlocks != null) {
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
int by = layer << 4;
|
||||
int ty = by + 15;
|
||||
index = 0;
|
||||
for (int y = by; y <= ty; y++, index += 256) {
|
||||
char[][] yBlocks = localBlocks[y];
|
||||
if (yBlocks != null) {
|
||||
if (chunk.ids[layer] == null) {
|
||||
chunk.ids[layer] = new byte[4096];
|
||||
chunk.data[layer] = new byte[2048];
|
||||
chunk.skyLight[layer] = new byte[2048];
|
||||
chunk.blockLight[layer] = new byte[2048];
|
||||
}
|
||||
byte[] idsLayer = chunk.ids[layer];
|
||||
byte[] dataLayer = chunk.data[layer];
|
||||
for (int z = 0; z < yBlocks.length; z++) {
|
||||
char[] zBlocks = yBlocks[z];
|
||||
if (zBlocks != null) {
|
||||
int zIndex = index + (z << 4);
|
||||
for (int x = 0; x < zBlocks.length; x++, zIndex++) {
|
||||
char combined = zBlocks[x];
|
||||
if (combined == 0) continue;
|
||||
int id = FaweCache.getId(combined);
|
||||
if (!FaweCache.hasData(id)) {
|
||||
chunk.setIdUnsafe(idsLayer, zIndex, (byte) id);
|
||||
} else {
|
||||
chunk.setBlockUnsafe(idsLayer, dataLayer, zIndex, (byte) id, FaweCache.getData(combined));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
chunk.setLoc(null, fcx, fcz);
|
||||
byte[] bytes = chunk.toBytes(byteStore1.get());
|
||||
byte[] compressedBytes = MainUtil.compress(bytes, byteStore2.get(), deflateStore.get());
|
||||
int blocks = (compressed.length + 4095) >> 12;
|
||||
compressed[((fcx & 31)) + ((fcz & 31) << 5)] = compressedBytes.clone();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (hasOverlay) {
|
||||
maxY++;
|
||||
}
|
||||
int maxLayer = maxY >> 4;
|
||||
int fillLayers = Math.max(0, (minY - 1)) >> 4;
|
||||
for (int layer = 0; layer <= maxLayer; layer++) {
|
||||
if (chunk.ids[layer] == null) {
|
||||
chunk.ids[layer] = new byte[4096];
|
||||
chunk.data[layer] = new byte[2048];
|
||||
chunk.skyLight[layer] = new byte[2048];
|
||||
chunk.blockLight[layer] = new byte[2048];
|
||||
}
|
||||
}
|
||||
if (modifiedMain) { // If the main block is modified, we can't short circuit this
|
||||
for (int layer = 0; layer < fillLayers; layer++) {
|
||||
index = 0;
|
||||
byte[] layerIds = chunk.ids[layer];
|
||||
byte[] layerDatas = chunk.data[layer];
|
||||
for (int z = csz; z <= cez; z++) {
|
||||
for (int x = csx; x <= cex; x++, index++) {
|
||||
globalIndex = indexes[index];
|
||||
char mainCombined = main[globalIndex];
|
||||
byte id = (byte) FaweCache.getId(mainCombined);
|
||||
int data = FaweCache.getData(mainCombined);
|
||||
if (data != 0) {
|
||||
for (int y = 0; y < 16; y++) {
|
||||
int mainIndex = index + (y << 8);
|
||||
chunk.setNibble(mainIndex, layerDatas, data);
|
||||
}
|
||||
});
|
||||
}
|
||||
for (int y = 0; y < 16; y++) {
|
||||
layerIds[index + (y << 8)] = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||
pool.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
int totalLength = 8192;
|
||||
for (int i = 0; i < compressed.length; i++) {
|
||||
byte[] compressedBytes = compressed[i];
|
||||
if (compressedBytes != null) {
|
||||
int blocks = ((4095 + compressedBytes.length + 5) / 4096) * 4096;
|
||||
totalLength += blocks;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int layer = 0; layer < fillLayers; layer++) {
|
||||
Arrays.fill(chunk.ids[layer], (byte) 1);
|
||||
}
|
||||
}
|
||||
for (int layer = fillLayers; layer <= maxLayer; layer++) {
|
||||
Arrays.fill(chunk.skyLight[layer], (byte) 255);
|
||||
byte[] layerIds = chunk.ids[layer];
|
||||
byte[] layerDatas = chunk.data[layer];
|
||||
index = 0;
|
||||
int startY = layer << 4;
|
||||
int endY = startY + 15;
|
||||
for (int z = csz; z <= cez; z++) {
|
||||
for (int x = csx; x <= cex; x++, index++) {
|
||||
globalIndex = indexes[index];
|
||||
int height = heightMap[index];
|
||||
int diff;
|
||||
if (height > endY) {
|
||||
diff = 16;
|
||||
} else if (height >= startY) {
|
||||
diff = height - startY;
|
||||
char floorCombined = floor[globalIndex];
|
||||
int id = FaweCache.getId(floorCombined);
|
||||
int floorIndex = index + ((height & 15) << 8);
|
||||
layerIds[floorIndex] = (byte) id;
|
||||
int data = FaweCache.getData(floorCombined);
|
||||
if (data != 0) {
|
||||
chunk.setNibble(floorIndex, layerDatas, data);
|
||||
}
|
||||
if (hasOverlay && height >= startY - 1 && height < endY) {
|
||||
char overlayCombined = overlay[globalIndex];
|
||||
id = FaweCache.getId(overlayCombined);
|
||||
int overlayIndex = index + (((height + 1) & 15) << 8);
|
||||
layerIds[overlayIndex] = (byte) id;
|
||||
data = FaweCache.getData(overlayCombined);
|
||||
if (data != 0) {
|
||||
chunk.setNibble(overlayIndex, layerDatas, data);
|
||||
}
|
||||
raf.setLength(totalLength);
|
||||
int offset = 8192;
|
||||
for (int i = 0; i < compressed.length; i++) {
|
||||
byte[] compressedBytes = compressed[i];
|
||||
if (compressedBytes != null) {
|
||||
// Set header
|
||||
int index = i << 2;
|
||||
int offsetMedium = offset >> 12;
|
||||
int blocks = ((4095 + compressedBytes.length + 5) / 4096);
|
||||
header[index] = (byte) (offsetMedium >> 16);
|
||||
header[index + 1] = (byte) ((offsetMedium >> 8));
|
||||
header[index + 2] = (byte) ((offsetMedium >> 0));
|
||||
header[index + 3] = (byte) (blocks);
|
||||
// Write bytes
|
||||
int cx = (fmcaX << 5) + (i & 31);
|
||||
int cz = (fmcaZ << 5) + (i >> 5);
|
||||
raf.seek(offset);
|
||||
raf.writeInt(compressedBytes.length);
|
||||
raf.write(2);
|
||||
raf.write(compressedBytes);
|
||||
offset += blocks * 4096;
|
||||
}
|
||||
} else if (hasOverlay && height == startY - 1) {
|
||||
char overlayCombined = overlay[globalIndex];
|
||||
int id = FaweCache.getId(overlayCombined);
|
||||
int overlayIndex = index + (((height + 1) & 15) << 8);
|
||||
layerIds[overlayIndex] = (byte) id;
|
||||
int data = FaweCache.getData(overlayCombined);
|
||||
if (data != 0) {
|
||||
chunk.setNibble(overlayIndex, layerDatas, data);
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
char mainCombined = main[globalIndex];
|
||||
byte id = (byte) FaweCache.getId(mainCombined);
|
||||
int data = FaweCache.getData(mainCombined);
|
||||
if (data != 0) {
|
||||
for (int y = 0; y < diff; y++) {
|
||||
int mainIndex = index + (y << 8);
|
||||
chunk.setNibble(mainIndex, layerDatas, data);
|
||||
}
|
||||
}
|
||||
for (int y = 0; y < diff; y++) {
|
||||
layerIds[index + (y << 8)] = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int maxYMod = 15 + (maxLayer << 4);
|
||||
for (int layer = (maxY >> 4) + 1; layer < 16; layer++) {
|
||||
chunk.ids[layer] = null;
|
||||
chunk.data[layer] = null;
|
||||
}
|
||||
index = 0;
|
||||
{ // Bedrock
|
||||
byte[] layerIds = chunk.ids[0];
|
||||
for (int z = csz; z <= cez; z++) {
|
||||
for (int x = csx; x <= cex; x++) {
|
||||
layerIds[index++] = (byte) 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
int chunkPair = MathMan.pair((short) cx, (short) cz);
|
||||
char[][][] localBlocks = blocks.get(chunkPair);
|
||||
if (localBlocks != null) {
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
int by = layer << 4;
|
||||
int ty = by + 15;
|
||||
index = 0;
|
||||
for (int y = by; y <= ty; y++, index += 256) {
|
||||
char[][] yBlocks = localBlocks[y];
|
||||
if (yBlocks != null) {
|
||||
if (chunk.ids[layer] == null) {
|
||||
chunk.ids[layer] = new byte[4096];
|
||||
chunk.data[layer] = new byte[2048];
|
||||
chunk.skyLight[layer] = new byte[2048];
|
||||
chunk.blockLight[layer] = new byte[2048];
|
||||
}
|
||||
byte[] idsLayer = chunk.ids[layer];
|
||||
byte[] dataLayer = chunk.data[layer];
|
||||
for (int z = 0; z < yBlocks.length; z++) {
|
||||
char[] zBlocks = yBlocks[z];
|
||||
if (zBlocks != null) {
|
||||
int zIndex = index + (z << 4);
|
||||
for (int x = 0; x < zBlocks.length; x++, zIndex++) {
|
||||
char combined = zBlocks[x];
|
||||
if (combined == 0) continue;
|
||||
int id = FaweCache.getId(combined);
|
||||
if (!FaweCache.hasData(id)) {
|
||||
chunk.setIdUnsafe(idsLayer, zIndex, (byte) id);
|
||||
} else {
|
||||
chunk.setBlockUnsafe(idsLayer, dataLayer, zIndex, (byte) id, FaweCache.getData(combined));
|
||||
}
|
||||
}
|
||||
}
|
||||
raf.seek(0);
|
||||
raf.write(header);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
raf.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
183
core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWriter.java
Normal file
183
core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWriter.java
Normal file
@ -0,0 +1,183 @@
|
||||
package com.boydti.fawe.jnbt.anvil;
|
||||
|
||||
import com.boydti.fawe.object.io.BufferedRandomAccessFile;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
public abstract class MCAWriter {
|
||||
private final File folder;
|
||||
private final int length;
|
||||
private final int width;
|
||||
private final int area;
|
||||
|
||||
public MCAWriter(int width, int length, File regionFolder) {
|
||||
if (!regionFolder.exists()) {
|
||||
regionFolder.mkdirs();
|
||||
}
|
||||
this.folder = regionFolder;
|
||||
this.width = width;
|
||||
this.length = length;
|
||||
this.area = width * length;
|
||||
}
|
||||
|
||||
public final File getFolder() {
|
||||
return folder;
|
||||
}
|
||||
|
||||
public final int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public final int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public final int getArea() {
|
||||
return area;
|
||||
}
|
||||
|
||||
public abstract boolean shouldWrite(int chunkX, int chunkZ);
|
||||
|
||||
public abstract MCAChunk write(MCAChunk input, int startX, int endX, int startZ, int endZ);
|
||||
|
||||
public void generate() throws IOException {
|
||||
final ForkJoinPool pool = new ForkJoinPool();
|
||||
int bcx = 0;
|
||||
int bcz = 0;
|
||||
int tcx = (width - 1) >> 4;
|
||||
int tcz = (length - 1) >> 4;
|
||||
final ThreadLocal<MCAChunk> chunkStore = new ThreadLocal<MCAChunk>() {
|
||||
@Override
|
||||
protected MCAChunk initialValue() {
|
||||
MCAChunk chunk = new MCAChunk(null, 0, 0);
|
||||
chunk.biomes = new byte[256];
|
||||
return chunk;
|
||||
}
|
||||
};
|
||||
final ThreadLocal<byte[]> byteStore1 = new ThreadLocal<byte[]>() {
|
||||
@Override
|
||||
protected byte[] initialValue() {
|
||||
return new byte[500000];
|
||||
}
|
||||
};
|
||||
final ThreadLocal<byte[]> byteStore2 = new ThreadLocal<byte[]>() {
|
||||
@Override
|
||||
protected byte[] initialValue() {
|
||||
return new byte[500000];
|
||||
}
|
||||
};
|
||||
final ThreadLocal<Deflater> deflateStore = new ThreadLocal<Deflater>() {
|
||||
@Override
|
||||
protected Deflater initialValue() {
|
||||
Deflater deflater = new Deflater(Deflater.BEST_SPEED, false);
|
||||
return deflater;
|
||||
}
|
||||
};
|
||||
byte[] fileBuf = new byte[1 << 16];
|
||||
for (int mcaZ = 0; mcaZ <= (length >> 9); mcaZ++) {
|
||||
for (int mcaX = 0; mcaX <= (width >> 9); mcaX++) {
|
||||
final int fmcaX = mcaX;
|
||||
final int fmcaZ = mcaZ;
|
||||
File file = new File(folder, "r." + mcaX + "." + mcaZ + ".mca");
|
||||
if (!file.exists()) {
|
||||
file.createNewFile();
|
||||
}
|
||||
final BufferedRandomAccessFile raf = new BufferedRandomAccessFile(file, "rw", fileBuf);
|
||||
final byte[] header = new byte[4096];
|
||||
final byte[][] compressed = new byte[1024][];
|
||||
int bx = mcaX << 9;
|
||||
int bz = mcaZ << 9;
|
||||
int scx = bx >> 4;
|
||||
int ecx = Math.min(scx + 31, tcx);
|
||||
int scz = bz >> 4;
|
||||
int ecz = Math.min(scz + 31, tcz);
|
||||
short pair = MathMan.pairByte(mcaX, mcaZ);
|
||||
for (int cz = scz; cz <= ecz; cz++) {
|
||||
final int csz = cz << 4;
|
||||
final int cez = Math.min(csz + 15, length - 1);
|
||||
for (int cx = scx; cx <= ecx; cx++) {
|
||||
final int csx = cx << 4;
|
||||
final int cex = Math.min(csx + 15, width - 1);
|
||||
final int fcx = cx;
|
||||
final int fcz = cz;
|
||||
if (shouldWrite(cx, cz)) {
|
||||
pool.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
MCAChunk chunk = chunkStore.get();
|
||||
chunk.setLoc(null, fcx, fcz);
|
||||
chunk = write(chunk, csx, cex, csz, cez);
|
||||
if (chunk != null) {
|
||||
byte[] bytes = chunk.toBytes(byteStore1.get());
|
||||
byte[] compressedBytes = MainUtil.compress(bytes, byteStore2.get(), deflateStore.get());
|
||||
int blocks = (compressed.length + 4095) >> 12;
|
||||
compressed[((fcx & 31)) + ((fcz & 31) << 5)] = compressedBytes.clone();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||
pool.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
int totalLength = 8192;
|
||||
for (int i = 0; i < compressed.length; i++) {
|
||||
byte[] compressedBytes = compressed[i];
|
||||
if (compressedBytes != null) {
|
||||
int blocks = ((4095 + compressedBytes.length + 5) / 4096) * 4096;
|
||||
totalLength += blocks;
|
||||
}
|
||||
}
|
||||
raf.setLength(totalLength);
|
||||
int offset = 8192;
|
||||
for (int i = 0; i < compressed.length; i++) {
|
||||
byte[] compressedBytes = compressed[i];
|
||||
if (compressedBytes != null) {
|
||||
// Set header
|
||||
int index = i << 2;
|
||||
int offsetMedium = offset >> 12;
|
||||
int blocks = ((4095 + compressedBytes.length + 5) / 4096);
|
||||
header[index] = (byte) (offsetMedium >> 16);
|
||||
header[index + 1] = (byte) ((offsetMedium >> 8));
|
||||
header[index + 2] = (byte) ((offsetMedium >> 0));
|
||||
header[index + 3] = (byte) (blocks);
|
||||
// Write bytes
|
||||
int cx = (fmcaX << 5) + (i & 31);
|
||||
int cz = (fmcaZ << 5) + (i >> 5);
|
||||
raf.seek(offset);
|
||||
raf.writeInt(compressedBytes.length);
|
||||
raf.write(2);
|
||||
raf.write(compressedBytes);
|
||||
offset += blocks * 4096;
|
||||
}
|
||||
}
|
||||
raf.seek(0);
|
||||
raf.write(header);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
raf.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ package com.boydti.fawe.object.brush;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.boydti.fawe.object.clipboard.CPUOptimizedClipboard;
|
||||
import com.boydti.fawe.object.clipboard.FaweClipboard;
|
||||
import com.boydti.fawe.object.clipboard.OffsetFaweClipboard;
|
||||
@ -61,10 +60,10 @@ public class ErodeBrush implements Brush {
|
||||
}
|
||||
FaweClipboard finalBuffer = swap % 2 == 0 ? buffer1 : buffer2;
|
||||
|
||||
finalBuffer.forEach(new RunnableVal2<Vector, BaseBlock>() {
|
||||
finalBuffer.forEach(new FaweClipboard.BlockReader() {
|
||||
@Override
|
||||
public void run(Vector pos, BaseBlock block) {
|
||||
es.setBlock(pos.getBlockX() + bx, pos.getBlockY() + by, pos.getBlockZ() + bz, block);
|
||||
public void run(int x, int y, int z, BaseBlock block) {
|
||||
es.setBlock(x + bx, y + by, z + bz, block);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.boydti.fawe.object.clipboard;
|
||||
|
||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
@ -78,7 +77,7 @@ public class AbstractDelegateFaweClipboard extends FaweClipboard {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(RunnableVal2<Vector, BaseBlock> task, boolean air) {
|
||||
public void forEach(BlockReader task, boolean air) {
|
||||
parent.forEach(task, air);
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ package com.boydti.fawe.object.clipboard;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
||||
import com.boydti.fawe.object.IntegerTrio;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
@ -156,19 +155,15 @@ public class CPUOptimizedClipboard extends FaweClipboard {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(final RunnableVal2<Vector,BaseBlock> task, boolean air) {
|
||||
task.value1 = new Vector(0, 0, 0);
|
||||
public void forEach(final BlockReader task, boolean air) {
|
||||
for (int y = 0, index = 0; y < height; y++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++, index++) {
|
||||
task.value2 = getBlock(index);
|
||||
if (!air && task.value2.getId() == 0) {
|
||||
BaseBlock block = getBlock(index);
|
||||
if (!air && block.getId() == 0) {
|
||||
continue;
|
||||
}
|
||||
task.value1.mutX(x);
|
||||
task.value1.mutY(y);
|
||||
task.value1.mutZ(z);
|
||||
task.run();
|
||||
task.run(x, y, z, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,14 +5,12 @@ import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
||||
import com.boydti.fawe.object.IntegerTrio;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.boydti.fawe.object.io.BufferedRandomAccessFile;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
@ -233,6 +231,33 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
public static long start;
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
BaseBlock block = FaweCache.getBlock(0, 0);
|
||||
DiskOptimizedClipboard clip = new DiskOptimizedClipboard(443, 256, 443, new File("test"));
|
||||
start = System.currentTimeMillis();
|
||||
clip.forEach(new BlockReader() {
|
||||
@Override
|
||||
public void run(int x, int y, int z, BaseBlock value2) {
|
||||
|
||||
}
|
||||
}, true);
|
||||
clip.close();
|
||||
// BufferedRandomAccessFile raf = new BufferedRandomAccessFile(new File("test"), "rw");
|
||||
// int len = 50000000;
|
||||
// raf.setLength(len * 2);
|
||||
// long start = System.currentTimeMillis();
|
||||
// long total = 0;
|
||||
// for (int i = 0; i < len; i++) {
|
||||
// total += raf.readChar();
|
||||
// }
|
||||
// raf.close();
|
||||
System.out.println(System.currentTimeMillis() - start + "ms");
|
||||
// System.out.println("Total " + total);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamDatas(NBTStreamer.ByteReader task) {
|
||||
try {
|
||||
@ -257,29 +282,38 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(final RunnableVal2<Vector,BaseBlock> task, boolean air) {
|
||||
public void forEach(final BlockReader task, boolean air) {
|
||||
try {
|
||||
raf.seek(HEADER_SIZE);
|
||||
BlockVector pos = new BlockVector(0, 0, 0);
|
||||
IntegerTrio trio = new IntegerTrio();
|
||||
final boolean hasTile = !nbtMap.isEmpty();
|
||||
if (air) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int combinedId = raf.readChar();
|
||||
BaseBlock block = FaweCache.CACHE_BLOCK[combinedId];
|
||||
if (FaweCache.hasNBT(block.getId())) {
|
||||
trio.set(x, y, z);
|
||||
CompoundTag nbt = nbtMap.get(trio);
|
||||
if (nbt != null) {
|
||||
block = new BaseBlock(block.getId(), block.getData());
|
||||
block.setNbtData(nbt);
|
||||
if (hasTile) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
char combinedId = raf.readChar();
|
||||
BaseBlock block = FaweCache.CACHE_BLOCK[combinedId];
|
||||
if (block.canStoreNBTData()) {
|
||||
trio.set(x, y, z);
|
||||
CompoundTag nbt = nbtMap.get(trio);
|
||||
if (nbt != null) {
|
||||
block = new BaseBlock(block.getId(), block.getData());
|
||||
block.setNbtData(nbt);
|
||||
}
|
||||
}
|
||||
task.run(x, y, z, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
char combinedId = raf.readChar();
|
||||
BaseBlock block = FaweCache.CACHE_BLOCK[combinedId];
|
||||
task.run(x, y, z, block);
|
||||
}
|
||||
pos.mutX(x);
|
||||
pos.mutY(y);
|
||||
pos.mutZ(z);
|
||||
task.run(pos, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -298,10 +332,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
|
||||
block.setNbtData(nbt);
|
||||
}
|
||||
}
|
||||
pos.mutX(x);
|
||||
pos.mutY(y);
|
||||
pos.mutZ(z);
|
||||
task.run(pos, block);
|
||||
task.run(x, y, z, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.boydti.fawe.object.clipboard;
|
||||
|
||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
@ -50,23 +49,27 @@ public abstract class FaweClipboard {
|
||||
* @param task
|
||||
* @param air
|
||||
*/
|
||||
public abstract void forEach(final RunnableVal2<Vector,BaseBlock> task, boolean air);
|
||||
public abstract void forEach(BlockReader task, boolean air);
|
||||
|
||||
public static abstract class BlockReader {
|
||||
public abstract void run(int x, int y, int z, BaseBlock block);
|
||||
}
|
||||
|
||||
public void streamIds(final NBTStreamer.ByteReader task) {
|
||||
forEach(new RunnableVal2<Vector, BaseBlock>() {
|
||||
forEach(new BlockReader() {
|
||||
private int index = 0;
|
||||
@Override
|
||||
public void run(Vector pos, BaseBlock block) {
|
||||
public void run(int x, int y, int z, BaseBlock block) {
|
||||
task.run(index++, block.getId());
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
public void streamDatas(final NBTStreamer.ByteReader task) {
|
||||
forEach(new RunnableVal2<Vector, BaseBlock>() {
|
||||
forEach(new BlockReader() {
|
||||
private int index = 0;
|
||||
@Override
|
||||
public void run(Vector pos, BaseBlock block) {
|
||||
public void run(int x, int y, int z, BaseBlock block) {
|
||||
task.run(index++, block.getData());
|
||||
}
|
||||
}, true);
|
||||
@ -74,16 +77,16 @@ public abstract class FaweClipboard {
|
||||
|
||||
public List<CompoundTag> getTileEntities() {
|
||||
final List<CompoundTag> tiles = new ArrayList<>();
|
||||
forEach(new RunnableVal2<Vector, BaseBlock>() {
|
||||
forEach(new BlockReader() {
|
||||
private int index = 0;
|
||||
@Override
|
||||
public void run(Vector pos, BaseBlock block) {
|
||||
public void run(int x, int y, int z, BaseBlock block) {
|
||||
CompoundTag tag = block.getNbtData();
|
||||
if (tag != null) {
|
||||
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
|
||||
values.put("x", new IntTag(pos.getBlockX()));
|
||||
values.put("y", new IntTag(pos.getBlockY()));
|
||||
values.put("z", new IntTag(pos.getBlockZ()));
|
||||
values.put("x", new IntTag(x));
|
||||
values.put("y", new IntTag(y));
|
||||
values.put("z", new IntTag(z));
|
||||
tiles.add(tag);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
||||
import com.boydti.fawe.object.IntegerTrio;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -377,20 +376,26 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(final RunnableVal2<Vector,BaseBlock> task, boolean air) {
|
||||
public void forEach(final BlockReader task, final boolean air) {
|
||||
// Fawe.debug("Compressed: " + size() + "b | Uncompressed: " + (volume << 0x5) + "b");
|
||||
task.value1 = new Vector(0, 0, 0);
|
||||
for (int y = 0, index = 0; y < height; y++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++, index++) {
|
||||
task.value2 = getBlock(index);
|
||||
if (!air && task.value2.getId() == 0) {
|
||||
continue;
|
||||
if (air) {
|
||||
for (int y = 0, index = 0; y < height; y++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++, index++) {
|
||||
BaseBlock block = getBlock(index);
|
||||
task.run(x, y, z, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int y = 0, index = 0; y < height; y++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++, index++) {
|
||||
BaseBlock block = getBlock(index);
|
||||
if (block.getId() == 0) {
|
||||
task.run(x, y, z, block);
|
||||
}
|
||||
}
|
||||
task.value1.mutX(x);
|
||||
task.value1.mutY(y);
|
||||
task.value1.mutZ(z);
|
||||
task.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
package com.boydti.fawe.object.clipboard;
|
||||
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
|
||||
public class OffsetFaweClipboard extends AbstractDelegateFaweClipboard {
|
||||
@ -35,14 +33,11 @@ public class OffsetFaweClipboard extends AbstractDelegateFaweClipboard {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(final RunnableVal2<Vector, BaseBlock> task, boolean air) {
|
||||
super.forEach(new RunnableVal2<Vector, BaseBlock>() {
|
||||
public void forEach(final BlockReader task, boolean air) {
|
||||
super.forEach(new BlockReader() {
|
||||
@Override
|
||||
public void run(Vector value, BaseBlock block) {
|
||||
value.mutX(value.getX() - ox);
|
||||
value.mutY(value.getY() - oy);
|
||||
value.mutZ(value.getZ() - oz);
|
||||
task.run(value, block);
|
||||
public void run(int x, int y, int z, BaseBlock block) {
|
||||
task.run(x - ox, y - oy, z - oz, block);
|
||||
}
|
||||
}, air);
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.boydti.fawe.object.clipboard;
|
||||
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
@ -47,7 +46,7 @@ public class WorldCopyClipboard extends ReadOnlyClipboard {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(final RunnableVal2<Vector, BaseBlock> task, boolean air) {
|
||||
public void forEach(BlockReader task, boolean air) {
|
||||
Vector min = region.getMinimumPoint();
|
||||
Vector max = region.getMaximumPoint();
|
||||
final Vector pos = new Vector();
|
||||
@ -57,21 +56,18 @@ public class WorldCopyClipboard extends ReadOnlyClipboard {
|
||||
RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
|
||||
@Override
|
||||
public boolean apply(Vector pos) throws WorldEditException {
|
||||
int x = pos.getBlockX();
|
||||
int y = pos.getBlockY();
|
||||
int z = pos.getBlockZ();
|
||||
BaseBlock block = getBlockAbs(x, y, z);
|
||||
pos.mutX(x - mx);
|
||||
pos.mutY(y - my);
|
||||
pos.mutZ(z - mz);
|
||||
BaseBlock block = getBlockAbs(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
|
||||
int x = pos.getBlockX() - mx;
|
||||
int y = pos.getBlockY() - my;
|
||||
int z = pos.getBlockZ() - mz;
|
||||
CompoundTag tag = block.getNbtData();
|
||||
if (tag != null) {
|
||||
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
|
||||
values.put("x", new IntTag(pos.getBlockX()));
|
||||
values.put("y", new IntTag(pos.getBlockY()));
|
||||
values.put("z", new IntTag(pos.getBlockZ()));
|
||||
values.put("x", new IntTag(x));
|
||||
values.put("y", new IntTag(y));
|
||||
values.put("z", new IntTag(z));
|
||||
}
|
||||
task.run(pos, block);
|
||||
task.run(x, y, z, block);
|
||||
return true;
|
||||
}
|
||||
}, editSession);
|
||||
@ -82,27 +78,21 @@ public class WorldCopyClipboard extends ReadOnlyClipboard {
|
||||
RegionVisitor visitor = new RegionVisitor(cuboidEquivalent, new RegionFunction() {
|
||||
@Override
|
||||
public boolean apply(Vector pos) throws WorldEditException {
|
||||
int x = pos.getBlockX() - mx;
|
||||
int y = pos.getBlockY() - my;
|
||||
int z = pos.getBlockZ() - mz;
|
||||
if (region.contains(pos)) {
|
||||
int x = pos.getBlockX();
|
||||
int y = pos.getBlockY();
|
||||
int z = pos.getBlockZ();
|
||||
BaseBlock block = getBlockAbs(x, y, z);
|
||||
pos.mutX(x - mx);
|
||||
pos.mutY(y - my);
|
||||
pos.mutZ(z - mz);
|
||||
BaseBlock block = getBlockAbs(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
|
||||
CompoundTag tag = block.getNbtData();
|
||||
if (tag != null) {
|
||||
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
|
||||
values.put("x", new IntTag(pos.getBlockX()));
|
||||
values.put("y", new IntTag(pos.getBlockY()));
|
||||
values.put("z", new IntTag(pos.getBlockZ()));
|
||||
values.put("x", new IntTag(x));
|
||||
values.put("y", new IntTag(y));
|
||||
values.put("z", new IntTag(z));
|
||||
}
|
||||
task.run(pos, block);
|
||||
task.run(x, y, z, block);
|
||||
} else {
|
||||
pos.mutX(pos.getBlockX() - mx);
|
||||
pos.mutY(pos.getBlockY() - my);
|
||||
pos.mutZ(pos.getBlockZ() - mz);
|
||||
task.run(pos, EditSession.nullBlock);
|
||||
task.run(x, y, z, EditSession.nullBlock);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -111,32 +101,29 @@ public class WorldCopyClipboard extends ReadOnlyClipboard {
|
||||
}
|
||||
} else {
|
||||
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
|
||||
pos.mutY(y);
|
||||
int yy = pos.getBlockY() - my;
|
||||
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
|
||||
pos.mutZ(z);
|
||||
int zz = pos.getBlockZ() - mz;
|
||||
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
|
||||
pos.mutX(x);
|
||||
pos.mutY(y);
|
||||
pos.mutZ(z);
|
||||
int xx = pos.getBlockX() - mx;
|
||||
if (region.contains(pos)) {
|
||||
BaseBlock block = getBlockAbs(x, y, z);
|
||||
if (!air && block == EditSession.nullBlock) {
|
||||
continue;
|
||||
}
|
||||
pos.mutX(pos.getX() - mx);
|
||||
pos.mutY(pos.getY() - my);
|
||||
pos.mutZ(pos.getZ() - mz);
|
||||
CompoundTag tag = block.getNbtData();
|
||||
if (tag != null) {
|
||||
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
|
||||
values.put("x", new IntTag(pos.getBlockX()));
|
||||
values.put("y", new IntTag(pos.getBlockY()));
|
||||
values.put("z", new IntTag(pos.getBlockZ()));
|
||||
values.put("x", new IntTag(xx));
|
||||
values.put("y", new IntTag(yy));
|
||||
values.put("z", new IntTag(zz));
|
||||
}
|
||||
task.run(pos, block);
|
||||
task.run(xx, yy, zz, block);
|
||||
} else if (air) {
|
||||
pos.mutX(pos.getX() - mx);
|
||||
pos.mutY(pos.getY() - my);
|
||||
pos.mutZ(pos.getZ() - mz);
|
||||
task.run(pos, EditSession.nullBlock);
|
||||
task.run(xx, yy, zz, EditSession.nullBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public class WorldCutClipboard extends WorldCopyClipboard {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(RunnableVal2<Vector, BaseBlock> task, boolean air) {
|
||||
public void forEach(BlockReader task, boolean air) {
|
||||
super.forEach(task, air);
|
||||
editSession.flushQueue();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.boydti.fawe.object.schematic;
|
||||
|
||||
import com.boydti.fawe.object.HasFaweQueue;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.boydti.fawe.object.clipboard.FaweClipboard;
|
||||
import com.boydti.fawe.object.clipboard.ReadOnlyClipboard;
|
||||
import com.boydti.fawe.util.EditSessionBuilder;
|
||||
import com.boydti.fawe.util.MaskTraverser;
|
||||
@ -167,18 +167,13 @@ public class Schematic {
|
||||
final int rely = to.getBlockY() + bot.getBlockY() - origin.getBlockY();
|
||||
final int relz = to.getBlockZ() + bot.getBlockZ() - origin.getBlockZ();
|
||||
BlockArrayClipboard bac = (BlockArrayClipboard) clipboard;
|
||||
bac.IMP.forEach(new RunnableVal2<Vector, BaseBlock>() {
|
||||
bac.IMP.forEach(new FaweClipboard.BlockReader() {
|
||||
@Override
|
||||
public void run(Vector mutable, BaseBlock block) {
|
||||
mutable.mutX(mutable.getX() + relx);
|
||||
mutable.mutY(mutable.getY() + rely);
|
||||
mutable.mutZ(mutable.getZ() + relz);
|
||||
if (mutable.getY() >= 0 && mutable.getY() <= maxY) {
|
||||
try {
|
||||
extent.setBlock(mutable, block);
|
||||
} catch (WorldEditException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
public void run(int x, int y, int z, BaseBlock block) {
|
||||
try {
|
||||
extent.setBlock(x + relx, y + rely, z + relz, block);
|
||||
} catch (WorldEditException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}, pasteAir);
|
||||
@ -194,12 +189,7 @@ public class Schematic {
|
||||
if (block == EditSession.nullBlock && !pasteAir) {
|
||||
return false;
|
||||
}
|
||||
mutable.mutX(mutable.getX() + relx);
|
||||
mutable.mutY(mutable.getY() + rely);
|
||||
mutable.mutZ(mutable.getZ() + relz);
|
||||
if (mutable.getY() >= 0 && mutable.getY() <= maxY) {
|
||||
return extent.setBlock(mutable, block);
|
||||
}
|
||||
extent.setBlock(mutable.getBlockX() + relx, mutable.getBlockY() + rely, mutable.getBlockZ() + relz, block);
|
||||
return false;
|
||||
}
|
||||
}, (HasFaweQueue) (extent instanceof HasFaweQueue ? extent : null));
|
||||
|
@ -250,7 +250,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
|
||||
if (combineStages == null) {
|
||||
combineStages = Settings.IMP.HISTORY.COMBINE_STAGES && !(queue instanceof MCAQueue);
|
||||
}
|
||||
if (limit.FAST_PLACEMENT) {
|
||||
if (!limit.FAST_PLACEMENT) {
|
||||
combineStages = false;
|
||||
}
|
||||
if (checkMemory) {
|
||||
@ -314,6 +314,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
|
||||
if (this.blockBag != null && limit.INVENTORY_MODE > 0) {
|
||||
changeSet = new BlockBagChangeSet(changeSet, blockBag, limit.INVENTORY_MODE == 1);
|
||||
}
|
||||
System.out.println("Combine stages " + combineStages);
|
||||
if (combineStages) {
|
||||
changeTask = changeSet;
|
||||
changeSet.addChangeTask(queue);
|
||||
@ -3213,17 +3214,13 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearContainerBlockContents(Vector position) {
|
||||
BaseBlock block = getBlock(position);
|
||||
public boolean clearContainerBlockContents(Vector pos) {
|
||||
BaseBlock block = getBlock(pos);
|
||||
CompoundTag nbt = block.getNbtData();
|
||||
if (nbt != null) {
|
||||
if (nbt.containsKey("items")) {
|
||||
block.setNbtData(null);
|
||||
try {
|
||||
return setBlock(position, block);
|
||||
} catch (WorldEditException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return setBlock(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(), block);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -237,6 +237,11 @@ public class BaseBlock extends Block implements TileEntityBlock, Pattern {
|
||||
return getNbtData() != null;
|
||||
}
|
||||
|
||||
public boolean canStoreNBTData() {
|
||||
return FaweCache.hasNBT(getId());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getNbtId() {
|
||||
CompoundTag nbtData = getNbtData();
|
||||
|
@ -29,6 +29,11 @@ public class ImmutableBlock extends BaseBlock {
|
||||
return clone.flip(direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canStoreNBTData() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImmutable() {
|
||||
return true;
|
||||
|
@ -23,4 +23,9 @@ public class ImmutableDatalessBlock extends ImmutableBlock {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canStoreNBTData() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
package com.sk89q.worldedit.blocks;
|
||||
|
||||
public class ImmutableNBTBlock extends ImmutableBlock {
|
||||
public ImmutableNBTBlock(int id, int data) {
|
||||
super(id, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canStoreNBTData() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ package com.sk89q.worldedit.extent.clipboard.io;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.boydti.fawe.object.clipboard.FaweClipboard;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.ByteArrayTag;
|
||||
@ -54,7 +53,7 @@ public class SchematicWriter implements ClipboardWriter {
|
||||
this.outputStream = outputStream;
|
||||
}
|
||||
|
||||
private static class ForEach extends RunnableVal2<Vector, BaseBlock> {
|
||||
private static class ForEach extends FaweClipboard.BlockReader {
|
||||
int x = -1;
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
@ -76,10 +75,7 @@ public class SchematicWriter implements ClipboardWriter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Vector point, BaseBlock block) {
|
||||
int x = (int) point.getX();
|
||||
int y = (int) point.getY();
|
||||
int z = (int) point.getZ();
|
||||
public void run(int x, int y, int z, BaseBlock block) {
|
||||
if (this.x == x - 1 && this.y == y && this.z == z) {
|
||||
this.x++;
|
||||
index++;
|
||||
@ -164,6 +160,7 @@ public class SchematicWriter implements ClipboardWriter {
|
||||
public void run(int index, int byteValue) {
|
||||
try {
|
||||
if (byteValue >= 256) {
|
||||
System.out.println("Add block");
|
||||
hasAdd = true;
|
||||
}
|
||||
if (FaweCache.hasData(byteValue)) {
|
||||
@ -205,6 +202,7 @@ public class SchematicWriter implements ClipboardWriter {
|
||||
@Override
|
||||
public void run(int index, int byteValue) {
|
||||
try {
|
||||
System.out.println("Add " + (byteValue >> 8));
|
||||
rawStream.writeByte(byteValue >> 8);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
@ -312,10 +310,10 @@ public class SchematicWriter implements ClipboardWriter {
|
||||
MutableBlockVector mutable = new MutableBlockVector(0, 0, 0);
|
||||
ForEach forEach = new ForEach(yarea, zwidth, blocks, blockData, tileEntities);
|
||||
for (Vector point : region) {
|
||||
mutable.mutX((point.getX() - mx));
|
||||
mutable.mutY((point.getY() - my));
|
||||
mutable.mutZ((point.getZ() - mz));
|
||||
forEach.run(mutable, clipboard.getBlock(point));
|
||||
int x = (point.getBlockX() - mx);
|
||||
int y = (point.getBlockY() - my);
|
||||
int z = (point.getBlockZ() - mz);
|
||||
forEach.run(x, y, z, clipboard.getBlock(point));
|
||||
}
|
||||
addBlocks = forEach.addBlocks;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user