233 lines
7.8 KiB
Java
233 lines
7.8 KiB
Java
package com.hypixel.hytale.builtin.hytalegenerator.patterns;
|
|
|
|
import com.hypixel.hytale.builtin.hytalegenerator.bounds.SpaceSize;
|
|
import com.hypixel.hytale.math.vector.Vector3d;
|
|
import com.hypixel.hytale.math.vector.Vector3i;
|
|
import java.util.ArrayList;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import javax.annotation.Nonnull;
|
|
|
|
public class GapPattern extends Pattern {
|
|
private List<List<GapPattern.PositionedPattern>> axisPositionedPatterns;
|
|
private List<GapPattern.PositionedPattern> depthPositionedPatterns;
|
|
private double gapSize;
|
|
private double anchorSize;
|
|
private double anchorRoughness;
|
|
private int depthDown;
|
|
private int depthUp;
|
|
private Pattern gapPattern;
|
|
private Pattern anchorPattern;
|
|
private SpaceSize readSpaceSize;
|
|
|
|
public GapPattern(
|
|
@Nonnull List<Float> angles,
|
|
double gapSize,
|
|
double anchorSize,
|
|
double anchorRoughness,
|
|
int depthDown,
|
|
int depthUp,
|
|
@Nonnull Pattern gapPattern,
|
|
@Nonnull Pattern anchorPattern
|
|
) {
|
|
if (!(gapSize < 0.0) && !(anchorSize < 0.0) && !(anchorRoughness < 0.0) && depthDown >= 0 && depthUp >= 0) {
|
|
this.gapSize = gapSize;
|
|
this.anchorSize = anchorSize;
|
|
this.gapPattern = gapPattern;
|
|
this.anchorPattern = anchorPattern;
|
|
this.anchorRoughness = anchorRoughness;
|
|
this.depthDown = depthDown;
|
|
this.depthUp = depthUp;
|
|
this.depthPositionedPatterns = this.renderDepths();
|
|
this.axisPositionedPatterns = new ArrayList<>(angles.size());
|
|
|
|
for (float angle : angles) {
|
|
List<GapPattern.PositionedPattern> positions = this.renderPositions(angle);
|
|
this.axisPositionedPatterns.add(positions);
|
|
}
|
|
|
|
Vector3i min = null;
|
|
Vector3i max = null;
|
|
|
|
for (List<GapPattern.PositionedPattern> direction : this.axisPositionedPatterns) {
|
|
for (GapPattern.PositionedPattern pos : direction) {
|
|
if (min == null) {
|
|
min = pos.position.clone();
|
|
max = pos.position.clone();
|
|
} else {
|
|
min = Vector3i.min(min, pos.position);
|
|
max = Vector3i.max(max, pos.position);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (max == null) {
|
|
this.readSpaceSize = new SpaceSize(new Vector3i(), new Vector3i());
|
|
} else {
|
|
max.add(1, 1, 1);
|
|
this.readSpaceSize = new SpaceSize(min, max);
|
|
}
|
|
} else {
|
|
throw new IllegalArgumentException("negative sizes");
|
|
}
|
|
}
|
|
|
|
@Nonnull
|
|
private List<GapPattern.PositionedPattern> renderDepths() {
|
|
ArrayList<GapPattern.PositionedPattern> positions = new ArrayList<>();
|
|
Vector3i pointer = new Vector3i();
|
|
int stepsDown = this.depthDown - 1;
|
|
|
|
for (int i = 0; i < this.depthDown; i++) {
|
|
pointer.add(0, -1, 0);
|
|
positions.add(new GapPattern.PositionedPattern(this.gapPattern, pointer.clone()));
|
|
}
|
|
|
|
pointer = new Vector3i();
|
|
int stepsUp = this.depthUp - 1;
|
|
|
|
for (int i = 0; i < this.depthUp; i++) {
|
|
pointer.add(0, 1, 0);
|
|
positions.add(new GapPattern.PositionedPattern(this.gapPattern, pointer.clone()));
|
|
}
|
|
|
|
return positions;
|
|
}
|
|
|
|
@Nonnull
|
|
private List<GapPattern.PositionedPattern> renderPositions(float angle) {
|
|
ArrayList<GapPattern.PositionedPattern> positions = new ArrayList<>();
|
|
positions.addAll(this.renderHalfPositions(angle));
|
|
positions.addAll(this.renderHalfPositions((float) Math.PI + angle));
|
|
ArrayList<GapPattern.PositionedPattern> uniquePositions = new ArrayList<>(positions.size());
|
|
HashSet<Vector3i> positionsSet = new HashSet<>();
|
|
|
|
for (GapPattern.PositionedPattern e : positions) {
|
|
if (!positionsSet.contains(e.position)) {
|
|
uniquePositions.add(e);
|
|
positionsSet.add(e.position);
|
|
}
|
|
}
|
|
|
|
return uniquePositions;
|
|
}
|
|
|
|
@Nonnull
|
|
private List<GapPattern.PositionedPattern> renderHalfPositions(float angle) {
|
|
ArrayList<GapPattern.PositionedPattern> positions = new ArrayList<>();
|
|
double halfGap = this.gapSize / 2.0 - 1.0 - this.anchorRoughness;
|
|
halfGap = Math.max(0.0, halfGap);
|
|
double halfWall = this.anchorSize / 2.0;
|
|
Vector3d pointer = new Vector3d(0.5, 0.5, 0.5);
|
|
Vector3d mov = new Vector3d(0.0, 0.0, -1.0);
|
|
mov.rotateY(angle);
|
|
double stepSize = 0.5;
|
|
mov.setLength(stepSize);
|
|
int steps = (int)(halfGap / stepSize);
|
|
|
|
for (int s = 0; s < steps; s++) {
|
|
pointer.add(mov);
|
|
positions.add(new GapPattern.PositionedPattern(this.gapPattern, pointer.toVector3i()));
|
|
}
|
|
|
|
positions.add(new GapPattern.PositionedPattern(this.gapPattern, new Vector3i()));
|
|
pointer = mov.clone().setLength(halfGap).add(0.5, 0.5, 0.5);
|
|
positions.add(new GapPattern.PositionedPattern(this.gapPattern, pointer.toVector3i()));
|
|
Vector3d anchor = mov.clone().setLength(this.gapSize / 2.0);
|
|
pointer = anchor.clone().add(0.5, 0.5, 0.5);
|
|
positions.add(new GapPattern.PositionedPattern(this.anchorPattern, anchor.toVector3i()));
|
|
mov.rotateY((float) (Math.PI / 2));
|
|
steps = (int)(halfWall / stepSize);
|
|
|
|
for (int s = 0; s < steps; s++) {
|
|
pointer.add(mov);
|
|
positions.add(new GapPattern.PositionedPattern(this.anchorPattern, pointer.toVector3i()));
|
|
}
|
|
|
|
Vector3d wallTip = anchor.clone().add(0.5, 0.5, 0.5);
|
|
wallTip.add(mov.clone().setLength(halfWall));
|
|
positions.add(new GapPattern.PositionedPattern(this.anchorPattern, wallTip.toVector3i()));
|
|
mov.scale(-1.0);
|
|
pointer = anchor.clone().add(0.5, 0.5, 0.5);
|
|
|
|
for (int s = 0; s < steps; s++) {
|
|
pointer.add(mov);
|
|
positions.add(new GapPattern.PositionedPattern(this.anchorPattern, pointer.toVector3i()));
|
|
}
|
|
|
|
wallTip = anchor.clone().add(0.5, 0.5, 0.5);
|
|
wallTip.add(mov.clone().setLength(halfWall));
|
|
positions.add(new GapPattern.PositionedPattern(this.anchorPattern, wallTip.toVector3i()));
|
|
return positions;
|
|
}
|
|
|
|
@Override
|
|
public boolean matches(@Nonnull Pattern.Context context) {
|
|
Vector3i childPosition = new Vector3i();
|
|
Pattern.Context childContext = new Pattern.Context(context);
|
|
childContext.position = childPosition;
|
|
|
|
for (GapPattern.PositionedPattern entry : this.depthPositionedPatterns) {
|
|
childPosition.assign(entry.position).add(context.position);
|
|
if (!entry.pattern.matches(childContext)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
for (List<GapPattern.PositionedPattern> patternsInDirection : this.axisPositionedPatterns) {
|
|
boolean matchesDirection = true;
|
|
|
|
for (GapPattern.PositionedPattern entryx : patternsInDirection) {
|
|
childPosition.assign(entryx.position).add(context.position);
|
|
if (!entryx.pattern.matches(context)) {
|
|
matchesDirection = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (matchesDirection) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public SpaceSize readSpace() {
|
|
return this.readSpaceSize.clone();
|
|
}
|
|
|
|
public static class PositionedPattern {
|
|
private Vector3i position;
|
|
private Pattern pattern;
|
|
|
|
public PositionedPattern(@Nonnull Pattern pattern, @Nonnull Vector3i position) {
|
|
this.pattern = pattern;
|
|
this.position = position.clone();
|
|
}
|
|
|
|
public int getX() {
|
|
return this.position.x;
|
|
}
|
|
|
|
public int getY() {
|
|
return this.position.y;
|
|
}
|
|
|
|
public int getZ() {
|
|
return this.position.z;
|
|
}
|
|
|
|
public Pattern getPattern() {
|
|
return this.pattern;
|
|
}
|
|
|
|
@Nonnull
|
|
protected GapPattern.PositionedPattern clone() {
|
|
return new GapPattern.PositionedPattern(this.pattern, this.position.clone());
|
|
}
|
|
}
|
|
}
|