mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2025-02-08 00:21:36 +01:00
Stencil brush + HeightMap optimizations
This commit is contained in:
parent
b595ec2f2d
commit
50d80b3d1c
@ -472,11 +472,6 @@ public class Fawe {
|
||||
// BlockData
|
||||
BlockData.inject(); // Temporary fix for 1.9.4
|
||||
BundledBlockData.inject(); // Add custom rotation
|
||||
try {
|
||||
BundledBlockData.getInstance().loadFromResource();
|
||||
} catch (IOException e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
File jar = MainUtil.getJarFile();
|
||||
File extraBlocks = MainUtil.copyFile(jar, "extrablocks.json", null);
|
||||
if (extraBlocks != null && extraBlocks.exists()) {
|
||||
|
@ -16,6 +16,7 @@ import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
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.world.biome.BaseBiome;
|
||||
@ -51,16 +52,8 @@ public class FaweCache {
|
||||
*/
|
||||
public final static byte[][] CACHE_Z = new byte[16][4096];
|
||||
|
||||
/**
|
||||
* [ combined ] => id
|
||||
* (combined >> 4) = id
|
||||
*/
|
||||
public final static short[] CACHE_ID = new short[65535];
|
||||
/**
|
||||
* [ combined ] => data
|
||||
* (combined & 0xF) = data
|
||||
*/
|
||||
public final static byte[] CACHE_DATA = new byte[65535];
|
||||
public final static boolean[] CACHE_PASSTHROUGH = new boolean[65535];
|
||||
public final static boolean[] CACHE_TRANSLUSCENT = new boolean[65535];
|
||||
|
||||
/**
|
||||
* Immutable biome cache
|
||||
@ -162,13 +155,24 @@ public class FaweCache {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 65535; i++) {
|
||||
final int j = i >> 4;
|
||||
final int k = i & 0xF;
|
||||
CACHE_ID[i] = (short) j;
|
||||
CACHE_DATA[i] = (byte) k;
|
||||
}
|
||||
|
||||
try {
|
||||
BundledBlockData bundled = BundledBlockData.getInstance();
|
||||
bundled.loadFromResource();
|
||||
for (int i = 0; i < Character.MAX_VALUE; i++) {
|
||||
int id = i >> 4;
|
||||
int data = i & 0xf;
|
||||
CACHE_TRANSLUSCENT[i] = BlockType.isTranslucent(id);
|
||||
CACHE_PASSTHROUGH[i] = BlockType.canPassThrough(id, data);
|
||||
BundledBlockData.BlockEntry blockEntry = bundled.findById(id);
|
||||
if (blockEntry != null) {
|
||||
BundledBlockData.FaweBlockMaterial material = blockEntry.material;
|
||||
if (material != null) {
|
||||
CACHE_TRANSLUSCENT[i] = !material.isOpaque();
|
||||
CACHE_PASSTHROUGH[i] = !material.isMovementBlocker();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignore) {}
|
||||
for (int i = 0; i < Character.MAX_VALUE; i++) {
|
||||
int id = i >> 4;
|
||||
int data = i & 0xf;
|
||||
@ -266,6 +270,14 @@ public class FaweCache {
|
||||
CACHE_COLOR[getCombined(35, 15)] = new Color(0, 0, 0); // Black
|
||||
}
|
||||
|
||||
public static boolean canPassThrough(int id, int data) {
|
||||
return CACHE_PASSTHROUGH[FaweCache.getCombined(id, data)];
|
||||
}
|
||||
|
||||
public static boolean isTranslucent(int id, int data) {
|
||||
return CACHE_TRANSLUSCENT[FaweCache.getCombined(id, data)];
|
||||
}
|
||||
|
||||
public static boolean isLiquidOrGas(int id) {
|
||||
switch (id) {
|
||||
case 0:
|
||||
|
@ -1,11 +1,12 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Masks;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import java.io.InputStream;
|
||||
|
||||
@ -20,15 +21,15 @@ public class StencilBrush extends HeightBrush {
|
||||
@Override
|
||||
public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
|
||||
int size = (int) sizeDouble;
|
||||
Mask mask = editSession.getMask();
|
||||
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
|
||||
mask = null;
|
||||
}
|
||||
Mask mask = new ExistingBlockMask(editSession);
|
||||
int maxY = editSession.getMaxY();
|
||||
double scale = (yscale / sizeDouble) * (maxY + 1);
|
||||
heightMap.setSize(size);
|
||||
int cutoff = onlyWhite ? maxY : 0;
|
||||
|
||||
for (int x = -size; x <= size; x++) {
|
||||
int xx = position.getBlockX() + x;
|
||||
for (int z = -size; z <= size; z++) {
|
||||
int zz = position.getBlockZ() + z;
|
||||
double raise;
|
||||
switch (rotation) {
|
||||
default:raise = heightMap.getHeight(x, z); break;
|
||||
@ -36,19 +37,16 @@ public class StencilBrush extends HeightBrush {
|
||||
case 2: raise = heightMap.getHeight(-x, -z); break;
|
||||
case 3: raise = heightMap.getHeight(-z, -x);break;
|
||||
}
|
||||
raise *= yscale;
|
||||
if (raise == 0 || (onlyWhite && raise < 255)) {
|
||||
int val = (int) Math.ceil(raise * scale);
|
||||
if (val <= cutoff) {
|
||||
continue;
|
||||
}
|
||||
if (val >= 255 || PseudoRandom.random.random(maxY) < val) {
|
||||
int zz = position.getBlockZ() + z;
|
||||
int y = editSession.getNearestSurfaceTerrainBlock(xx, zz, position.getBlockY(), 0, maxY);
|
||||
editSession.setBlock(xx, y, zz, pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int[] data = heightMap.generateHeightData(editSession, mask, position, size, rotation, yscale, true, false);
|
||||
int diameter = size * 2;
|
||||
int x = position.getBlockX();
|
||||
int y = position.getBlockY();
|
||||
int z = position.getBlockZ();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -131,7 +131,7 @@ public class ScalableHeightMap {
|
||||
WorldVector min = new WorldVector(LocalWorldAdapter.adapt(session.getWorld()), pos.subtract(size, maxY, size));
|
||||
Vector max = pos.add(size, maxY, size);
|
||||
Region region = new CuboidRegion(session.getWorld(), min, max);
|
||||
HeightMap heightMap = new HeightMap(session, region, true);
|
||||
HeightMap heightMap = new HeightMap(session, region, false);
|
||||
if (smooth) {
|
||||
try {
|
||||
HeightMapFilter filter = (HeightMapFilter) HeightMapFilter.class.getConstructors()[0].newInstance(GaussianKernel.class.getConstructors()[0].newInstance(5, 1));
|
||||
@ -178,7 +178,7 @@ public class ScalableHeightMap {
|
||||
raise = getHeight(-z, -x);
|
||||
break;
|
||||
}
|
||||
int height = session.getHighestTerrainBlock(xx, zz, 0, 255, false);
|
||||
int height = session.getNearestSurfaceTerrainBlock(xx, zz, pos.getBlockY(), 0, 255);
|
||||
if (height == 0) {
|
||||
newData[index] = centerY;
|
||||
continue;
|
||||
@ -214,7 +214,7 @@ public class ScalableHeightMap {
|
||||
raise = getHeight(-z, -x);
|
||||
break;
|
||||
}
|
||||
int height = session.getHighestTerrainBlock(xx, zz, 0, maxY, false);
|
||||
int height = session.getNearestSurfaceTerrainBlock(xx, zz, pos.getBlockY(), 0, maxY);
|
||||
if (height == 0) {
|
||||
newData[index] = centerY;
|
||||
continue;
|
||||
|
@ -929,10 +929,14 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
|
||||
*/
|
||||
@Deprecated
|
||||
public int getBlockType(final Vector position) {
|
||||
return getBlockType(position.getBlockX(), position.getBlockY(), position.getBlockZ());
|
||||
}
|
||||
|
||||
public int getBlockType(int x, int y, int z) {
|
||||
if (!limit.MAX_CHECKS()) {
|
||||
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
|
||||
}
|
||||
int combinedId4Data = queue.getCombinedId4DataDebug(position.getBlockX(), position.getBlockY(), position.getBlockZ(), 0, this);
|
||||
int combinedId4Data = queue.getCombinedId4DataDebug(x, y, z, 0, this);
|
||||
return combinedId4Data >> 4;
|
||||
}
|
||||
|
||||
@ -977,6 +981,38 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
|
||||
return this.getHighestTerrainBlock(x, z, minY, maxY, false);
|
||||
}
|
||||
|
||||
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) {
|
||||
int clearanceAbove = maxY - y;
|
||||
int clearanceBelow = y - minY;
|
||||
int clearance = Math.min(clearanceAbove, clearanceBelow);
|
||||
|
||||
BaseBlock block = getBlock(x, y, z);
|
||||
boolean state = FaweCache.canPassThrough(block.getId(), block.getData());
|
||||
int offset = state ? 0 : 1;
|
||||
for (int d = 0; d <= clearance; d++) {
|
||||
int y1 = y + d;
|
||||
block = getLazyBlock(x, y1, z);
|
||||
if (FaweCache.canPassThrough(block.getId(), block.getData()) != state) return y1 - offset;
|
||||
int y2 = y - d;
|
||||
block = getLazyBlock(x, y2, z);
|
||||
if (FaweCache.canPassThrough(block.getId(), block.getData()) != state) return y2 + offset;
|
||||
}
|
||||
if (clearanceAbove != clearanceBelow) {
|
||||
if (clearanceAbove < clearanceBelow) {
|
||||
for (int layer = y - clearance - 1; layer >= minY; layer--) {
|
||||
block = getLazyBlock(x, layer, z);
|
||||
if (FaweCache.canPassThrough(block.getId(), block.getData()) != state) return layer + offset;
|
||||
}
|
||||
} else {
|
||||
for (int layer = y + clearance + 1; layer <= maxY; layer++) {
|
||||
block = getLazyBlock(x, layer, z);
|
||||
if (FaweCache.canPassThrough(block.getId(), block.getData()) != state) return layer - offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
return maxY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the highest solid 'terrain' block which can occur naturally.
|
||||
*
|
||||
@ -990,100 +1026,19 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
|
||||
public int getHighestTerrainBlock(final int x, final int z, int minY, int maxY, final boolean naturalOnly) {
|
||||
maxY = Math.min(maxY, Math.max(0, maxY));
|
||||
minY = Math.max(0, minY);
|
||||
for (int y = maxY; y >= minY; --y) {
|
||||
BaseBlock block = getLazyBlock(x, y, z);
|
||||
final int id = block.getId();
|
||||
int data;
|
||||
switch (id) {
|
||||
case 0: {
|
||||
continue;
|
||||
}
|
||||
case 2:
|
||||
case 4:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 25:
|
||||
case 30:
|
||||
case 32:
|
||||
case 37:
|
||||
case 39:
|
||||
case 40:
|
||||
case 41:
|
||||
case 42:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
case 48:
|
||||
case 49:
|
||||
case 51:
|
||||
case 52:
|
||||
case 54:
|
||||
case 55:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 61:
|
||||
case 62:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 73:
|
||||
case 74:
|
||||
case 78:
|
||||
case 79:
|
||||
case 80:
|
||||
case 81:
|
||||
case 82:
|
||||
case 83:
|
||||
case 84:
|
||||
case 85:
|
||||
case 87:
|
||||
case 88:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 110:
|
||||
case 112:
|
||||
case 113:
|
||||
case 117:
|
||||
case 121:
|
||||
case 122:
|
||||
case 123:
|
||||
case 124:
|
||||
case 129:
|
||||
case 133:
|
||||
case 138:
|
||||
case 137:
|
||||
case 140:
|
||||
case 165:
|
||||
case 166:
|
||||
case 169:
|
||||
case 170:
|
||||
case 172:
|
||||
case 173:
|
||||
case 174:
|
||||
case 176:
|
||||
case 177:
|
||||
case 181:
|
||||
case 182:
|
||||
case 188:
|
||||
case 189:
|
||||
case 190:
|
||||
case 191:
|
||||
case 192:
|
||||
if (naturalOnly) {
|
||||
for (int y = maxY; y >= minY; --y) {
|
||||
BaseBlock block = getLazyBlock(x, y, z);
|
||||
if (BlockType.isNaturalTerrainBlock(block.getId(), block.getData())) {
|
||||
return y;
|
||||
default:
|
||||
data = 0;
|
||||
}
|
||||
}
|
||||
if (naturalOnly ? BlockType.isNaturalTerrainBlock(id, data) : !BlockType.canPassThrough(id, data)) {
|
||||
return y;
|
||||
} else {
|
||||
for (int y = maxY; y >= minY; --y) {
|
||||
BaseBlock block = getLazyBlock(x, y, z);
|
||||
if (!FaweCache.canPassThrough(block.getId(), block.getData())) {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
}
|
||||
return minY;
|
||||
|
Loading…
Reference in New Issue
Block a user