Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
import net.minecraft.util.Vec3;
import net.minecraftforge.common.util.ForgeDirection;

import org.joml.Vector3i;

import com.gtnewhorizon.structurelib.alignment.enumerable.Direction;
import com.gtnewhorizon.structurelib.coords.CoordinateSystem;
import com.gtnewhorizon.structurelib.coords.Position;
import com.gtnewhorizon.structurelib.util.Vec3Impl;

public class IntegerAxisSwap {
Expand Down Expand Up @@ -91,4 +95,32 @@ public void inverseTranslate(double[] point, double[] out) {
out[1] = forFirstAxis.get1() * point[0] + forSecondAxis.get1() * point[1] + forThirdAxis.get1() * point[2];
out[2] = forFirstAxis.get2() * point[0] + forSecondAxis.get2() * point[1] + forThirdAxis.get2() * point[2];
}

public Vector3i translate(Vector3i point) {
return new Vector3i(
forFirstAxis.get0() * point.x() + forFirstAxis.get1() * point.y() + forFirstAxis.get2() * point.z(),
forSecondAxis.get0() * point.x() + forSecondAxis.get1() * point.y() + forSecondAxis.get2() * point.z(),
forThirdAxis.get0() * point.x() + forThirdAxis.get1() * point.y() + forThirdAxis.get2() * point.z());
}

public Vector3i inverseTranslate(Vector3i point) {
return new Vector3i(
forFirstAxis.get0() * point.x() + forSecondAxis.get0() * point.y() + forThirdAxis.get0() * point.z(),
forFirstAxis.get1() * point.x() + forSecondAxis.get1() * point.y() + forThirdAxis.get1() * point.z(),
forFirstAxis.get2() * point.x() + forSecondAxis.get2() * point.y() + forThirdAxis.get2() * point.z());
}

public <C extends CoordinateSystem<C, ?>> Position<C> translate(Position<?> point) {
return new Position<>(
forFirstAxis.get0() * point.x() + forFirstAxis.get1() * point.y() + forFirstAxis.get2() * point.z(),
forSecondAxis.get0() * point.x() + forSecondAxis.get1() * point.y() + forSecondAxis.get2() * point.z(),
forThirdAxis.get0() * point.x() + forThirdAxis.get1() * point.y() + forThirdAxis.get2() * point.z());
}

public <C extends CoordinateSystem<C, ?>> Position<C> inverseTranslate(Position<?> point) {
return new Position<>(
forFirstAxis.get0() * point.x() + forSecondAxis.get0() * point.y() + forThirdAxis.get0() * point.z(),
forFirstAxis.get1() * point.x() + forSecondAxis.get1() * point.y() + forThirdAxis.get1() * point.z(),
forFirstAxis.get2() * point.x() + forSecondAxis.get2() * point.y() + forThirdAxis.get2() * point.z());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.google.common.collect.ImmutableSet;
import com.gtnewhorizon.structurelib.alignment.IAlignment;
import com.gtnewhorizon.structurelib.alignment.IntegerAxisSwap;
import com.gtnewhorizon.structurelib.coords.StructureRelativeCoords;
import com.gtnewhorizon.structurelib.util.Vec3Impl;

public enum ExtendedFacing {
Expand Down Expand Up @@ -166,6 +167,7 @@ public enum ExtendedFacing {

private final String name;
private final IntegerAxisSwap integerAxisSwap;
private final StructureRelativeCoords coordinateSystem;

ExtendedFacing(String name) {
this.name = name;
Expand Down Expand Up @@ -247,6 +249,7 @@ public enum ExtendedFacing {
this.b = b;
this.c = c;
integerAxisSwap = new IntegerAxisSwap(a, b, c);
coordinateSystem = new StructureRelativeCoords(integerAxisSwap);
}

public static ExtendedFacing of(ForgeDirection direction, Rotation rotation, Flip flip) {
Expand Down Expand Up @@ -437,4 +440,8 @@ public ForgeDirection getRelativeBackInWorld() {
public ForgeDirection getRelativeForwardInWorld() {
return c.getOpposite();
}

public StructureRelativeCoords asCoordinateSystem() {
return coordinateSystem;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.gtnewhorizon.structurelib.coords;

/**
* Controller-relative coordinates. The controller is at 0,0,0. No axis swapping takes place, each axis points in the
* same directions as the matching world axis.
*/
public class ControllerRelativeCoords implements CoordinateSystem<ControllerRelativeCoords, WorldCoords> {

public final int controllerX, controllerY, controllerZ;

public ControllerRelativeCoords(int controllerX, int controllerY, int controllerZ) {
this.controllerX = controllerX;
this.controllerY = controllerY;
this.controllerZ = controllerZ;
}

@Override
public Position<ControllerRelativeCoords> translate(Position<WorldCoords> position) {
return translate(position, controllerX, controllerY, controllerZ);
}

@Override
public Position<WorldCoords> translateInverse(Position<ControllerRelativeCoords> position) {
return translateInverse(position, controllerX, controllerY, controllerZ);
}

public static Position<ControllerRelativeCoords> translate(Position<WorldCoords> position, int controllerX,
int controllerY, int controllerZ) {
position.sub(controllerX, controllerY, controllerZ);

return CoordinateSystem.transmute(position);
}

public static Position<WorldCoords> translateInverse(Position<ControllerRelativeCoords> position, int controllerX,
int controllerY, int controllerZ) {
position.add(controllerX, controllerY, controllerZ);

return CoordinateSystem.transmute(position);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.gtnewhorizon.structurelib.coords;

import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;

/**
* A coordinate system is a statically-checked helper for determining which coordinates a {@link Position} has.
* Translation methods never copy a {@link Position} - if a position must remain unchanged, it must be copied
* separately. Most coordinate systems will have static methods that allow you to avoid allocations, though some (such
* as the ones provided by {@link ExtendedFacing#asCoordinateSystem()}) have no reason to be static.
*
* @param <Self>
* @param <Parent>
*/
public interface CoordinateSystem<Self extends CoordinateSystem<Self, Parent>, Parent extends CoordinateSystem<Parent, ?>> {

/**
* Translates a position from the parent coordinate system into this one.
*/
Position<Self> translate(Position<Parent> position);

/**
* Translates a position from this coordinate system into the parent.
*/
Position<Parent> translateInverse(Position<Self> position);

/**
* Helper method that converts a position's coordinate system. Should not be used unless you know it's correct.
*/
static <P1 extends CoordinateSystem<P1, ?>, P2 extends CoordinateSystem<P2, ?>> Position<P1> transmute(
Position<P2> pos) {
// noinspection unchecked
return (Position<P1>) pos;
}
}
73 changes: 73 additions & 0 deletions src/main/java/com/gtnewhorizon/structurelib/coords/Position.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.gtnewhorizon.structurelib.coords;

import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.world.ChunkPosition;

import org.joml.Vector3f;
import org.joml.Vector3i;

import com.gtnewhorizon.gtnhlib.blockpos.BlockPos;
import com.gtnewhorizon.structurelib.util.Vec3Impl;

/**
* A {@link BlockPos} with a statically-checked coordinate system.
*/
public class Position<C extends CoordinateSystem<C, ?>> extends BlockPos {

public Position() {

}

public Position(int x, int y, int z) {
super(x, y, z);
}

public Position(float x, float y, float z) {
super(MathHelper.floor_float(x), MathHelper.floor_float(y), MathHelper.floor_float(z));
}

public Position(double x, double y, double z) {
super(MathHelper.floor_double(x), MathHelper.floor_double(y), MathHelper.floor_double(z));
}

public Position(ChunkPosition chunkPosition) {
super(chunkPosition);
}

public Position(Vector3i v) {
super(v.x, v.y, v.z);
}

public Position(Vector3f v) {
this(v.x, v.y, v.z);
}

public Position(Vec3 v) {
this(v.xCoord, v.yCoord, v.zCoord);
}

public Position(Vec3Impl v) {
this(v.get0(), v.get1(), v.get2());
}

public Position<C> copy() {
return new Position<>(x, y, z);
}

public Vector3i toVector3i() {
return new Vector3i(x, y, z);
}

public Vector3f toVector3f() {
return new Vector3f(x, y, z);
}

public Vec3 toVec3() {
return Vec3.createVectorHelper(x, y, z);
}

public Vec3Impl toVec3Impl() {
return new Vec3Impl(x, y, z);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.gtnewhorizon.structurelib.coords;

/// The structure definition-local coords. 0,0,0 is the front-most left-most top-most element. Coordinates increase as
/// you go down, right, or back.
public class StructureDefinitionCoords implements CoordinateSystem<StructureDefinitionCoords, StructureRelativeCoords> {

public final int offsetX, offsetY, offsetZ;

public StructureDefinitionCoords(int offsetX, int offsetY, int offsetZ) {
this.offsetX = offsetX;
this.offsetY = offsetY;
this.offsetZ = offsetZ;
}

@Override
public Position<StructureDefinitionCoords> translate(Position<StructureRelativeCoords> position) {
return translate(position, offsetX, offsetY, offsetZ);
}

@Override
public Position<StructureRelativeCoords> translateInverse(Position<StructureDefinitionCoords> position) {
return translateInverse(position, offsetX, offsetY, offsetZ);
}

public static Position<StructureDefinitionCoords> translate(Position<StructureRelativeCoords> position, int offsetX,
int offsetY, int offsetZ) {
position.add(offsetX, offsetY, offsetZ);

return CoordinateSystem.transmute(position);
}

public static Position<StructureRelativeCoords> translateInverse(Position<StructureDefinitionCoords> position,
int offsetX, int offsetY, int offsetZ) {
position.sub(offsetX, offsetY, offsetZ);

return CoordinateSystem.transmute(position);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.gtnewhorizon.structurelib.coords;

import com.gtnewhorizon.structurelib.alignment.IntegerAxisSwap;

/**
* Coordinates relative to the structure. 0,0,0 is the controller. 0,0,1 is the block immediately behind the controller
* (looking at it from its face). 1,0,0 is the block to the right of the controller. 0,1,0 is the block below the
* controller.
*/
public class StructureRelativeCoords implements CoordinateSystem<StructureRelativeCoords, ControllerRelativeCoords> {

public final IntegerAxisSwap axisSwap;

public StructureRelativeCoords(IntegerAxisSwap axisSwap) {
this.axisSwap = axisSwap;
}

@Override
public Position<StructureRelativeCoords> translate(Position<ControllerRelativeCoords> position) {
position.set(axisSwap.translate(position));

return CoordinateSystem.transmute(position);
}

@Override
public Position<ControllerRelativeCoords> translateInverse(Position<StructureRelativeCoords> position) {
position.set(axisSwap.inverseTranslate(position));

return CoordinateSystem.transmute(position);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.gtnewhorizon.structurelib.coords;

/**
* World block coordinates
*/
public class WorldCoords implements CoordinateSystem<WorldCoords, WorldCoords> {

public static final WorldCoords INSTANCE = new WorldCoords();

private WorldCoords() {}

@Override
public Position<WorldCoords> translate(Position<WorldCoords> position) {
return position;
}

@Override
public Position<WorldCoords> translateInverse(Position<WorldCoords> position) {
return position;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
import static com.gtnewhorizon.structurelib.structure.IStructureWalker.ignoreBlockUnloaded;
import static com.gtnewhorizon.structurelib.structure.IStructureWalker.skipBlockUnloaded;

import java.util.List;
import java.util.function.Function;

import javax.annotation.Nonnull;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
Expand All @@ -15,6 +18,8 @@
import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor;
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
import com.gtnewhorizon.structurelib.coords.Position;
import com.gtnewhorizon.structurelib.coords.StructureDefinitionCoords;

/**
* This is the structure definition of your multi. You will have one of these for each multi.
Expand Down Expand Up @@ -335,6 +340,49 @@ default void iterate(String piece, World world, ExtendedFacing extendedFacing, i
"customIterate");
}

/**
* Gets the controller position for a piece. Controller positions are denoted by a tilde.
*
* @param piece The piece name
* @return The controller position, or null if it doesn't exist for the given piece
*/
Position<StructureDefinitionCoords> getControllerPosition(String piece);

/**
* Gets the coordinate system for a piece. This is used to translate structure definition coordinates into structure
* relative coordinates.
*
* @param piece The piece
* @return The coordinate system
* @throws IllegalArgumentException When the piece does not exist
*/
StructureDefinitionCoords getCoordinateSystem(String piece);

/**
* Gets a socket from a piece.
*
* @param piece The piece name
* @param socket The socket character
* @return The socket's position
* @throws IllegalArgumentException When the piece does not exist
* @throws IllegalArgumentException When the socket does not exist
* @throws IllegalStateException When more than one socket exists with this character
* @see StructureDefinition.Builder#addSocket(char, char)
*/
Position<StructureDefinitionCoords> getSocket(String piece, char socket);

/**
* Gets all sockets with a given character for a piece.
*
* @param piece The piece name
* @param socket The socket character
* @return The list of socket positions, or an empty list if the socket is not present
* @throws IllegalArgumentException When the piece does not exist
* @see StructureDefinition.Builder#addSocket(char, char)
*/
@Nonnull
List<Position<StructureDefinitionCoords>> getAllSockets(String piece, char socket);

/**
* Low level utility.
*
Expand Down
Loading
Loading