diff --git a/src/main/java/com/dfsek/terra/command/geometry/TubeCommand.java b/src/main/java/com/dfsek/terra/command/geometry/TubeCommand.java index 8b610cc04..9f9546a3a 100644 --- a/src/main/java/com/dfsek/terra/command/geometry/TubeCommand.java +++ b/src/main/java/com/dfsek/terra/command/geometry/TubeCommand.java @@ -1,13 +1,8 @@ package com.dfsek.terra.command.geometry; -import com.dfsek.terra.WorldEditUtil; +import com.dfsek.terra.util.structure.WorldEditUtil; import com.dfsek.terra.command.type.PlayerCommand; import com.dfsek.terra.procgen.voxel.Tube; -import com.sk89q.worldedit.IncompleteRegionException; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.command.Command; diff --git a/src/main/java/com/dfsek/terra/command/structure/ExportCommand.java b/src/main/java/com/dfsek/terra/command/structure/ExportCommand.java index f70b68aed..cf257b438 100644 --- a/src/main/java/com/dfsek/terra/command/structure/ExportCommand.java +++ b/src/main/java/com/dfsek/terra/command/structure/ExportCommand.java @@ -1,15 +1,10 @@ package com.dfsek.terra.command.structure; import com.dfsek.terra.Terra; -import com.dfsek.terra.WorldEditUtil; +import com.dfsek.terra.util.structure.WorldEditUtil; import com.dfsek.terra.command.type.PlayerCommand; import com.dfsek.terra.structure.GaeaStructure; import com.dfsek.terra.structure.InitializationException; -import com.sk89q.worldedit.IncompleteRegionException; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; import org.bukkit.Location; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; diff --git a/src/main/java/com/dfsek/terra/procgen/math/Vector2.java b/src/main/java/com/dfsek/terra/procgen/math/Vector2.java index 83764e25d..1ec1a5394 100644 --- a/src/main/java/com/dfsek/terra/procgen/math/Vector2.java +++ b/src/main/java/com/dfsek/terra/procgen/math/Vector2.java @@ -154,4 +154,14 @@ public class Vector2 implements Cloneable { throw new Error(e); } } + + public Vector2 setX(double x) { + this.x = x; + return this; + } + + public Vector2 setZ(double z) { + this.z = z; + return this; + } } diff --git a/src/main/java/com/dfsek/terra/structure/GaeaStructure.java b/src/main/java/com/dfsek/terra/structure/GaeaStructure.java index 7a510c203..c99c61fd6 100644 --- a/src/main/java/com/dfsek/terra/structure/GaeaStructure.java +++ b/src/main/java/com/dfsek/terra/structure/GaeaStructure.java @@ -1,6 +1,8 @@ package com.dfsek.terra.structure; import com.dfsek.terra.Debug; +import com.dfsek.terra.procgen.math.Vector2; +import com.dfsek.terra.util.structure.RotationUtil; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -34,6 +36,8 @@ import java.util.Objects; import java.util.UUID; import java.util.function.Consumer; +import static com.dfsek.terra.util.structure.RotationUtil.*; + public class GaeaStructure implements Serializable { public static final long serialVersionUID = -6664585217063842035L; private final StructureContainedBlock[][][] structure; @@ -125,166 +129,7 @@ public class GaeaStructure implements Serializable { this.executeForBlocksInRange(getRange(Axis.X), getRange(Axis.Y), getRange(Axis.Z), block -> pasteBlock(block, origin, r), r); } - /** - * Rotate and mirror a coordinate pair. - * @param arr Array containing X and Z coordinates. - * @param r Rotation - * @return Rotated coordinate pair - */ - private int[] getRotatedCoords(int[] arr, Rotation r) { - int[] cp = Arrays.copyOf(arr, 2); - switch(r) { - case CW_90: - arr[0] = cp[1]; - arr[1] = - cp[0]; - break; - case CCW_90: - arr[0] = - cp[1]; - arr[1] = cp[0]; - break; - case CW_180: - arr[0] = - cp[0]; - arr[1] = - cp[1]; - break; - } - return arr; - } - /** - * Get the BlockFace with rotation and mirrors applied to it - * @param f BlockFace to apply rotation to - * @param r Rotation - * @return Rotated BlockFace - */ - private BlockFace getRotatedFace(BlockFace f, Rotation r) { - BlockFace n = f; - int rotateNum = r.getDegrees()/90; - int rn = faceRotation(f); - if(rn >= 0) { - n = fromRotation(faceRotation(n) + 4*rotateNum); - } - return n; - } - - private org.bukkit.Axis getRotatedAxis(org.bukkit.Axis orig, Rotation r) { - org.bukkit.Axis other = orig; - final boolean shouldSwitch = r.equals(Rotation.CW_90) || r.equals(Rotation.CCW_90); - switch(orig) { - case X: - if(shouldSwitch) other = org.bukkit.Axis.Z; - break; - case Z: - if(shouldSwitch) other = org.bukkit.Axis.X; - break; - } - return other; - } - - - /** - * Method to rotate the incredibly obnoxious Rail.Shape enum - * @param orig Original shape - * @param r Rotate - * @return Rotated/mirrored shape - */ - private Rail.Shape getRotatedRail(Rail.Shape orig, Rotation r) { - switch(r) { - case CCW_90: - switch(orig) { - case NORTH_WEST: return Rail.Shape.SOUTH_WEST; - case NORTH_SOUTH: return Rail.Shape.EAST_WEST; - case SOUTH_WEST: return Rail.Shape.SOUTH_EAST; - case SOUTH_EAST: return Rail.Shape.NORTH_EAST; - case EAST_WEST: return Rail.Shape.NORTH_SOUTH; - case NORTH_EAST: return Rail.Shape.NORTH_WEST; - case ASCENDING_EAST: return Rail.Shape.ASCENDING_NORTH; - case ASCENDING_WEST: return Rail.Shape.ASCENDING_SOUTH; - case ASCENDING_NORTH: return Rail.Shape.ASCENDING_WEST; - case ASCENDING_SOUTH: return Rail.Shape.ASCENDING_EAST; - } - case CW_90: - switch(orig) { - case NORTH_WEST: return Rail.Shape.NORTH_EAST; - case NORTH_SOUTH: return Rail.Shape.EAST_WEST; - case SOUTH_WEST: return Rail.Shape.NORTH_WEST; - case SOUTH_EAST: return Rail.Shape.SOUTH_WEST; - case EAST_WEST: return Rail.Shape.NORTH_SOUTH; - case NORTH_EAST: return Rail.Shape.SOUTH_EAST; - case ASCENDING_EAST: return Rail.Shape.ASCENDING_SOUTH; - case ASCENDING_WEST: return Rail.Shape.ASCENDING_NORTH; - case ASCENDING_NORTH: return Rail.Shape.ASCENDING_EAST; - case ASCENDING_SOUTH: return Rail.Shape.ASCENDING_WEST; - } - case CW_180: - switch(orig) { - case NORTH_WEST: return Rail.Shape.SOUTH_EAST; - case NORTH_SOUTH: return Rail.Shape.NORTH_SOUTH; - case SOUTH_WEST: return Rail.Shape.NORTH_EAST; - case SOUTH_EAST: return Rail.Shape.NORTH_WEST; - case EAST_WEST: return Rail.Shape.EAST_WEST; - case NORTH_EAST: return Rail.Shape.SOUTH_WEST; - case ASCENDING_EAST: return Rail.Shape.ASCENDING_WEST; - case ASCENDING_WEST: return Rail.Shape.ASCENDING_EAST; - case ASCENDING_NORTH: return Rail.Shape.ASCENDING_SOUTH; - case ASCENDING_SOUTH: return Rail.Shape.ASCENDING_NORTH; - } - } - return orig; - } - - /** - * Get an integer representation of a BlockFace, to perform math on. - * @param f BlockFace to get integer for - * @return integer representation of BlockFace - */ - private static int faceRotation(BlockFace f) { - switch(f) { - case NORTH: return 0; - case NORTH_NORTH_EAST: return 1; - case NORTH_EAST: return 2; - case EAST_NORTH_EAST: return 3; - case EAST: return 4; - case EAST_SOUTH_EAST: return 5; - case SOUTH_EAST: return 6; - case SOUTH_SOUTH_EAST: return 7; - case SOUTH: return 8; - case SOUTH_SOUTH_WEST: return 9; - case SOUTH_WEST: return 10; - case WEST_SOUTH_WEST: return 11; - case WEST: return 12; - case WEST_NORTH_WEST: return 13; - case NORTH_WEST: return 14; - case NORTH_NORTH_WEST: return 15; - default: return -1; - } - } - - /** - * Convert integer to BlockFace representation - * @param r integer to get BlockFace for - * @return BlockFace represented by integer. - */ - private static BlockFace fromRotation(int r) { - switch(Math.floorMod(r, 16)) { - case 0: return BlockFace.NORTH; - case 1: return BlockFace.NORTH_NORTH_EAST; - case 2: return BlockFace.NORTH_EAST; - case 3: return BlockFace.EAST_NORTH_EAST; - case 4: return BlockFace.EAST; - case 5: return BlockFace.EAST_SOUTH_EAST; - case 6: return BlockFace.SOUTH_EAST; - case 7: return BlockFace.SOUTH_SOUTH_EAST; - case 8: return BlockFace.SOUTH; - case 9: return BlockFace.SOUTH_SOUTH_WEST; - case 10: return BlockFace.SOUTH_WEST; - case 11: return BlockFace.WEST_SOUTH_WEST; - case 12: return BlockFace.WEST; - case 13: return BlockFace.WEST_NORTH_WEST; - case 14: return BlockFace.NORTH_WEST; - case 15: return BlockFace.NORTH_NORTH_WEST; - default: throw new IllegalArgumentException(); - } - } /** @@ -354,11 +199,10 @@ public class GaeaStructure implements Serializable { for(int x : xM) { for(int y : yM) { for(int z : zM) { - int[] c = getRotatedCoords(new int[] {x-structureInfo.getCenterX(), z-structureInfo.getCenterZ()}, r); - c[0] = c[0] + structureInfo.getCenterX(); - c[1] = c[1] + structureInfo.getCenterZ(); - if(isInStructure(c[0], y, c[1])) { - StructureContainedBlock b = structure[c[0]][c[1]][y]; + Vector2 c = getRotatedCoords(new Vector2(x-structureInfo.getCenterX(), z-structureInfo.getCenterZ()), r); + c.add(new Vector2(structureInfo.getCenterX(), structureInfo.getCenterZ())); + if(isInStructure((int) c.getX(), y, (int) c.getZ())) { + StructureContainedBlock b = structure[(int) c.getX()][(int) c.getZ()][y]; exec.accept(new StructureContainedBlock(x - getStructureInfo().getCenterX(), y, z - getStructureInfo().getCenterZ(), b.getState(), b.getBlockData())); } } diff --git a/src/main/java/com/dfsek/terra/util/structure/RotationUtil.java b/src/main/java/com/dfsek/terra/util/structure/RotationUtil.java new file mode 100644 index 000000000..f77f3fa30 --- /dev/null +++ b/src/main/java/com/dfsek/terra/util/structure/RotationUtil.java @@ -0,0 +1,168 @@ +package com.dfsek.terra.util.structure; + +import com.dfsek.terra.procgen.math.Vector2; +import com.dfsek.terra.structure.GaeaStructure; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Rail; + +import java.util.Arrays; + +public class RotationUtil { + /** + * Rotate and mirror a coordinate pair. + * @param arr Array containing X and Z coordinates. + * @param r Rotation + * @return Rotated coordinate pair + */ + public static Vector2 getRotatedCoords(Vector2 orig, GaeaStructure.Rotation r) { + Vector2 copy = orig.clone(); + switch(r) { + case CW_90: + copy.setX(orig.getZ()).setZ(-orig.getX()); + break; + case CCW_90: + copy.setX(-orig.getZ()).setZ(orig.getX()); + break; + case CW_180: + copy.multiply(-1); + break; + } + return copy; + } + + /** + * Get the BlockFace with rotation and mirrors applied to it + * @param f BlockFace to apply rotation to + * @param r Rotation + * @return Rotated BlockFace + */ + public static BlockFace getRotatedFace(BlockFace f, GaeaStructure.Rotation r) { + BlockFace n = f; + int rotateNum = r.getDegrees()/90; + int rn = faceRotation(f); + if(rn >= 0) { + n = fromRotation(faceRotation(n) + 4*rotateNum); + } + return n; + } + + public static org.bukkit.Axis getRotatedAxis(org.bukkit.Axis orig, GaeaStructure.Rotation r) { + org.bukkit.Axis other = orig; + final boolean shouldSwitch = r.equals(GaeaStructure.Rotation.CW_90) || r.equals(GaeaStructure.Rotation.CCW_90); + switch(orig) { + case X: + if(shouldSwitch) other = org.bukkit.Axis.Z; + break; + case Z: + if(shouldSwitch) other = org.bukkit.Axis.X; + break; + } + return other; + } + + + /** + * Method to rotate the incredibly obnoxious Rail.Shape enum + * @param orig Original shape + * @param r Rotate + * @return Rotated/mirrored shape + */ + public static Rail.Shape getRotatedRail(Rail.Shape orig, GaeaStructure.Rotation r) { + switch(r) { + case CCW_90: + switch(orig) { + case NORTH_WEST: return Rail.Shape.SOUTH_WEST; + case NORTH_SOUTH: return Rail.Shape.EAST_WEST; + case SOUTH_WEST: return Rail.Shape.SOUTH_EAST; + case SOUTH_EAST: return Rail.Shape.NORTH_EAST; + case EAST_WEST: return Rail.Shape.NORTH_SOUTH; + case NORTH_EAST: return Rail.Shape.NORTH_WEST; + case ASCENDING_EAST: return Rail.Shape.ASCENDING_NORTH; + case ASCENDING_WEST: return Rail.Shape.ASCENDING_SOUTH; + case ASCENDING_NORTH: return Rail.Shape.ASCENDING_WEST; + case ASCENDING_SOUTH: return Rail.Shape.ASCENDING_EAST; + } + case CW_90: + switch(orig) { + case NORTH_WEST: return Rail.Shape.NORTH_EAST; + case NORTH_SOUTH: return Rail.Shape.EAST_WEST; + case SOUTH_WEST: return Rail.Shape.NORTH_WEST; + case SOUTH_EAST: return Rail.Shape.SOUTH_WEST; + case EAST_WEST: return Rail.Shape.NORTH_SOUTH; + case NORTH_EAST: return Rail.Shape.SOUTH_EAST; + case ASCENDING_EAST: return Rail.Shape.ASCENDING_SOUTH; + case ASCENDING_WEST: return Rail.Shape.ASCENDING_NORTH; + case ASCENDING_NORTH: return Rail.Shape.ASCENDING_EAST; + case ASCENDING_SOUTH: return Rail.Shape.ASCENDING_WEST; + } + case CW_180: + switch(orig) { + case NORTH_WEST: return Rail.Shape.SOUTH_EAST; + case NORTH_SOUTH: return Rail.Shape.NORTH_SOUTH; + case SOUTH_WEST: return Rail.Shape.NORTH_EAST; + case SOUTH_EAST: return Rail.Shape.NORTH_WEST; + case EAST_WEST: return Rail.Shape.EAST_WEST; + case NORTH_EAST: return Rail.Shape.SOUTH_WEST; + case ASCENDING_EAST: return Rail.Shape.ASCENDING_WEST; + case ASCENDING_WEST: return Rail.Shape.ASCENDING_EAST; + case ASCENDING_NORTH: return Rail.Shape.ASCENDING_SOUTH; + case ASCENDING_SOUTH: return Rail.Shape.ASCENDING_NORTH; + } + } + return orig; + } + + /** + * Get an integer representation of a BlockFace, to perform math on. + * @param f BlockFace to get integer for + * @return integer representation of BlockFace + */ + public static int faceRotation(BlockFace f) { + switch(f) { + case NORTH: return 0; + case NORTH_NORTH_EAST: return 1; + case NORTH_EAST: return 2; + case EAST_NORTH_EAST: return 3; + case EAST: return 4; + case EAST_SOUTH_EAST: return 5; + case SOUTH_EAST: return 6; + case SOUTH_SOUTH_EAST: return 7; + case SOUTH: return 8; + case SOUTH_SOUTH_WEST: return 9; + case SOUTH_WEST: return 10; + case WEST_SOUTH_WEST: return 11; + case WEST: return 12; + case WEST_NORTH_WEST: return 13; + case NORTH_WEST: return 14; + case NORTH_NORTH_WEST: return 15; + default: return -1; + } + } + + /** + * Convert integer to BlockFace representation + * @param r integer to get BlockFace for + * @return BlockFace represented by integer. + */ + public static BlockFace fromRotation(int r) { + switch(Math.floorMod(r, 16)) { + case 0: return BlockFace.NORTH; + case 1: return BlockFace.NORTH_NORTH_EAST; + case 2: return BlockFace.NORTH_EAST; + case 3: return BlockFace.EAST_NORTH_EAST; + case 4: return BlockFace.EAST; + case 5: return BlockFace.EAST_SOUTH_EAST; + case 6: return BlockFace.SOUTH_EAST; + case 7: return BlockFace.SOUTH_SOUTH_EAST; + case 8: return BlockFace.SOUTH; + case 9: return BlockFace.SOUTH_SOUTH_WEST; + case 10: return BlockFace.SOUTH_WEST; + case 11: return BlockFace.WEST_SOUTH_WEST; + case 12: return BlockFace.WEST; + case 13: return BlockFace.WEST_NORTH_WEST; + case 14: return BlockFace.NORTH_WEST; + case 15: return BlockFace.NORTH_NORTH_WEST; + default: throw new IllegalArgumentException(); + } + } +} diff --git a/src/main/java/com/dfsek/terra/WorldEditUtil.java b/src/main/java/com/dfsek/terra/util/structure/WorldEditUtil.java similarity index 97% rename from src/main/java/com/dfsek/terra/WorldEditUtil.java rename to src/main/java/com/dfsek/terra/util/structure/WorldEditUtil.java index bfc7ed642..af3928368 100644 --- a/src/main/java/com/dfsek/terra/WorldEditUtil.java +++ b/src/main/java/com/dfsek/terra/util/structure/WorldEditUtil.java @@ -1,4 +1,4 @@ -package com.dfsek.terra; +package com.dfsek.terra.util.structure; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -6,7 +6,6 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.regions.RegionSelector; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player;