mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-03 08:25:31 +00:00
short-circuit locators
This commit is contained in:
parent
0f767c6896
commit
68f8c8cea8
@ -27,13 +27,7 @@ public class AdjacentPatternLocator implements Locator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BinaryColumn getSuitableCoordinates(Column<?> column) {
|
public BinaryColumn getSuitableCoordinates(Column<?> column) {
|
||||||
BinaryColumn locations = new BinaryColumn(search);
|
return new BinaryColumn(search, y -> isValid(y, column));
|
||||||
|
|
||||||
for(int y : search) {
|
|
||||||
if(isValid(y, column)) locations.set(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
return locations;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValid(int y, Column<?> column) {
|
private boolean isValid(int y, Column<?> column) {
|
||||||
|
@ -11,6 +11,7 @@ import com.dfsek.terra.api.structure.feature.BinaryColumn;
|
|||||||
import com.dfsek.terra.api.structure.feature.Locator;
|
import com.dfsek.terra.api.structure.feature.Locator;
|
||||||
import com.dfsek.terra.api.util.Range;
|
import com.dfsek.terra.api.util.Range;
|
||||||
import com.dfsek.terra.api.world.chunk.generation.util.Column;
|
import com.dfsek.terra.api.world.chunk.generation.util.Column;
|
||||||
|
import com.dfsek.terra.api.world.chunk.generation.util.Column.BinaryColumnBuilder;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@ -44,13 +45,13 @@ public class GaussianRandomLocator implements Locator {
|
|||||||
int size = points.get(r);
|
int size = points.get(r);
|
||||||
|
|
||||||
|
|
||||||
BinaryColumn results = new BinaryColumn(column.getMinY(), column.getMaxY());
|
BinaryColumnBuilder results = column.newBinaryColumn();
|
||||||
for(int i = 0; i < size; i++) {
|
for(int i = 0; i < size; i++) {
|
||||||
int h = (int) r.nextGaussian(mean, standardDeviation);
|
int h = (int) r.nextGaussian(mean, standardDeviation);
|
||||||
if(h >= column.getMaxY() || h < column.getMinY()) continue;
|
if(h >= column.getMaxY() || h < column.getMinY()) continue;
|
||||||
results.set(h);
|
results.set(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,6 @@ public class PatternLocator implements Locator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BinaryColumn getSuitableCoordinates(Column<?> column) {
|
public BinaryColumn getSuitableCoordinates(Column<?> column) {
|
||||||
BinaryColumn locations = new BinaryColumn(column.getMinY(), column.getMaxY());
|
return new BinaryColumn(column.getMinY(), column.getMaxY(), y -> pattern.matches(y, column));
|
||||||
|
|
||||||
for(int y : search) {
|
|
||||||
if(pattern.matches(y, column)) locations.set(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
return locations;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import com.dfsek.terra.api.structure.feature.BinaryColumn;
|
|||||||
import com.dfsek.terra.api.structure.feature.Locator;
|
import com.dfsek.terra.api.structure.feature.Locator;
|
||||||
import com.dfsek.terra.api.util.Range;
|
import com.dfsek.terra.api.util.Range;
|
||||||
import com.dfsek.terra.api.world.chunk.generation.util.Column;
|
import com.dfsek.terra.api.world.chunk.generation.util.Column;
|
||||||
|
import com.dfsek.terra.api.world.chunk.generation.util.Column.BinaryColumnBuilder;
|
||||||
|
|
||||||
|
|
||||||
public class RandomLocator implements Locator {
|
public class RandomLocator implements Locator {
|
||||||
@ -39,13 +40,13 @@ public class RandomLocator implements Locator {
|
|||||||
|
|
||||||
int size = points.get(r);
|
int size = points.get(r);
|
||||||
|
|
||||||
BinaryColumn results = new BinaryColumn(column.getMinY(), column.getMaxY());
|
BinaryColumnBuilder results = column.newBinaryColumn();
|
||||||
for(int i = 0; i < size; i++) {
|
for(int i = 0; i < size; i++) {
|
||||||
int h = height.get(r);
|
int h = height.get(r);
|
||||||
if(h >= column.getMaxY() || h < column.getMinY()) continue;
|
if(h >= column.getMaxY() || h < column.getMinY()) continue;
|
||||||
results.set(h);
|
results.set(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,9 @@ public class Sampler3DLocator implements Locator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BinaryColumn getSuitableCoordinates(Column<?> column) {
|
public BinaryColumn getSuitableCoordinates(Column<?> column) {
|
||||||
BinaryColumn results = column.newBinaryColumn();
|
|
||||||
long seed = column.getWorld().getSeed();
|
long seed = column.getWorld().getSeed();
|
||||||
int x = column.getX();
|
int x = column.getX();
|
||||||
int z = column.getZ();
|
int z = column.getZ();
|
||||||
column.forEach(y -> {
|
return column.newBinaryColumn(y -> sampler.noise(seed, x, y, z) > 0);
|
||||||
if(sampler.noise(seed, x, y, z) > 0) results.set(y);
|
|
||||||
});
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
package com.dfsek.terra.addons.feature.locator.locators;
|
package com.dfsek.terra.addons.feature.locator.locators;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.world.chunk.generation.util.Column.BinaryColumnBuilder;
|
||||||
|
|
||||||
import net.jafama.FastMath;
|
import net.jafama.FastMath;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -26,7 +28,7 @@ public class SamplerLocator implements Locator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BinaryColumn getSuitableCoordinates(Column<?> column) {
|
public BinaryColumn getSuitableCoordinates(Column<?> column) {
|
||||||
BinaryColumn results = new BinaryColumn(column.getMinY(), column.getMaxY());
|
BinaryColumnBuilder results = column.newBinaryColumn();
|
||||||
|
|
||||||
long seed = column.getWorld().getSeed();
|
long seed = column.getWorld().getSeed();
|
||||||
samplers.forEach(sampler -> {
|
samplers.forEach(sampler -> {
|
||||||
@ -35,6 +37,6 @@ public class SamplerLocator implements Locator {
|
|||||||
results.set(y);
|
results.set(y);
|
||||||
});
|
});
|
||||||
|
|
||||||
return results;
|
return results.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import com.dfsek.terra.api.structure.feature.BinaryColumn;
|
|||||||
import com.dfsek.terra.api.structure.feature.Locator;
|
import com.dfsek.terra.api.structure.feature.Locator;
|
||||||
import com.dfsek.terra.api.util.Range;
|
import com.dfsek.terra.api.util.Range;
|
||||||
import com.dfsek.terra.api.world.chunk.generation.util.Column;
|
import com.dfsek.terra.api.world.chunk.generation.util.Column;
|
||||||
|
import com.dfsek.terra.api.world.chunk.generation.util.Column.BinaryColumnBuilder;
|
||||||
|
|
||||||
|
|
||||||
public class SurfaceLocator implements Locator {
|
public class SurfaceLocator implements Locator {
|
||||||
@ -22,12 +23,12 @@ public class SurfaceLocator implements Locator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BinaryColumn getSuitableCoordinates(Column<?> column) {
|
public BinaryColumn getSuitableCoordinates(Column<?> column) {
|
||||||
BinaryColumn location = new BinaryColumn(column.getMinY(), column.getMaxY());
|
BinaryColumnBuilder builder = column.newBinaryColumn();
|
||||||
for(int y : search) {
|
for(int y : search) {
|
||||||
if(column.getBlock(y).isAir() && !column.getBlock(y - 1).isAir()) {
|
if(column.getBlock(y).isAir() && !column.getBlock(y - 1).isAir()) {
|
||||||
location.set(y);
|
builder.set(y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return location;
|
return builder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,11 @@ public class TopLocator implements Locator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BinaryColumn getSuitableCoordinates(Column<?> column) {
|
public BinaryColumn getSuitableCoordinates(Column<?> column) {
|
||||||
BinaryColumn location = new BinaryColumn(column.getMinY(), column.getMaxY());
|
|
||||||
for(int y : search) {
|
for(int y : search) {
|
||||||
if(column.getBlock(y).isAir() && !column.getBlock(y - 1).isAir()) {
|
if(column.getBlock(y).isAir() && !column.getBlock(y - 1).isAir()) {
|
||||||
location.set(y);
|
return new BinaryColumn(y, y+1, yi -> true);
|
||||||
return location;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return location;
|
return BinaryColumn.getNull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,41 +7,41 @@
|
|||||||
|
|
||||||
package com.dfsek.terra.api.structure.feature;
|
package com.dfsek.terra.api.structure.feature;
|
||||||
|
|
||||||
|
import java.util.function.BooleanSupplier;
|
||||||
import java.util.function.IntConsumer;
|
import java.util.function.IntConsumer;
|
||||||
|
|
||||||
import com.dfsek.terra.api.util.Range;
|
import com.dfsek.terra.api.util.Range;
|
||||||
|
import com.dfsek.terra.api.util.function.IntToBooleanFunction;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A column of binary data
|
* A column of binary data
|
||||||
*/
|
*/
|
||||||
public class BinaryColumn {
|
public class BinaryColumn {
|
||||||
private final boolean[] data;
|
private final IntToBooleanFunction data;
|
||||||
private final int minY;
|
private final int minY;
|
||||||
private final int maxY;
|
private final int maxY;
|
||||||
|
|
||||||
|
private static final BinaryColumn NULL = new BinaryColumn(0, 1, y -> false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new {@link BinaryColumn} with all values initiated to {@code false}
|
* Constructs a new {@link BinaryColumn} with all values initiated to {@code false}
|
||||||
* @param minY Minimum Y value
|
* @param minY Minimum Y value
|
||||||
* @param maxY Maximum Y value
|
* @param maxY Maximum Y value
|
||||||
*/
|
*/
|
||||||
public BinaryColumn(int minY, int maxY) {
|
public BinaryColumn(int minY, int maxY, IntToBooleanFunction data) {
|
||||||
this.minY = minY;
|
this.minY = minY;
|
||||||
this.maxY = maxY;
|
this.maxY = maxY;
|
||||||
if(maxY <= minY) throw new IllegalArgumentException("Max y must be greater than min y");
|
if(maxY <= minY) throw new IllegalArgumentException("Max y must be greater than min y");
|
||||||
this.data = new boolean[maxY - minY];
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BinaryColumn(Range y) {
|
public static BinaryColumn getNull() {
|
||||||
this(y.getMin(), y.getMax());
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public BinaryColumn(Range y, IntToBooleanFunction data) {
|
||||||
* Set the value of a height to {@code true}.
|
this(y.getMin(), y.getMax(), data);
|
||||||
* @param y Height of entry to set.
|
|
||||||
*/
|
|
||||||
public void set(int y) {
|
|
||||||
data[y - minY] = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,7 +50,7 @@ public class BinaryColumn {
|
|||||||
* @return Whether height has been set.
|
* @return Whether height has been set.
|
||||||
*/
|
*/
|
||||||
public boolean get(int y) {
|
public boolean get(int y) {
|
||||||
return data[y - minY];
|
return data.apply(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -63,9 +63,9 @@ public class BinaryColumn {
|
|||||||
* @param consumer Action to perform
|
* @param consumer Action to perform
|
||||||
*/
|
*/
|
||||||
public void forEach(IntConsumer consumer) {
|
public void forEach(IntConsumer consumer) {
|
||||||
for(int y = 0; y < data.length; y++) {
|
for(int y = minY; y < maxY; y++) {
|
||||||
if(data[y]) {
|
if(get(y)) {
|
||||||
consumer.accept(y + minY);
|
consumer.accept(y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,7 +78,7 @@ public class BinaryColumn {
|
|||||||
* @throws IllegalArgumentException if column heights do not match
|
* @throws IllegalArgumentException if column heights do not match
|
||||||
*/
|
*/
|
||||||
public BinaryColumn and(BinaryColumn that) {
|
public BinaryColumn and(BinaryColumn that) {
|
||||||
return bool(that, Boolean::logicalAnd);
|
return bool(that, (a, b) -> a.getAsBoolean() && b.getAsBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,38 +89,21 @@ public class BinaryColumn {
|
|||||||
* @throws IllegalArgumentException if column heights do not match
|
* @throws IllegalArgumentException if column heights do not match
|
||||||
*/
|
*/
|
||||||
public BinaryColumn or(BinaryColumn that) {
|
public BinaryColumn or(BinaryColumn that) {
|
||||||
return bool(that, Boolean::logicalOr);
|
return bool(that, (a, b) -> a.getAsBoolean() || b.getAsBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BinaryColumn xor(BinaryColumn that) {
|
public BinaryColumn xor(BinaryColumn that) {
|
||||||
return bool(that, Boolean::logicalXor);
|
return bool(that, (a, b) -> a.getAsBoolean() ^ b.getAsBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
private BinaryColumn bool(BinaryColumn that, BooleanBinaryOperator operator) {
|
private BinaryColumn bool(BinaryColumn that, BooleanBinaryOperator operator) {
|
||||||
int smallMinY = Math.min(this.minY, that.minY);
|
int smallMinY = Math.min(this.minY, that.minY);
|
||||||
int bigMaxY = Math.max(this.maxY, that.maxY);
|
int bigMaxY = Math.max(this.maxY, that.maxY);
|
||||||
|
|
||||||
BinaryColumn next = new BinaryColumn(smallMinY, bigMaxY);
|
return new BinaryColumn(smallMinY, bigMaxY, y -> operator.apply(() -> this.get(y), () -> that.get(y)));
|
||||||
|
|
||||||
for(int i = smallMinY; i < bigMaxY; i++) {
|
|
||||||
boolean left = false;
|
|
||||||
boolean right = false;
|
|
||||||
|
|
||||||
if(this.contains(i)) {
|
|
||||||
left = this.get(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(that.contains(i)) {
|
|
||||||
right = that.get(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
next.data[i - smallMinY] = operator.apply(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
return next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface BooleanBinaryOperator {
|
private interface BooleanBinaryOperator {
|
||||||
boolean apply(boolean a, boolean b);
|
boolean apply(BooleanSupplier a, BooleanSupplier b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.dfsek.terra.api.util.function;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface IntToBooleanFunction {
|
||||||
|
boolean apply(int value);
|
||||||
|
}
|
@ -11,6 +11,7 @@ import java.util.function.IntConsumer;
|
|||||||
|
|
||||||
import com.dfsek.terra.api.block.state.BlockState;
|
import com.dfsek.terra.api.block.state.BlockState;
|
||||||
import com.dfsek.terra.api.structure.feature.BinaryColumn;
|
import com.dfsek.terra.api.structure.feature.BinaryColumn;
|
||||||
|
import com.dfsek.terra.api.util.function.IntToBooleanFunction;
|
||||||
import com.dfsek.terra.api.world.WritableWorld;
|
import com.dfsek.terra.api.world.WritableWorld;
|
||||||
|
|
||||||
|
|
||||||
@ -58,8 +59,31 @@ public class Column<T extends WritableWorld> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BinaryColumn newBinaryColumn() {
|
public BinaryColumn newBinaryColumn(IntToBooleanFunction function) {
|
||||||
return new BinaryColumn(getMinY(), getMaxY());
|
return new BinaryColumn(getMinY(), getMaxY(), function);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BinaryColumnBuilder newBinaryColumn() {
|
||||||
|
return new BinaryColumnBuilder(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BinaryColumnBuilder {
|
||||||
|
private final boolean[] arr;
|
||||||
|
private final Column<?> column;
|
||||||
|
|
||||||
|
public BinaryColumnBuilder(Column<?> column) {
|
||||||
|
this.column = column;
|
||||||
|
arr = new boolean[column.getMaxY() - column.getMinY()];
|
||||||
|
}
|
||||||
|
|
||||||
|
public BinaryColumn build() {
|
||||||
|
return new BinaryColumn(column.getMinY(), column.getMaxY(), y -> arr[y - column.getMinY()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BinaryColumnBuilder set(int y) {
|
||||||
|
arr[y - column.getMinY()] = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user