short-circuit locators

This commit is contained in:
dfsek 2022-02-14 09:30:45 -07:00
parent 0f767c6896
commit 68f8c8cea8
11 changed files with 71 additions and 71 deletions

View File

@ -27,13 +27,7 @@ public class AdjacentPatternLocator implements Locator {
@Override
public BinaryColumn getSuitableCoordinates(Column<?> column) {
BinaryColumn locations = new BinaryColumn(search);
for(int y : search) {
if(isValid(y, column)) locations.set(y);
}
return locations;
return new BinaryColumn(search, y -> isValid(y, column));
}
private boolean isValid(int y, Column<?> column) {

View File

@ -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.util.Range;
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;
@ -44,13 +45,13 @@ public class GaussianRandomLocator implements Locator {
int size = points.get(r);
BinaryColumn results = new BinaryColumn(column.getMinY(), column.getMaxY());
BinaryColumnBuilder results = column.newBinaryColumn();
for(int i = 0; i < size; i++) {
int h = (int) r.nextGaussian(mean, standardDeviation);
if(h >= column.getMaxY() || h < column.getMinY()) continue;
results.set(h);
}
return results;
return results.build();
}
}

View File

@ -25,12 +25,6 @@ public class PatternLocator implements Locator {
@Override
public BinaryColumn getSuitableCoordinates(Column<?> column) {
BinaryColumn locations = new BinaryColumn(column.getMinY(), column.getMaxY());
for(int y : search) {
if(pattern.matches(y, column)) locations.set(y);
}
return locations;
return new BinaryColumn(column.getMinY(), column.getMaxY(), y -> pattern.matches(y, column));
}
}

View File

@ -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.util.Range;
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 {
@ -39,13 +40,13 @@ public class RandomLocator implements Locator {
int size = points.get(r);
BinaryColumn results = new BinaryColumn(column.getMinY(), column.getMaxY());
BinaryColumnBuilder results = column.newBinaryColumn();
for(int i = 0; i < size; i++) {
int h = height.get(r);
if(h >= column.getMaxY() || h < column.getMinY()) continue;
results.set(h);
}
return results;
return results.build();
}
}

View File

@ -22,13 +22,9 @@ public class Sampler3DLocator implements Locator {
@Override
public BinaryColumn getSuitableCoordinates(Column<?> column) {
BinaryColumn results = column.newBinaryColumn();
long seed = column.getWorld().getSeed();
int x = column.getX();
int z = column.getZ();
column.forEach(y -> {
if(sampler.noise(seed, x, y, z) > 0) results.set(y);
});
return results;
return column.newBinaryColumn(y -> sampler.noise(seed, x, y, z) > 0);
}
}

View File

@ -7,6 +7,8 @@
package com.dfsek.terra.addons.feature.locator.locators;
import com.dfsek.terra.api.world.chunk.generation.util.Column.BinaryColumnBuilder;
import net.jafama.FastMath;
import java.util.List;
@ -26,7 +28,7 @@ public class SamplerLocator implements Locator {
@Override
public BinaryColumn getSuitableCoordinates(Column<?> column) {
BinaryColumn results = new BinaryColumn(column.getMinY(), column.getMaxY());
BinaryColumnBuilder results = column.newBinaryColumn();
long seed = column.getWorld().getSeed();
samplers.forEach(sampler -> {
@ -35,6 +37,6 @@ public class SamplerLocator implements Locator {
results.set(y);
});
return results;
return results.build();
}
}

View File

@ -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.util.Range;
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 {
@ -22,12 +23,12 @@ public class SurfaceLocator implements Locator {
@Override
public BinaryColumn getSuitableCoordinates(Column<?> column) {
BinaryColumn location = new BinaryColumn(column.getMinY(), column.getMaxY());
BinaryColumnBuilder builder = column.newBinaryColumn();
for(int y : search) {
if(column.getBlock(y).isAir() && !column.getBlock(y - 1).isAir()) {
location.set(y);
builder.set(y);
}
}
return location;
return builder.build();
}
}

View File

@ -22,13 +22,11 @@ public class TopLocator implements Locator {
@Override
public BinaryColumn getSuitableCoordinates(Column<?> column) {
BinaryColumn location = new BinaryColumn(column.getMinY(), column.getMaxY());
for(int y : search) {
if(column.getBlock(y).isAir() && !column.getBlock(y - 1).isAir()) {
location.set(y);
return location;
return new BinaryColumn(y, y+1, yi -> true);
}
}
return location;
return BinaryColumn.getNull();
}
}

View File

@ -7,41 +7,41 @@
package com.dfsek.terra.api.structure.feature;
import java.util.function.BooleanSupplier;
import java.util.function.IntConsumer;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.util.function.IntToBooleanFunction;
/**
* A column of binary data
*/
public class BinaryColumn {
private final boolean[] data;
private final IntToBooleanFunction data;
private final int minY;
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}
* @param minY Minimum 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.maxY = maxY;
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) {
this(y.getMin(), y.getMax());
public static BinaryColumn getNull() {
return NULL;
}
/**
* Set the value of a height to {@code true}.
* @param y Height of entry to set.
*/
public void set(int y) {
data[y - minY] = true;
public BinaryColumn(Range y, IntToBooleanFunction data) {
this(y.getMin(), y.getMax(), data);
}
/**
@ -50,7 +50,7 @@ public class BinaryColumn {
* @return Whether height has been set.
*/
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
*/
public void forEach(IntConsumer consumer) {
for(int y = 0; y < data.length; y++) {
if(data[y]) {
consumer.accept(y + minY);
for(int y = minY; y < maxY; y++) {
if(get(y)) {
consumer.accept(y);
}
}
}
@ -78,7 +78,7 @@ public class BinaryColumn {
* @throws IllegalArgumentException if column heights do not match
*/
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
*/
public BinaryColumn or(BinaryColumn that) {
return bool(that, Boolean::logicalOr);
return bool(that, (a, b) -> a.getAsBoolean() || b.getAsBoolean());
}
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) {
int smallMinY = Math.min(this.minY, that.minY);
int bigMaxY = Math.max(this.maxY, that.maxY);
BinaryColumn next = new BinaryColumn(smallMinY, bigMaxY);
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;
return new BinaryColumn(smallMinY, bigMaxY, y -> operator.apply(() -> this.get(y), () -> that.get(y)));
}
private interface BooleanBinaryOperator {
boolean apply(boolean a, boolean b);
boolean apply(BooleanSupplier a, BooleanSupplier b);
}
}

View File

@ -0,0 +1,6 @@
package com.dfsek.terra.api.util.function;
@FunctionalInterface
public interface IntToBooleanFunction {
boolean apply(int value);
}

View File

@ -11,6 +11,7 @@ import java.util.function.IntConsumer;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.structure.feature.BinaryColumn;
import com.dfsek.terra.api.util.function.IntToBooleanFunction;
import com.dfsek.terra.api.world.WritableWorld;
@ -58,8 +59,31 @@ public class Column<T extends WritableWorld> {
}
}
public BinaryColumn newBinaryColumn() {
return new BinaryColumn(getMinY(), getMaxY());
public BinaryColumn newBinaryColumn(IntToBooleanFunction function) {
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")