water height

This commit is contained in:
Jesse Boyd 2017-05-01 03:04:35 +10:00
parent 94e5a931ec
commit b756f93361
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
2 changed files with 215 additions and 151 deletions

View File

@ -13,6 +13,7 @@ import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.BlockPattern;
@ -43,10 +44,11 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
private final char[] floor; private final char[] floor;
private final char[] main; private final char[] main;
private char[] overlay; private char[] overlay;
private int waterHeight = 0;
private TextureUtil textureUtil; private TextureUtil textureUtil;
private boolean randomVariation = true; private boolean randomVariation = true;
private int biomePriority = 0; private int biomePriority = 0;
private byte waterId = BlockID.STATIONARY_WATER;
private boolean modifiedMain = false; private boolean modifiedMain = false;
public HeightMapMCAGenerator(BufferedImage img, File regionFolder) { public HeightMapMCAGenerator(BufferedImage img, File regionFolder) {
@ -78,6 +80,14 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
} }
public void setWaterHeight(int waterHeight) {
this.waterHeight = waterHeight;
}
public void setWaterId(int waterId) {
this.waterId = (byte) waterId;
}
public void setTextureRandomVariation(boolean randomVariation) { public void setTextureRandomVariation(boolean randomVariation) {
this.randomVariation = randomVariation; this.randomVariation = randomVariation;
} }
@ -214,6 +224,9 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
} }
} }
if (y > waterHeight) {
return FaweCache.CACHE_BLOCK[waterId << 4];
}
return FaweCache.CACHE_BLOCK[0]; return FaweCache.CACHE_BLOCK[0];
} else if (y == height) { } else if (y == height) {
return FaweCache.CACHE_BLOCK[floor[index]]; return FaweCache.CACHE_BLOCK[floor[index]];
@ -630,180 +643,203 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
@Override @Override
public MCAChunk write(MCAChunk chunk, int csx, int cex, int csz, int cez) { public MCAChunk write(MCAChunk chunk, int csx, int cex, int csz, int cez) {
int cx = chunk.getX(); try {
int cz = chunk.getZ(); int cx = chunk.getX();
int[] indexes = indexStore.get(); int cz = chunk.getZ();
for (int i = 0; i < chunk.ids.length; i++) { int[] indexes = indexStore.get();
byte[] idsArray = chunk.ids[i]; for (int i = 0; i < chunk.ids.length; i++) {
if (idsArray != null) { byte[] idsArray = chunk.ids[i];
Arrays.fill(idsArray, (byte) 0); if (idsArray != null) {
Arrays.fill(chunk.data[i], (byte) 0); Arrays.fill(idsArray, (byte) 0);
Arrays.fill(chunk.data[i], (byte) 0);
}
} }
} int index = 0;
int index = 0; int maxY = 0;
int maxY = 0; int minY = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE; int[] heightMap = chunk.getHeightMapArray();
int[] heightMap = chunk.getHeightMapArray(); int globalIndex;
int globalIndex; for (int z = csz; z <= cez; z++) {
for (int z = csz; z <= cez; z++) { globalIndex = z * getWidth() + csx;
globalIndex = z * getWidth() + csx; for (int x = csx; x <= cex; x++, index++, globalIndex++) {
for (int x = csx; x <= cex; x++, index++, globalIndex++) { indexes[index] = globalIndex;
indexes[index] = globalIndex; chunk.biomes[index] = biomes[globalIndex];
chunk.biomes[index] = biomes[globalIndex]; int height = heights[globalIndex] & 0xFF;
int height = heights[globalIndex] & 0xFF; heightMap[index] = height;
heightMap[index] = height; maxY = Math.max(maxY, height);
maxY = Math.max(maxY, height); minY = Math.min(minY, height);
minY = Math.min(minY, height); }
} }
} boolean hasOverlay = this.overlay != null;
boolean hasOverlay = this.overlay != null; if (hasOverlay) {
if (hasOverlay) { maxY++;
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];
} }
} int maxLayer = maxY >> 4;
if (modifiedMain) { // If the main block is modified, we can't short circuit this int fillLayers = Math.max(0, (minY - 1)) >> 4;
for (int layer = 0; layer < fillLayers; layer++) { for (int layer = 0; layer <= maxLayer; layer++) {
index = 0; 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);
}
}
if (waterHeight != 0) {
maxY = Math.max(maxY, waterHeight);
int maxWaterLayer = ((waterHeight + 15) >> 4);
for (int layer = 0; layer < maxWaterLayer; layer++) {
boolean fillAll = (layer << 4) + 15 <= waterHeight;
byte[] ids = chunk.ids[layer];
if (ids == null) {
chunk.ids[layer] = ids = new byte[4096];
chunk.data[layer] = new byte[2048];
chunk.skyLight[layer] = new byte[2048];
chunk.blockLight[layer] = new byte[2048];
Arrays.fill(chunk.skyLight[layer], (byte) 255);
}
if (fillAll) {
Arrays.fill(ids, waterId);
} else {
int maxIndex = maxWaterLayer << 8;
Arrays.fill(ids, 0, maxIndex, waterId);
}
}
}
for (int layer = fillLayers; layer <= maxLayer; layer++) {
Arrays.fill(chunk.skyLight[layer], (byte) 255);
byte[] layerIds = chunk.ids[layer]; byte[] layerIds = chunk.ids[layer];
byte[] layerDatas = chunk.data[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 z = csz; z <= cez; z++) {
for (int x = csx; x <= cex; x++, index++) { for (int x = csx; x <= cex; x++, index++) {
globalIndex = indexes[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]; char mainCombined = main[globalIndex];
byte id = (byte) FaweCache.getId(mainCombined); byte id = (byte) FaweCache.getId(mainCombined);
int data = FaweCache.getData(mainCombined); int data = FaweCache.getData(mainCombined);
if (data != 0) { if (data != 0) {
for (int y = 0; y < 16; y++) { for (int y = 0; y < diff; y++) {
int mainIndex = index + (y << 8); int mainIndex = index + (y << 8);
chunk.setNibble(mainIndex, layerDatas, data); chunk.setNibble(mainIndex, layerDatas, data);
} }
} }
for (int y = 0; y < 16; y++) { for (int y = 0; y < diff; y++) {
layerIds[index + (y << 8)] = id; layerIds[index + (y << 8)] = id;
} }
} }
} }
} }
} else { int maxYMod = 15 + (maxLayer << 4);
for (int layer = 0; layer < fillLayers; layer++) { for (int layer = (maxY >> 4) + 1; layer < 16; layer++) {
Arrays.fill(chunk.ids[layer], (byte) 1); chunk.ids[layer] = null;
chunk.data[layer] = null;
} }
}
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; index = 0;
int startY = layer << 4; { // Bedrock
int endY = startY + 15; byte[] layerIds = chunk.ids[0];
for (int z = csz; z <= cez; z++) { for (int z = csz; z <= cez; z++) {
for (int x = csx; x <= cex; x++, index++) { for (int x = csx; x <= cex; x++) {
globalIndex = indexes[index]; layerIds[index++] = (byte) 7;
int height = heightMap[index]; }
int diff; }
if (height > endY) { }
diff = 16; int chunkPair = MathMan.pair((short) cx, (short) cz);
} else if (height >= startY) { char[][][] localBlocks = blocks.get(chunkPair);
diff = height - startY; if (localBlocks != null) {
char floorCombined = floor[globalIndex]; for (int layer = 0; layer < 16; layer++) {
int id = FaweCache.getId(floorCombined); int by = layer << 4;
int floorIndex = index + ((height & 15) << 8); int ty = by + 15;
layerIds[floorIndex] = (byte) id; index = 0;
int data = FaweCache.getData(floorCombined); for (int y = by; y <= ty; y++, index += 256) {
if (data != 0) { char[][] yBlocks = localBlocks[y];
chunk.setNibble(floorIndex, layerDatas, data); if (yBlocks != null) {
} if (chunk.ids[layer] == null) {
if (hasOverlay && height >= startY - 1 && height < endY) { chunk.ids[layer] = new byte[4096];
char overlayCombined = overlay[globalIndex]; chunk.data[layer] = new byte[2048];
id = FaweCache.getId(overlayCombined); chunk.skyLight[layer] = new byte[2048];
int overlayIndex = index + (((height + 1) & 15) << 8); chunk.blockLight[layer] = new byte[2048];
layerIds[overlayIndex] = (byte) id;
data = FaweCache.getData(overlayCombined);
if (data != 0) {
chunk.setNibble(overlayIndex, layerDatas, data);
} }
} byte[] idsLayer = chunk.ids[layer];
} else if (hasOverlay && height == startY - 1) { byte[] dataLayer = chunk.data[layer];
char overlayCombined = overlay[globalIndex]; for (int z = 0; z < yBlocks.length; z++) {
int id = FaweCache.getId(overlayCombined); char[] zBlocks = yBlocks[z];
int overlayIndex = index + (((height + 1) & 15) << 8); if (zBlocks != null) {
layerIds[overlayIndex] = (byte) id; int zIndex = index + (z << 4);
int data = FaweCache.getData(overlayCombined); for (int x = 0; x < zBlocks.length; x++, zIndex++) {
if (data != 0) { char combined = zBlocks[x];
chunk.setNibble(overlayIndex, layerDatas, data); if (combined == 0) continue;
} int id = FaweCache.getId(combined);
continue; if (!FaweCache.hasData(id)) {
} else { chunk.setIdUnsafe(idsLayer, zIndex, (byte) id);
continue; } else {
} chunk.setBlockUnsafe(idsLayer, dataLayer, zIndex, (byte) id, FaweCache.getData(combined));
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));
} }
} }
} }
@ -811,6 +847,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
} }
} }
} catch (Throwable e) {
e.printStackTrace();
} }
return chunk; return chunk;
} }

View File

@ -145,6 +145,8 @@ public class CreateFromImage extends Command {
fp.sendMessage(BBC.getPrefix() + "/2 cfi ore[s]"); fp.sendMessage(BBC.getPrefix() + "/2 cfi ore[s]");
fp.sendMessage(BBC.getPrefix() + "/2 cfi schem <mask> <schem> <rarity> <rotate>"); fp.sendMessage(BBC.getPrefix() + "/2 cfi schem <mask> <schem> <rarity> <rotate>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi height <image-url|height>"); fp.sendMessage(BBC.getPrefix() + "/2 cfi height <image-url|height>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi waterheight <height>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi waterid <number-id>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi color <image-url>"); fp.sendMessage(BBC.getPrefix() + "/2 cfi color <image-url>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi glass <image-url>"); fp.sendMessage(BBC.getPrefix() + "/2 cfi glass <image-url>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi biomeColor <image-url>"); fp.sendMessage(BBC.getPrefix() + "/2 cfi biomeColor <image-url>");
@ -304,6 +306,30 @@ public class CreateFromImage extends Command {
player.sendMessage("Set glass color, what's next?"); player.sendMessage("Set glass color, what's next?");
return; return;
} }
case "waterheight":
case "setwaterheight": {
// roughness
// blocks
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <height>");
return;
}
generator.setWaterHeight(Integer.parseInt(argList.get(1)));
player.sendMessage("Set water height, what's next?");
return;
}
case "waterid":
case "setwaterid": {
// roughness
// blocks
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <id>");
return;
}
generator.setWaterId(Integer.parseInt(argList.get(1)));
player.sendMessage("Set water id, what's next?");
return;
}
case "height": case "height":
case "setheight": { case "setheight": {
if (argList.size() != 2) { if (argList.size() != 2) {