hytale-server/com/hypixel/hytale/builtin/hytalegenerator/scanners/AreaScanner.java

92 lines
3.1 KiB
Java

package com.hypixel.hytale.builtin.hytalegenerator.scanners;
import com.hypixel.hytale.builtin.hytalegenerator.VectorUtil;
import com.hypixel.hytale.builtin.hytalegenerator.bounds.SpaceSize;
import com.hypixel.hytale.builtin.hytalegenerator.framework.math.Calculator;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.codecs.EnumCodec;
import com.hypixel.hytale.math.vector.Vector2i;
import com.hypixel.hytale.math.vector.Vector3i;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
public class AreaScanner extends Scanner {
@Nonnull
private final AreaScanner.ScanShape scanShape;
private final int range;
private final int resultCap;
@Nonnull
private final Scanner childScanner;
@Nonnull
private final List<Vector2i> scanOrder;
@Nonnull
private final SpaceSize scanSpaceSize;
public AreaScanner(int resultCap, @Nonnull AreaScanner.ScanShape scanShape, int range, @Nonnull Scanner childScanner) {
if (resultCap >= 0 && range >= 0) {
this.resultCap = resultCap;
this.childScanner = childScanner;
this.scanShape = scanShape;
this.range = range;
ArrayList<Vector2i> scanOrder = new ArrayList<>();
for (int x = -range; x <= range; x++) {
for (int z = -range; z <= range; z++) {
if (scanShape != AreaScanner.ScanShape.CIRCLE || !(Calculator.distance(x, z, 0.0, 0.0) > range)) {
scanOrder.add(new Vector2i(x, z));
}
}
}
this.scanOrder = VectorUtil.orderByDistanceFrom(new Vector2i(), scanOrder);
this.scanSpaceSize = new SpaceSize(new Vector3i(-range, 0, -range), new Vector3i(1 + range, 0, 1 + range));
} else {
throw new IllegalArgumentException();
}
}
@Nonnull
@Override
public List<Vector3i> scan(@Nonnull Scanner.Context context) {
if (this.resultCap == 0) {
return Collections.emptyList();
} else {
ArrayList<Vector3i> validPositions = new ArrayList<>(this.resultCap);
for (Vector2i column : this.scanOrder) {
Vector3i columnOrigin = new Vector3i(context.position.x + column.x, context.position.y, context.position.z + column.y);
Scanner.Context childContext = new Scanner.Context(columnOrigin, context.pattern, context.materialSpace, context.workerId);
for (Vector3i result : this.childScanner.scan(childContext)) {
validPositions.add(result);
if (validPositions.size() == this.resultCap) {
return validPositions;
}
}
}
return validPositions;
}
}
@Nonnull
@Override
public SpaceSize scanSpace() {
return this.scanSpaceSize.clone();
}
public static enum ScanShape {
CIRCLE,
SQUARE;
public static final Codec<AreaScanner.ScanShape> CODEC = new EnumCodec<>(AreaScanner.ScanShape.class, EnumCodec.EnumStyle.LEGACY);
}
public static enum Verticality {
GLOBAL,
LOCAL;
}
}