package net.tropicraft.world.worldgen; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.init.Blocks; import net.minecraft.util.MathHelper; import net.minecraft.world.World; import net.minecraft.world.gen.feature.WorldGenerator; public abstract class TCGenBase extends WorldGenerator { World worldObj; Random rand; /**Used in placeBlockLine*/ static final byte otherCoordPairs[] = { 2, 0, 0, 1, 2, 1 }; /**Blocks normally checked in the check methods*/ List<Block> standardAllowedBlocks = Arrays.asList(Blocks.air, Blocks.leaves, Blocks.tallgrass, Blocks.snow_layer); /** Default flag for the blockGenNotifyFlag below */ public static final int BLOCK_GEN_NOTIFY_FLAG_DEFAULT = 2; /** Added by Corosus to reduce/remove the many second client side stallout, was either because of lighting updates or just general client side chunk update spam * Setting to 0 solves the issue and doesn't seem to cause much issue server side block notify wise as far as I can tell, refine more if it does */ public static int blockGenNotifyFlag = BLOCK_GEN_NOTIFY_FLAG_DEFAULT; public TCGenBase(World world, Random random) { worldObj = world; rand = random; } /** Checks if the ID is that of a leaf block*/ public boolean isLeafBlock(Block block) { return block == Blocks.leaves; // TODO: Add tropileaves } public abstract boolean generate(int i, int j, int k); /** Allows this class to work as a WorldGenerator object */ @Override public boolean generate(World world, Random rand, int i, int j, int k) { worldObj = world; this.rand = rand; return generate(i, j, k); } /** * Generates a circle * @param x The x coordinate of the center of the circle * @param y The y coordinate of the center of the circle * @param z The z coordinate of the center of the circle * @param outerRadius The radius of the circle's outside edge * @param innerRadius The radius of the circle's inner edge, 0 for a full circle * @param id The ID to generate with * @param meta The metadata to generate with * @param solid Whether it should place the block if another block is already occupying that space */ public boolean genCircle(int x, int y, int z, double outerRadius, double innerRadius, Block block, int meta, boolean solid) { boolean hasGenned = false; for(int i = (int)(-outerRadius - 1) + x; i <= (int)(outerRadius + 1) + x; i++) { for(int k = (int)(-outerRadius - 1) + z; k <= (int)(outerRadius + 1) + z; k++) { double d = (i - x) * (i - x) + (k - z) * (k - z); if(d <= outerRadius * outerRadius && d >= innerRadius * innerRadius) { if(worldObj.isAirBlock(i, y, k) || solid) { if(worldObj.setBlock(i, y, k, block, meta, blockGenNotifyFlag)) { hasGenned = true; } } } } } return hasGenned; } /** * Checks whether any blocks not specified in allowedBlockList exist in that circle * @param x The x coordinate of the center of the circle * @param y The y coordinate of the center of the circle * @param z The z coordinate of the center of the circle * @param outerRadius The radius of the circle's outside edge * @param innerRadius The radius of the circle's inner edge, 0 for a full circle * @param allowedBlockList The blocks to exclude from the check * @return Whether any blocks not specified in allowedBlockList exist in that circle */ public boolean checkCircle(int i, int j, int k, double outerRadius, double innerRadius, List allowedBlockList) { for(int x = (int)(-outerRadius - 2) + i; x < (int)(outerRadius + 2) + i; x++) { for(int z = (int)(-outerRadius - 2) + k; z < (int)(outerRadius + 2) + k; z++) { double d = (i - x) * (i - x) + (k - z) * (k - z); if(d <= outerRadius * outerRadius && d >= innerRadius * innerRadius) { if(!allowedBlockList.contains(worldObj.getBlock(x, j, z))) { System.out.println("t2"); return false; } } } } return true; } /** * Checks whether any blocks not specified in allowedBlockList exist in that line * @param ai One end of the line * @param ai1 The other end of the line * @param allowedBlockList The block to exclude from the check * @return Whether any blocks not specified in allowedBlockList exist in that circle */ public boolean checkBlockLine(int ai[], int ai1[], List allowedBlockList) { int ai2[] = { 0, 0, 0 }; byte byte0 = 0; int j = 0; for(; byte0 < 3; byte0++) { ai2[byte0] = ai1[byte0] - ai[byte0]; if(Math.abs(ai2[byte0]) > Math.abs(ai2[j])) { j = byte0; } } if(ai2[j] == 0) { return false; } byte byte1 = otherCoordPairs[j]; byte byte2 = otherCoordPairs[j + 3]; byte byte3; if(ai2[j] > 0) { byte3 = 1; } else { byte3 = -1; } double d = (double)ai2[byte1] / (double)ai2[j]; double d1 = (double)ai2[byte2] / (double)ai2[j]; int ai3[] = { 0, 0, 0 }; int k = 0; for(int l = ai2[j] + byte3; k != l; k += byte3) { ai3[j] = MathHelper.floor_double((double)(ai[j] + k) + 0.5D); ai3[byte1] = MathHelper.floor_double((double)ai[byte1] + (double)k * d + 0.5D); ai3[byte2] = MathHelper.floor_double((double)ai[byte2] + (double)k * d1 + 0.5D); if(!allowedBlockList.contains(worldObj.getBlock(ai3[0], ai3[1], ai3[2]))) { return false; } } return true; } /** * Places a line from coords ai to coords ai1 * @param ai One end of the line * @param ai1 The other end of the line * @param block The block to place * @param meta The block metadata to place * @return The coords that blocks were placed on */ public ArrayList<int[]> placeBlockLine(int ai[], int ai1[], Block block, int meta) { ArrayList<int[]> places = new ArrayList<int[]>(); int ai2[] = { 0, 0, 0 }; byte byte0 = 0; int j = 0; for(; byte0 < 3; byte0++) { ai2[byte0] = ai1[byte0] - ai[byte0]; if(Math.abs(ai2[byte0]) > Math.abs(ai2[j])) { j = byte0; } } if(ai2[j] == 0) { return null; } byte byte1 = otherCoordPairs[j]; byte byte2 = otherCoordPairs[j + 3]; byte byte3; if(ai2[j] > 0) { byte3 = 1; } else { byte3 = -1; } double d = (double)ai2[byte1] / (double)ai2[j]; double d1 = (double)ai2[byte2] / (double)ai2[j]; int ai3[] = { 0, 0, 0 }; int k = 0; for(int l = ai2[j] + byte3; k != l; k += byte3) { ai3[j] = MathHelper.floor_double((double)(ai[j] + k) + 0.5D); ai3[byte1] = MathHelper.floor_double((double)ai[byte1] + (double)k * d + 0.5D); ai3[byte2] = MathHelper.floor_double((double)ai[byte2] + (double)k * d1 + 0.5D); worldObj.setBlock(ai3[0], ai3[1], ai3[2], block, meta, blockGenNotifyFlag); places.add(new int[] { ai3[0], ai3[1], ai3[2] }); } return places; } /** * Checks whether any blocks not specified in allowedBlockList exist in that line of circles * @param ai One end of the line * @param ai1 The other end of the line * @param outerRadius The radius of the circle's outside edge * @param innerRadius The radius of the circle's inner edge, 0 for a full circle * @param allowedBlockList The block to exclude from the check * @return */ public boolean checkBlockCircleLine(int ai[], int ai1[], double outerRadius, double innerRadius, List allowedBlockList) { ArrayList<int[]> places = new ArrayList<int[]>(); int ai2[] = { 0, 0, 0 }; byte byte0 = 0; int j = 0; for(; byte0 < 3; byte0++) { ai2[byte0] = ai1[byte0] - ai[byte0]; if(Math.abs(ai2[byte0]) > Math.abs(ai2[j])) { j = byte0; } } if(ai2[j] == 0) { return false; } byte byte1 = otherCoordPairs[j]; byte byte2 = otherCoordPairs[j + 3]; byte byte3; if(ai2[j] > 0) { byte3 = 1; } else { byte3 = -1; } double d = (double)ai2[byte1] / (double)ai2[j]; double d1 = (double)ai2[byte2] / (double)ai2[j]; int ai3[] = { 0, 0, 0 }; int k = 0; for(int l = ai2[j] + byte3; k != l; k += byte3) { ai3[j] = MathHelper.floor_double((double)(ai[j] + k) + 0.5D); ai3[byte1] = MathHelper.floor_double((double)ai[byte1] + (double)k * d + 0.5D); ai3[byte2] = MathHelper.floor_double((double)ai[byte2] + (double)k * d1 + 0.5D); if(!checkCircle(ai3[0], ai3[1], ai3[2], outerRadius, innerRadius, allowedBlockList)) { return false; } } return true; } /** * Checks whether any blocks not specified in allowedBlockList exist in that line of circles and if not places the block circle line * @param ai One end of the line * @param ai1 The other end of the line * @param outerRadius The radius of the circle's outside edge * @param innerRadius The radius of the circle's inner edge, 0 for a full circle * @param block The block to generate the block circle line with * @param meta The metadata to generate the block circle line with * @param allowedBlockList The block to exclude from the check * @return The coordinates where a circle was generated */ public ArrayList<int[]> checkAndPlaceBlockCircleLine(int ai[], int ai1[], double outerRadius, double innerRadius, Block block, int meta, List allowedBlockList) { ArrayList<int[]> places = new ArrayList<int[]>(); int ai2[] = { 0, 0, 0 }; byte byte0 = 0; int j = 0; for(; byte0 < 3; byte0++) { ai2[byte0] = ai1[byte0] - ai[byte0]; if(Math.abs(ai2[byte0]) > Math.abs(ai2[j])) { j = byte0; } } if(ai2[j] == 0) { return null; } byte byte1 = otherCoordPairs[j]; byte byte2 = otherCoordPairs[j + 3]; byte byte3; if(ai2[j] > 0) { byte3 = 1; } else { byte3 = -1; } double d = (double)ai2[byte1] / (double)ai2[j]; double d1 = (double)ai2[byte2] / (double)ai2[j]; int ai3[] = { 0, 0, 0 }; int k = 0; for(int l = ai2[j] + byte3; k != l; k += byte3) { ai3[j] = MathHelper.floor_double((double)(ai[j] + k) + 0.5D); ai3[byte1] = MathHelper.floor_double((double)ai[byte1] + (double)k * d + 0.5D); ai3[byte2] = MathHelper.floor_double((double)ai[byte2] + (double)k * d1 + 0.5D); if(!checkCircle(ai3[0], ai3[1], ai3[2], outerRadius, innerRadius, allowedBlockList)) { return null; } } k = 0; for(int l = ai2[j] + byte3; k != l; k += byte3) { System.out.println("watwat"); ai3[j] = MathHelper.floor_double((double)(ai[j] + k) + 0.5D); ai3[byte1] = MathHelper.floor_double((double)ai[byte1] + (double)k * d + 0.5D); ai3[byte2] = MathHelper.floor_double((double)ai[byte2] + (double)k * d1 + 0.5D); genCircle(ai3[0], ai3[1], ai3[2], outerRadius, innerRadius, block, meta, true); places.add(new int[] { ai3[0], ai3[1], ai3[2] }); } return places; } /** * Checks if any blocks not specified in allowedBlockList exist within the line and if not places the line * @param ai One end of the line * @param ai1 The other end of the line * @param block The block to generate the block circle line with * @param meta The metadata to generate the block circle line with * @param allowedBlockList The block to exclude from the check * @return The coordinates where a block was placed */ public ArrayList<int[]> checkAndPlaceBlockLine(int ai[], int ai1[], Block block, int meta, List allowedBlockList) { ArrayList<int[]> places = new ArrayList<int[]>(); int ai2[] = { 0, 0, 0 }; byte byte0 = 0; int j = 0; for(; byte0 < 3; byte0++) { ai2[byte0] = ai1[byte0] - ai[byte0]; if(Math.abs(ai2[byte0]) > Math.abs(ai2[j])) { j = byte0; } } if(ai2[j] == 0) { return null; } byte byte1 = otherCoordPairs[j]; byte byte2 = otherCoordPairs[j + 3]; byte byte3; if(ai2[j] > 0) { byte3 = 1; } else { byte3 = -1; } double d = (double)ai2[byte1] / (double)ai2[j]; double d1 = (double)ai2[byte2] / (double)ai2[j]; int ai3[] = { 0, 0, 0 }; int k = 0; for(int l = ai2[j] + byte3; k != l; k += byte3) { ai3[j] = MathHelper.floor_double((double)(ai[j] + k) + 0.5D); ai3[byte1] = MathHelper.floor_double((double)ai[byte1] + (double)k * d + 0.5D); ai3[byte2] = MathHelper.floor_double((double)ai[byte2] + (double)k * d1 + 0.5D); if(!allowedBlockList.contains(worldObj.getBlock(ai3[0], ai3[1], ai3[2]))) { return null; } } for(int l = ai2[j] + byte3; k != l; k += byte3) { ai3[j] = MathHelper.floor_double((double)(ai[j] + k) + 0.5D); ai3[byte1] = MathHelper.floor_double((double)ai[byte1] + (double)k * d + 0.5D); ai3[byte2] = MathHelper.floor_double((double)ai[byte2] + (double)k * d1 + 0.5D); worldObj.setBlock(ai3[0], ai3[1], ai3[2], block, meta, blockGenNotifyFlag); places.add(new int[] { ai3[0], ai3[1], ai3[2] }); } return places; } /** * Places a block circle line * @param ai One end of the line * @param ai1 The other end of the line * @param outerRadius The radius of the circle's outside edge * @param innerRadius The radius of the circle's inner edge, 0 for a full circle * @param block The block to generate the block circle line with * @param meta The metadata to generate the block circle line with * @param allowedBlockList The block to exclude from the check * @return The coordinates where a circle was generated */ public ArrayList<int[]> placeBlockCircleLine(int ai[], int ai1[], double distance, double distance2, Block block, int meta) { ArrayList<int[]> places = new ArrayList<int[]>(); int ai2[] = { 0, 0, 0 }; byte byte0 = 0; int j = 0; for(; byte0 < 3; byte0++) { ai2[byte0] = ai1[byte0] - ai[byte0]; if(Math.abs(ai2[byte0]) > Math.abs(ai2[j])) { j = byte0; } } if(ai2[j] == 0) { return null; } byte byte1 = otherCoordPairs[j]; byte byte2 = otherCoordPairs[j + 3]; byte byte3; if(ai2[j] > 0) { byte3 = 1; } else { byte3 = -1; } double d = (double)ai2[byte1] / (double)ai2[j]; double d1 = (double)ai2[byte2] / (double)ai2[j]; int ai3[] = { 0, 0, 0 }; int k = 0; for(int l = ai2[j] + byte3; k != l; k += byte3) { ai3[j] = MathHelper.floor_double((double)(ai[j] + k) + 0.5D); ai3[byte1] = MathHelper.floor_double((double)ai[byte1] + (double)k * d + 0.5D); ai3[byte2] = MathHelper.floor_double((double)ai[byte2] + (double)k * d1 + 0.5D); genCircle(ai3[0], ai3[1], ai3[2], distance, distance2, block, meta, true); places.add(new int[] { ai3[0], ai3[1], ai3[2] }); } return places; } /** * Generates a sphere at the specified coordinates * @param x The x coordinate * @param y The y coordinate * @param z The z coordinate * @param outerRadius The radius of the sphere's outside edge * @param block The block to generate the sphere with * @param meta The block metadata to generate the sphere with */ public void genSphere(int x, int y, int z, int outerRadius, Block block, int meta) { for(int i = x - outerRadius; i < x + outerRadius; i++) { for(int j = y - outerRadius; j < y + outerRadius; j++) { for(int k = z - outerRadius; k < z + outerRadius; k++) { if(worldObj.isAirBlock(i, j, k)) { int distance1 = (i - x) * (i - x) + (j - y) * (j - y) + (k - z) * (k - z); if(distance1 <= outerRadius) { worldObj.setBlock(i, j, k, block, meta, blockGenNotifyFlag); } } } } } } /** * Gets the terrain height at the specified coordinates * @param x The x coordinate * @param z The z coordinate * @return The terrain height at the specified coordinates */ public int getTerrainHeightAt(int x, int z) { for(int y = worldObj.getHeightValue(x, z) + 1; y > 0; y--) { Block block = worldObj.getBlock(x, y, z); if(block == Blocks.dirt || block == Blocks.grass || block == Blocks.sand || block == Blocks.stone) { return y + 1; } } return 0; } /** * Gets a random angle in radians * @return A random angle in radians */ public double randAngle() { return rand.nextDouble() * 3.1415926535897931D * 2D; } }