package game.world; import java.util.Iterator; import java.util.Map; import java.util.function.Predicate; import game.ExtMath; import game.collect.Iterators; import game.collect.Maps; import game.properties.IStringSerializable; import game.rng.Random; public enum Facing implements IStringSerializable { DOWN(0, 2, 1, -1, "down", Facing.AxisDirection.NEGATIVE, Facing.Axis.Y, new Vec3i(0, -1, 0)), UP(1, 3, 0, -1, "up", Facing.AxisDirection.POSITIVE, Facing.Axis.Y, new Vec3i(0, 1, 0)), NORTH(2, 4, 3, 2, "north", Facing.AxisDirection.NEGATIVE, Facing.Axis.Z, new Vec3i(0, 0, -1)), SOUTH(3, 5, 2, 0, "south", Facing.AxisDirection.POSITIVE, Facing.Axis.Z, new Vec3i(0, 0, 1)), WEST(4, 1, 5, 1, "west", Facing.AxisDirection.NEGATIVE, Facing.Axis.X, new Vec3i(-1, 0, 0)), EAST(5, 0, 4, 3, "east", Facing.AxisDirection.POSITIVE, Facing.Axis.X, new Vec3i(1, 0, 0)); /** Ordering index for D-U-N-S-W-E */ private final int index; private final int qindex; /** Index of the opposite Facing in the VALUES array */ private final int opposite; /** Ordering index for the HORIZONTALS field (S-W-N-E) */ private final int horizontalIndex; private final String name; private final Facing.Axis axis; private final Facing.AxisDirection axisDirection; /** Normalized Vector that points in the direction of this Facing */ private final Vec3i directionVec; /** All facings in D-U-N-S-W-E order */ private static final Facing[] VALUES = new Facing[6]; /** All Facings with horizontal axis in order S-W-N-E */ private static final Facing[] HORIZONTALS = new Facing[4]; private static final Map NAME_LOOKUP = Maps.newHashMap(); private Facing(int indexIn, int qindexIn, int oppositeIn, int horizontalIndexIn, String nameIn, Facing.AxisDirection axisDirectionIn, Facing.Axis axisIn, Vec3i directionVecIn) { this.index = indexIn; this.qindex = qindexIn; this.horizontalIndex = horizontalIndexIn; this.opposite = oppositeIn; this.name = nameIn; this.axis = axisIn; this.axisDirection = axisDirectionIn; this.directionVec = directionVecIn; } /** * Get the Index of this Facing (0-5). The order is D-U-N-S-W-E */ public int getIndex() { return this.index; } public int getQIndex() { return this.qindex; } /** * Get the index of this horizontal facing (0-3). The order is S-W-N-E */ public int getHorizontalIndex() { return this.horizontalIndex; } /** * Get the AxisDirection of this Facing. */ public Facing.AxisDirection getAxisDirection() { return this.axisDirection; } /** * Get the opposite Facing (e.g. DOWN => UP) */ public Facing getOpposite() { return getFront(this.opposite); } /** * Rotate this Facing around the given axis clockwise. If this facing cannot be rotated around the given axis, * returns this facing without rotating. */ public Facing rotateAround(Facing.Axis axis) { switch (axis) { case X: if (this != WEST && this != EAST) { return this.rotateX(); } return this; case Y: if (this != UP && this != DOWN) { return this.rotateY(); } return this; case Z: if (this != NORTH && this != SOUTH) { return this.rotateZ(); } return this; default: throw new IllegalStateException("Unable to get CW facing for axis " + axis); } } /** * Rotate this Facing around the Y axis clockwise (NORTH => EAST => SOUTH => WEST => NORTH) */ public Facing rotateY() { switch (this) { case NORTH: return EAST; case EAST: return SOUTH; case SOUTH: return WEST; case WEST: return NORTH; default: throw new IllegalStateException("Unable to get Y-rotated facing of " + this); } } /** * Rotate this Facing around the X axis (NORTH => DOWN => SOUTH => UP => NORTH) */ private Facing rotateX() { switch (this) { case NORTH: return DOWN; case EAST: case WEST: default: throw new IllegalStateException("Unable to get X-rotated facing of " + this); case SOUTH: return UP; case UP: return NORTH; case DOWN: return SOUTH; } } /** * Rotate this Facing around the Z axis (EAST => DOWN => WEST => UP => EAST) */ private Facing rotateZ() { switch (this) { case EAST: return DOWN; case SOUTH: default: throw new IllegalStateException("Unable to get Z-rotated facing of " + this); case WEST: return UP; case UP: return EAST; case DOWN: return WEST; } } /** * Rotate this Facing around the Y axis counter-clockwise (NORTH => WEST => SOUTH => EAST => NORTH) */ public Facing rotateYCCW() { switch (this) { case NORTH: return WEST; case EAST: return NORTH; case SOUTH: return EAST; case WEST: return SOUTH; default: throw new IllegalStateException("Unable to get CCW facing of " + this); } } /** * Returns a offset that addresses the block in front of this facing. */ public int getFrontOffsetX() { return this.axis == Facing.Axis.X ? this.axisDirection.getOffset() : 0; } public int getFrontOffsetY() { return this.axis == Facing.Axis.Y ? this.axisDirection.getOffset() : 0; } /** * Returns a offset that addresses the block in front of this facing. */ public int getFrontOffsetZ() { return this.axis == Facing.Axis.Z ? this.axisDirection.getOffset() : 0; } /** * Same as getName, but does not override the method from Enum. */ public String getName2() { return this.name; } public Facing.Axis getAxis() { return this.axis; } /** * Get the facing specified by the given name */ public static Facing byName(String name) { return name == null ? null : (Facing)NAME_LOOKUP.get(name.toLowerCase()); } /** * Get a Facing by it's index (0-5). The order is D-U-N-S-W-E. Named getFront for legacy reasons. */ public static Facing getFront(int index) { return VALUES[ExtMath.absi(index % VALUES.length)]; } /** * Get a Facing by it's horizontal index (0-3). The order is S-W-N-E. */ public static Facing getHorizontal(int p_176731_0_) { return HORIZONTALS[ExtMath.absi(p_176731_0_ % HORIZONTALS.length)]; } /** * Get the Facing corresponding to the given angle (0-360). An angle of 0 is SOUTH, an angle of 90 would be WEST. */ public static Facing fromAngle(double angle) { return getHorizontal(ExtMath.floord(angle / 90.0D + 0.5D) & 3); } /** * Choose a random Facing using the given Random */ public static Facing random(Random rand) { return values()[rand.zrange(values().length)]; } public static Facing randHorizontal(Random rand) { return rand.pick(HORIZONTALS); } public static Facing getFacingFromVector(float p_176737_0_, float p_176737_1_, float p_176737_2_) { Facing enumfacing = NORTH; float f = Float.MIN_VALUE; for (Facing enumfacing1 : values()) { float f1 = p_176737_0_ * (float)enumfacing1.directionVec.getX() + p_176737_1_ * (float)enumfacing1.directionVec.getY() + p_176737_2_ * (float)enumfacing1.directionVec.getZ(); if (f1 > f) { f = f1; enumfacing = enumfacing1; } } return enumfacing; } public String toString() { return this.name; } public String getName() { return this.name; } public static Facing getFacingFromAxis(Facing.AxisDirection p_181076_0_, Facing.Axis p_181076_1_) { for (Facing enumfacing : values()) { if (enumfacing.getAxisDirection() == p_181076_0_ && enumfacing.getAxis() == p_181076_1_) { return enumfacing; } } throw new IllegalArgumentException("No such direction: " + p_181076_0_ + " " + p_181076_1_); } /** * Get a normalized Vector that points in the direction of this Facing. */ public Vec3i getDirectionVec() { return this.directionVec; } static { for (Facing enumfacing : values()) { VALUES[enumfacing.index] = enumfacing; if (enumfacing.getAxis().isHorizontal()) { HORIZONTALS[enumfacing.horizontalIndex] = enumfacing; } NAME_LOOKUP.put(enumfacing.getName2().toLowerCase(), enumfacing); } } public static enum Axis implements Predicate, IStringSerializable { X("x", Facing.Plane.HORIZONTAL), Y("y", Facing.Plane.VERTICAL), Z("z", Facing.Plane.HORIZONTAL); private static final Map NAME_LOOKUP = Maps.newHashMap(); private final String name; private final Facing.Plane plane; private Axis(String name, Facing.Plane plane) { this.name = name; this.plane = plane; } public static Facing.Axis byName(String name) { return name == null ? null : (Facing.Axis)NAME_LOOKUP.get(name.toLowerCase()); } public String getName2() { return this.name; } public boolean isVertical() { return this.plane == Facing.Plane.VERTICAL; } public boolean isHorizontal() { return this.plane == Facing.Plane.HORIZONTAL; } public String toString() { return this.name; } public boolean test(Facing p_apply_1_) { return p_apply_1_ != null && p_apply_1_.getAxis() == this; } public Facing.Plane getPlane() { return this.plane; } public String getName() { return this.name; } static { for (Facing.Axis enumfacing$axis : values()) { NAME_LOOKUP.put(enumfacing$axis.getName2().toLowerCase(), enumfacing$axis); } } } public static enum AxisDirection { POSITIVE(1, "Towards positive"), NEGATIVE(-1, "Towards negative"); private final int offset; private final String description; private AxisDirection(int offset, String description) { this.offset = offset; this.description = description; } public int getOffset() { return this.offset; } public String toString() { return this.description; } } public static enum Plane implements Predicate, Iterable { HORIZONTAL, VERTICAL; public Facing[] facings() { switch (this) { case HORIZONTAL: return new Facing[] {Facing.NORTH, Facing.EAST, Facing.SOUTH, Facing.WEST}; case VERTICAL: return new Facing[] {Facing.UP, Facing.DOWN}; default: throw new Error("Someone\'s been tampering with the universe!"); } } public Facing random(Random rand) { Facing[] aenumfacing = this.facings(); return aenumfacing[rand.zrange(aenumfacing.length)]; } public boolean test(Facing p_apply_1_) { return p_apply_1_ != null && p_apply_1_.getAxis().getPlane() == this; } public Iterator iterator() { return Iterators.forArray(this.facings()); } } }