diff --git a/pom.xml b/pom.xml index c3ca0cc49..701c54b2b 100644 --- a/pom.xml +++ b/pom.xml @@ -95,7 +95,7 @@ org.polydev gaea - 1.10.83 + 1.10.84 org.apache.commons diff --git a/src/main/java/com/dfsek/terra/command/structure/LoadCommand.java b/src/main/java/com/dfsek/terra/command/structure/LoadCommand.java index bc1e7ed65..c1c7f89a9 100644 --- a/src/main/java/com/dfsek/terra/command/structure/LoadCommand.java +++ b/src/main/java/com/dfsek/terra/command/structure/LoadCommand.java @@ -19,8 +19,8 @@ public class LoadCommand extends PlayerCommand { try { GaeaStructure.Rotation r = GaeaStructure.Rotation.fromDegrees(Integer.parseInt(args[1])); GaeaStructure struc = GaeaStructure.load(new File(Terra.getInstance().getDataFolder() + File.separator + "export" + File.separator + "structures", args[0] + ".tstructure")); - if("true".equals(args[2])) struc.paste(sender.getLocation(), r, Collections.emptyList()); - else struc.paste(sender.getLocation(), sender.getLocation().getChunk(), r, Collections.emptyList()); + if("true".equals(args[2])) struc.paste(sender.getLocation(), r); + else struc.paste(sender.getLocation(), sender.getLocation().getChunk(), r); } catch(IOException e) { e.printStackTrace(); sender.sendMessage("Structure not found."); diff --git a/src/main/java/com/dfsek/terra/population/CavePopulator.java b/src/main/java/com/dfsek/terra/population/CavePopulator.java index 0996399da..7d439e63b 100644 --- a/src/main/java/com/dfsek/terra/population/CavePopulator.java +++ b/src/main/java/com/dfsek/terra/population/CavePopulator.java @@ -2,6 +2,7 @@ package com.dfsek.terra.population; import com.dfsek.terra.TerraProfiler; import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.carving.SimplexCarver; import com.dfsek.terra.config.base.ConfigPack; import com.dfsek.terra.config.base.ConfigUtil; import com.dfsek.terra.config.genconfig.CarverConfig; @@ -81,7 +82,15 @@ public class CavePopulator extends BlockPopulator { } /*for(Map.Entry e : new SimplexCarver(chunk.getX(), chunk.getZ()).carve(chunk.getX(), chunk.getZ(), world).getCarvedBlocks().entrySet()) { Vector v = e.getKey(); - chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ()).setBlockData(AIR, false); + switch(e.getValue()) { + case TOP: + case CENTER: + chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ()).setBlockData(AIR, false); + break; + case BOTTOM: + chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ()).setBlockData(Material.MYCELIUM.createBlockData(), false); + } + }*/ } diff --git a/src/main/java/com/dfsek/terra/population/StructurePopulator.java b/src/main/java/com/dfsek/terra/population/StructurePopulator.java index 8c4dd0971..2d7e71097 100644 --- a/src/main/java/com/dfsek/terra/population/StructurePopulator.java +++ b/src/main/java/com/dfsek/terra/population/StructurePopulator.java @@ -44,7 +44,7 @@ public class StructurePopulator extends BlockPopulator { double horizontal = struc.getStructureInfo().getMaxHorizontal(); if(Math.abs((cx + 8) - spawn.getBlockX()) <= horizontal && Math.abs((cz + 8) - spawn.getBlockZ()) <= horizontal) { try(ProfileFuture ignore = TerraProfiler.fromWorld(world).measure("StructurePasteTime")) { - struc.paste(spawn, chunk, GaeaStructure.Rotation.fromDegrees(r2.nextInt(4) * 90), Collections.emptyList()); + struc.paste(spawn, chunk, GaeaStructure.Rotation.fromDegrees(r2.nextInt(4) * 90)); break; } } diff --git a/src/main/java/com/dfsek/terra/population/TreePopulator.java b/src/main/java/com/dfsek/terra/population/TreePopulator.java index 0e4553ed5..8512d5ad8 100644 --- a/src/main/java/com/dfsek/terra/population/TreePopulator.java +++ b/src/main/java/com/dfsek/terra/population/TreePopulator.java @@ -30,7 +30,7 @@ public class TreePopulator extends GaeaBlockPopulator { try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("TreeGenTime")) { TerraWorld tw = TerraWorld.getWorld(world); TerraBiomeGrid grid = tw.getGrid();; - int x = random.nextInt(16); // Decrease chances of chunk-crossing trees + int x = random.nextInt(16); int z = random.nextInt(16); int origX = chunk.getX() << 4; int origZ = chunk.getZ() << 4; @@ -40,16 +40,11 @@ public class TreePopulator extends GaeaBlockPopulator { int att = 0; for(int i = 0; i < b.getDecorator().getTreeDensity() && att < max; ) { att++; - int y = 255; - while(y > 1) { - if(chunk.getBlock(x, y, z).getType().isAir() && chunk.getBlock(x, y-1, z).getType().isSolid()) break; - y--; - } - Tree tree = b.getDecorator().getTrees().get(random); - Range range = tw.getConfig().getBiome((UserDefinedBiome) b).getTreeRange(tree); - if(!tw.getConfig().getBiome((UserDefinedBiome) b).getTreeRange(tree).isInRange(y)) continue; - b = grid.getBiome(x+origX, z+origZ, GenerationPhase.POPULATE); - for(Block block : getValidSpawnsAt(chunk, x, z, range)) { + for(Block block : getValidSpawnsAt(chunk, x, z, new Range(0, 254))) { + Tree tree = b.getDecorator().getTrees().get(random); + Range range = tw.getConfig().getBiome((UserDefinedBiome) b).getTreeRange(tree); + if(!range.isInRange(block.getY())) continue; + b = grid.getBiome(x+origX, z+origZ, GenerationPhase.POPULATE); try { if(tree.plant(block.getLocation(), random, false, Terra.getInstance())) i++; } catch(NullPointerException ignore) {} diff --git a/src/main/java/com/dfsek/terra/structure/GaeaStructure.java b/src/main/java/com/dfsek/terra/structure/GaeaStructure.java index 059964a27..7a510c203 100644 --- a/src/main/java/com/dfsek/terra/structure/GaeaStructure.java +++ b/src/main/java/com/dfsek/terra/structure/GaeaStructure.java @@ -1,9 +1,6 @@ package com.dfsek.terra.structure; import com.dfsek.terra.Debug; -import org.bukkit.block.data.MultipleFacing; -import org.bukkit.util.Vector; -import org.polydev.gaea.math.Range; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -14,10 +11,13 @@ import org.bukkit.block.BlockState; import org.bukkit.block.Sign; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Directional; +import org.bukkit.block.data.MultipleFacing; +import org.bukkit.block.data.Orientable; +import org.bukkit.block.data.Rail; import org.bukkit.block.data.Rotatable; -import org.bukkit.block.data.type.Chest; -import org.bukkit.block.data.type.Stairs; +import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; +import org.polydev.gaea.math.Range; import java.io.File; import java.io.FileInputStream; @@ -120,20 +120,18 @@ public class GaeaStructure implements Serializable { * Paste the structure at a Location, ignoring chunk boundaries. * @param origin Origin location * @param r Rotation - * @param m Mirror */ - public void paste(@NotNull Location origin, Rotation r, List m) { - this.executeForBlocksInRange(getRange(Axis.X), getRange(Axis.Y), getRange(Axis.Z), block -> pasteBlock(block, origin, r, m), r, m); + public void paste(@NotNull Location origin, Rotation r) { + 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 - * @param m Mirror * @return Rotated coordinate pair */ - private int[] getRotatedCoords(int[] arr, Rotation r, List m) { + private int[] getRotatedCoords(int[] arr, Rotation r) { int[] cp = Arrays.copyOf(arr, 2); switch(r) { case CW_90: @@ -149,8 +147,6 @@ public class GaeaStructure implements Serializable { arr[1] = - cp[1]; break; } - if(m.contains(Mirror.X)) arr[0] = - arr[0]; - if(m.contains(Mirror.Z)) arr[1] = - arr[1]; return arr; } @@ -158,21 +154,84 @@ public class GaeaStructure implements Serializable { * Get the BlockFace with rotation and mirrors applied to it * @param f BlockFace to apply rotation to * @param r Rotation - * @param m Mirror * @return Rotated BlockFace */ - private BlockFace getRotatedFace(BlockFace f, Rotation r, List m) { + 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); } - if(f.getModX()!=0 && m.contains(Mirror.X)) n = n.getOppositeFace(); - if(f.getModZ()!=0 && m.contains(Mirror.Z)) n = n.getOppositeFace(); 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 @@ -233,9 +292,8 @@ public class GaeaStructure implements Serializable { * @param origin Origin location * @param chunk Chunk to confine pasting to * @param r Rotation - * @param m Mirror */ - public void paste(Location origin, Chunk chunk, Rotation r, List m) { + public void paste(Location origin, Chunk chunk, Rotation r) { int xOr = (chunk.getX() << 4); int zOr = (chunk.getZ() << 4); Range intersectX; @@ -243,7 +301,7 @@ public class GaeaStructure implements Serializable { intersectX = new Range(xOr, xOr+16).sub(origin.getBlockX() - structureInfo.getCenterX()); intersectZ = new Range(zOr, zOr+16).sub(origin.getBlockZ() - structureInfo.getCenterZ()); if(intersectX == null || intersectZ == null) return; - executeForBlocksInRange(intersectX, getRange(Axis.Y), intersectZ, block -> pasteBlock(block, origin, r, m), r, m); + executeForBlocksInRange(intersectX, getRange(Axis.Y), intersectZ, block -> pasteBlock(block, origin, r), r); Debug.info(intersectX.toString() + " : " + intersectZ.toString()); } @@ -252,25 +310,30 @@ public class GaeaStructure implements Serializable { * @param block The block to paste * @param origin The origin location * @param r The rotation of the structure - * @param m The mirror type of the structure */ - private void pasteBlock(StructureContainedBlock block, Location origin, Rotation r, List m) { + private void pasteBlock(StructureContainedBlock block, Location origin, Rotation r) { BlockData data = block.getBlockData().clone(); Block worldBlock = origin.clone().add(block.getX(), block.getY(), block.getZ()).getBlock(); if(!data.getMaterial().equals(Material.STRUCTURE_VOID)) { if(data instanceof Rotatable) { - BlockFace rt = getRotatedFace(((Rotatable) data).getRotation(), r, m); + BlockFace rt = getRotatedFace(((Rotatable) data).getRotation(), r); ((Rotatable) data).setRotation(rt); } else if(data instanceof Directional) { - BlockFace rt = getRotatedFace(((Directional) data).getFacing(), r, m); + BlockFace rt = getRotatedFace(((Directional) data).getFacing(), r); ((Directional) data).setFacing(rt); } else if(data instanceof MultipleFacing) { MultipleFacing mfData = (MultipleFacing) data; List faces = new ArrayList<>(mfData.getFaces()); for(BlockFace face : faces) { mfData.setFace(face, false); - mfData.setFace(getRotatedFace(face, r, m), true); + mfData.setFace(getRotatedFace(face, r), true); } + } else if(data instanceof Rail) { + Rail.Shape newShape = getRotatedRail(((Rail) data).getShape(), r); + ((Rail) data).setShape(newShape); + } else if(data instanceof Orientable) { + org.bukkit.Axis newAxis = getRotatedAxis(((Orientable) data).getAxis(), r); + ((Orientable) data).setAxis(newAxis); } worldBlock.setBlockData(data, false); if(block.getState() != null) { @@ -286,13 +349,12 @@ public class GaeaStructure implements Serializable { * @param zM Z Range * @param exec Consumer to execute for each block. * @param r Rotation - * @param m Mirror */ - private void executeForBlocksInRange(Range xM, Range yM, Range zM, Consumer exec, Rotation r, List m) { + private void executeForBlocksInRange(Range xM, Range yM, Range zM, Consumer exec, Rotation r) { for(int x : xM) { for(int y : yM) { for(int z : zM) { - int[] c = getRotatedCoords(new int[] {x-structureInfo.getCenterX(), z-structureInfo.getCenterZ()}, r, m); + 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])) { @@ -407,7 +469,4 @@ public class GaeaStructure implements Serializable { } } } - public enum Mirror { - NONE, X, Z - } }