2021-05-17 03:02:24 +08:00
|
|
|
package com.gtnewhorizon.structurelib.alignment;
|
2022-07-08 17:14:18 +08:00
|
|
|
|
2022-08-08 17:40:12 +08:00
|
|
|
import static com.gtnewhorizon.structurelib.alignment.IAlignment.STATES_COUNT;
|
|
|
|
|
|
2021-05-27 18:26:05 +08:00
|
|
|
import java.util.Arrays;
|
|
|
|
|
import java.util.Optional;
|
|
|
|
|
import java.util.function.Function;
|
2023-01-30 12:52:27 +00:00
|
|
|
|
2022-08-08 17:40:12 +08:00
|
|
|
import net.minecraftforge.common.util.ForgeDirection;
|
2021-05-27 18:26:05 +08:00
|
|
|
|
2021-05-17 03:02:24 +08:00
|
|
|
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
|
|
|
|
import com.gtnewhorizon.structurelib.alignment.enumerable.Flip;
|
|
|
|
|
import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation;
|
2023-01-30 12:52:27 +00:00
|
|
|
|
2021-05-17 03:02:24 +08:00
|
|
|
public interface IAlignmentLimits {
|
|
|
|
|
|
2025-07-31 21:54:59 -06:00
|
|
|
/**
|
|
|
|
|
* Can be placed in any orientation.
|
|
|
|
|
*/
|
2021-05-27 18:26:05 +08:00
|
|
|
IAlignmentLimits UNLIMITED = (direction, rotation, flip) -> true;
|
2021-05-17 03:02:24 +08:00
|
|
|
|
2025-07-31 21:54:59 -06:00
|
|
|
/**
|
|
|
|
|
* Must be standing upright; i.e., top side of the block facing up.
|
|
|
|
|
*/
|
|
|
|
|
IAlignmentLimits UPRIGHT = (direction, rotation, flip) -> direction.offsetY == 0
|
|
|
|
|
&& (flip.isVerticallyFliped() ? rotation.isUpsideDown() : rotation.isNotRotated());
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Can be in any orientation except upside down; i.e., top side of the block facing down.
|
|
|
|
|
*/
|
|
|
|
|
IAlignmentLimits NOT_UPSIDE_DOWN = (direction, rotation, flip) -> direction.offsetY != 0
|
|
|
|
|
|| (flip.isVerticallyFliped() ? !rotation.isNotRotated() : !rotation.isUpsideDown());
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Front side of the block must be facing up.
|
|
|
|
|
*/
|
|
|
|
|
IAlignmentLimits FACING_UP = (direction, rotation, flip) -> direction == ForgeDirection.UP;
|
|
|
|
|
|
2021-05-17 03:02:24 +08:00
|
|
|
boolean isNewExtendedFacingValid(ForgeDirection direction, Rotation rotation, Flip flip);
|
|
|
|
|
|
2021-05-27 18:26:05 +08:00
|
|
|
default boolean isNewExtendedFacingValid(ExtendedFacing alignment) {
|
2022-08-08 17:40:12 +08:00
|
|
|
return isNewExtendedFacingValid(alignment.getDirection(), alignment.getRotation(), alignment.getFlip());
|
2021-05-17 03:02:24 +08:00
|
|
|
}
|
2021-05-27 18:26:05 +08:00
|
|
|
|
2021-05-29 19:10:15 +08:00
|
|
|
static IAlignmentLimits allowOnly(ExtendedFacing... allowedFacings) {
|
|
|
|
|
Builder builder = Builder.denyAll();
|
|
|
|
|
for (ExtendedFacing allowedFacing : allowedFacings) {
|
|
|
|
|
builder.allow(allowedFacing);
|
|
|
|
|
}
|
|
|
|
|
return builder.build();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static IAlignmentLimits denyOnly(ExtendedFacing... allowedFacings) {
|
|
|
|
|
Builder builder = Builder.allowAll();
|
|
|
|
|
for (ExtendedFacing allowedFacing : allowedFacings) {
|
|
|
|
|
builder.deny(allowedFacing);
|
|
|
|
|
}
|
|
|
|
|
return builder.build();
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-27 18:26:05 +08:00
|
|
|
class Builder {
|
2023-01-30 12:52:27 +00:00
|
|
|
|
2021-05-27 18:26:05 +08:00
|
|
|
protected final boolean[] validStates = new boolean[STATES_COUNT];
|
|
|
|
|
|
2022-08-08 17:40:12 +08:00
|
|
|
private Builder() {}
|
2021-05-29 19:10:15 +08:00
|
|
|
|
2021-05-27 18:26:05 +08:00
|
|
|
public static Builder allowAll() {
|
|
|
|
|
Builder b = new Builder();
|
|
|
|
|
Arrays.fill(b.validStates, true);
|
|
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Builder denyAll() {
|
|
|
|
|
Builder b = new Builder();
|
|
|
|
|
Arrays.fill(b.validStates, true);
|
|
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Builder deny(ForgeDirection fd) {
|
2022-08-08 17:40:12 +08:00
|
|
|
ExtendedFacing.getAllWith(fd).stream().mapToInt(ExtendedFacing::getIndex)
|
|
|
|
|
.forEach(v -> validStates[v] = false);
|
2021-05-27 18:26:05 +08:00
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Builder allow(ForgeDirection fd) {
|
2022-08-08 17:40:12 +08:00
|
|
|
ExtendedFacing.getAllWith(fd).stream().mapToInt(ExtendedFacing::getIndex)
|
|
|
|
|
.forEach(v -> validStates[v] = true);
|
2021-05-27 18:26:05 +08:00
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-29 17:56:28 +08:00
|
|
|
public Builder deny(ExtendedFacing o) {
|
|
|
|
|
validStates[o.getIndex()] = false;
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Builder allow(ExtendedFacing o) {
|
|
|
|
|
validStates[o.getIndex()] = true;
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-27 18:26:05 +08:00
|
|
|
public Builder deny(Rotation fd) {
|
2022-08-08 17:40:12 +08:00
|
|
|
ExtendedFacing.getAllWith(fd).stream().mapToInt(ExtendedFacing::getIndex)
|
|
|
|
|
.forEach(v -> validStates[v] = false);
|
2021-05-27 18:26:05 +08:00
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Builder allow(Rotation fd) {
|
2022-08-08 17:40:12 +08:00
|
|
|
ExtendedFacing.getAllWith(fd).stream().mapToInt(ExtendedFacing::getIndex)
|
|
|
|
|
.forEach(v -> validStates[v] = true);
|
2021-05-27 18:26:05 +08:00
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Builder deny(Flip fd) {
|
2022-08-08 17:40:12 +08:00
|
|
|
ExtendedFacing.getAllWith(fd).stream().mapToInt(ExtendedFacing::getIndex)
|
|
|
|
|
.forEach(v -> validStates[v] = false);
|
2021-05-27 18:26:05 +08:00
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Builder allow(Flip fd) {
|
2022-08-08 17:40:12 +08:00
|
|
|
ExtendedFacing.getAllWith(fd).stream().mapToInt(ExtendedFacing::getIndex)
|
|
|
|
|
.forEach(v -> validStates[v] = true);
|
2021-05-27 18:26:05 +08:00
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Builder filter(Function<ExtendedFacing, Optional<Boolean>> predicate) {
|
|
|
|
|
for (ExtendedFacing value : ExtendedFacing.VALUES) {
|
|
|
|
|
predicate.apply(value).ifPresent(bool -> validStates[value.getIndex()] = bool);
|
|
|
|
|
}
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Builder ensureDuplicates() {
|
|
|
|
|
for (ExtendedFacing value : ExtendedFacing.VALUES) {
|
|
|
|
|
if (validStates[value.getIndex()]) {
|
|
|
|
|
validStates[value.getDuplicate().getIndex()] = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-09-06 16:34:46 +08:00
|
|
|
* Prefers rotation to flip, so both flip will get translated to opposite rotation and no flip
|
2021-05-27 18:26:05 +08:00
|
|
|
*
|
|
|
|
|
* @param flip the preferred flip to be used Horizontal or vertical
|
|
|
|
|
* @return this
|
|
|
|
|
*/
|
|
|
|
|
public Builder ensureNoDuplicates(Flip flip) {
|
|
|
|
|
if (flip == Flip.BOTH || flip == Flip.NONE) {
|
|
|
|
|
throw new IllegalArgumentException("Preffered Flip must be Horizontal or Vertical");
|
|
|
|
|
}
|
|
|
|
|
flip = flip.getOpposite();
|
|
|
|
|
for (ExtendedFacing value : ExtendedFacing.VALUES) {
|
|
|
|
|
if (validStates[value.getIndex()]) {
|
|
|
|
|
if (value.getFlip() == Flip.BOTH || value.getFlip() == flip) {
|
|
|
|
|
validStates[value.getIndex()] = false;
|
|
|
|
|
validStates[value.getDuplicate().getIndex()] = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IAlignmentLimits build() {
|
|
|
|
|
return new AlignmentLimits(validStates);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-17 03:02:24 +08:00
|
|
|
}
|