From 73cb5ccb6c38fbc428ae2d9e3b1610d4a6d26b88 Mon Sep 17 00:00:00 2001 From: SenseiKiwi Date: Wed, 12 Mar 2014 05:08:49 -0400 Subject: [PATCH] Fixed Rifts Spreading through Walls Fixed the issue of rifts spreading through walls. We tried using raytracing but rifts would always "leak" out of unbreakable enclosures. With this latest change, rifts spread with the same logic that determines which blocks are reachable to them. --- .../mod_pocketDim/blocks/BlockRift.java | 84 +++++++++++++++---- .../mod_pocketDim/core/NewDimData.java | 1 - .../tileentities/TileEntityRift.java | 51 ++--------- 3 files changed, 73 insertions(+), 63 deletions(-) diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/blocks/BlockRift.java b/src/main/java/StevenDimDoors/mod_pocketDim/blocks/BlockRift.java index 4e307cd..cc15c9f 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/blocks/BlockRift.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/blocks/BlockRift.java @@ -7,7 +7,6 @@ import java.util.Queue; import java.util.Random; import net.minecraft.block.Block; -import net.minecraft.block.BlockContainer; import net.minecraft.block.BlockFlowing; import net.minecraft.block.BlockFluid; import net.minecraft.block.ITileEntityProvider; @@ -27,6 +26,7 @@ import StevenDimDoors.mod_pocketDim.core.DimLink; import StevenDimDoors.mod_pocketDim.core.NewDimData; import StevenDimDoors.mod_pocketDim.core.PocketManager; import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift; +import StevenDimDoors.mod_pocketDim.util.Point4D; import StevenDimDoors.mod_pocketDimClient.ClosingRiftFX; import StevenDimDoors.mod_pocketDimClient.GoggleRiftFX; import StevenDimDoors.mod_pocketDimClient.RiftFX; @@ -38,7 +38,7 @@ public class BlockRift extends Block implements ITileEntityProvider { private static final float MIN_IMMUNE_RESISTANCE = 5000.0F; private static final int BLOCK_DESTRUCTION_RANGE = 4; - private static final int BLOCK_DESTRUCTION_VOLUME = (int) Math.pow(2 * BLOCK_DESTRUCTION_RANGE + 1, 3); + private static final int RIFT_SPREAD_RANGE = 5; private static final int MAX_BLOCK_SEARCH_CHANCE = 100; private static final int BLOCK_SEARCH_CHANCE = 50; private static final int MAX_BLOCK_DESTRUCTION_CHANCE = 100; @@ -164,11 +164,30 @@ public class BlockRift extends Block implements ITileEntityProvider private void destroyNearbyBlocks(World world, int x, int y, int z, Random random) { - HashMap pointDistances = new HashMap(BLOCK_DESTRUCTION_VOLUME); - Queue points = new LinkedList(); + // Find reachable blocks that are vulnerable to rift damage (ignoring air, of course) + ArrayList targets = findReachableBlocks(world, x, y, z, BLOCK_DESTRUCTION_RANGE, false); - //Perform a breadth-first search outwards from the point at which the rift is located. Record the distances - //of the points we visit to stop the search at its maximum range. + // For each block, randomly decide whether to destroy it. + // The randomness makes it so the destroyed area appears "noisy" if the rift is exposed to a large surface. + for (Point3D target : targets) + { + if (random.nextInt(MAX_BLOCK_DESTRUCTION_CHANCE) < BLOCK_DESTRUCTION_CHANCE) + { + spawnWorldThread(world.getBlockId(target.getX(), target.getY(), target.getZ()), world, x, y, z, random); + world.destroyBlock(target.getX(), target.getY(), target.getZ(), false); + } + } + } + + private ArrayList findReachableBlocks(World world, int x, int y, int z, int range, boolean includeAir) + { + int searchVolume = (int) Math.pow(2 * range + 1, 3); + HashMap pointDistances = new HashMap(searchVolume); + Queue points = new LinkedList(); + ArrayList targets = new ArrayList(); + + // Perform a breadth-first search outwards from the point at which the rift is located. + // Record the distances of the points we visit to stop the search at its maximum range. pointDistances.put(new Point3D(x, y, z), 0); addAdjacentBlocks(x, y, z, 0, pointDistances, points); while (!points.isEmpty()) @@ -176,10 +195,14 @@ public class BlockRift extends Block implements ITileEntityProvider Point3D current = points.remove(); int distance = pointDistances.get(current); - //If the current block is air, continue searching. Otherwise, try destroying the block. + // If the current block is air, continue searching. Otherwise, add the block to our list. if (world.isAirBlock(current.getX(), current.getY(), current.getZ())) { - //Make sure we stay within the search range + if (includeAir) + { + targets.add(current); + } + // Make sure we stay within the search range if (distance < BLOCK_DESTRUCTION_RANGE) { addAdjacentBlocks(current.getX(), current.getY(), current.getZ(), distance, pointDistances, points); @@ -187,18 +210,16 @@ public class BlockRift extends Block implements ITileEntityProvider } else { - //Check if the current block is immune to destruction by rifts. If not, randomly decide whether to destroy it. - //The randomness makes it so the destroyed area appears "noisy" if the rift is exposed to a large surface. - if (!isBlockImmune(world, current.getX(), current.getY(), current.getZ()) && - random.nextInt(MAX_BLOCK_DESTRUCTION_CHANCE) < BLOCK_DESTRUCTION_CHANCE) + // Check if the current block is immune to destruction by rifts. If not, add it to our list. + if (!isBlockImmune(world, current.getX(), current.getY(), current.getZ())) { - this.spawnWorldThread(world.getBlockId(current.getX(), current.getY(), current.getZ()), world, x, y, z, random); - world.destroyBlock(current.getX(), current.getY(), current.getZ(), false); + targets.add(current); } } } + return targets; } - + private void spawnWorldThread(int blockID, World world, int x, int y, int z, Random random) { if (blockID != 0 && (random.nextInt(MAX_WORLD_THREAD_CHANCE) < WORLD_THREAD_CHANCE) @@ -236,11 +257,40 @@ public class BlockRift extends Block implements ITileEntityProvider if (!this.isBlockImmune(world, x, y, z) && world.getChunkProvider().chunkExists(x >> 4, z >> 4)) { int blockID = world.getBlockId(x, y, z); - world.setBlock(x, y, z, properties.RiftBlockID); - this.spawnWorldThread(blockID, world, x, y, z, random); + if (world.setBlock(x, y, z, properties.RiftBlockID)) + spawnWorldThread(blockID, world, x, y, z, random); } } + public boolean spreadRift(NewDimData dimension, DimLink parent, World world, Random random) + { + int x, y, z, blockID; + Point4D source = parent.source(); + + // Find reachable blocks that are vulnerable to rift damage and include air + ArrayList targets = findReachableBlocks(world, source.getX(), source.getY(), source.getZ(), + RIFT_SPREAD_RANGE, true); + + if (!targets.isEmpty()) + { + // Choose randomly from among the possible locations where we can spawn a new rift + Point3D target = targets.get( random.nextInt(targets.size()) ); + x = target.getX(); + y = target.getY(); + z = target.getZ(); + + // Create a child, replace the block with a rift, and consider dropping World Thread + blockID = world.getBlockId(x, y, z); + if (world.setBlock(x, y, z, properties.RiftBlockID)) + { + dimension.createChildLink(x, y, z, parent); + spawnWorldThread(blockID, world, x, y, z, random); + return true; + } + } + return false; + } + /** * Lets pistons push through rifts, destroying them */ diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/core/NewDimData.java b/src/main/java/StevenDimDoors/mod_pocketDim/core/NewDimData.java index 6eb201b..ba977d5 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/core/NewDimData.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/core/NewDimData.java @@ -15,7 +15,6 @@ import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPack; import StevenDimDoors.mod_pocketDim.util.Point4D; import StevenDimDoors.mod_pocketDim.watcher.IUpdateWatcher; -@SuppressWarnings("deprecation") public abstract class NewDimData { private static class InnerDimLink extends DimLink diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/tileentities/TileEntityRift.java b/src/main/java/StevenDimDoors/mod_pocketDim/tileentities/TileEntityRift.java index d597e9f..dd6f08e 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/tileentities/TileEntityRift.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/tileentities/TileEntityRift.java @@ -35,8 +35,6 @@ import StevenDimDoors.mod_pocketDim.util.Point4D; public class TileEntityRift extends TileEntity { - private static final int MAX_SPREAD_ATTEMPTS = 3; - private static final int MAX_SEARCH_ATTEMPTS = 50; private static final int MAX_ANCESTOR_LINKS = 3; private static final int ENDERMAN_SPAWNING_CHANCE = 1; private static final int MAX_ENDERMAN_SPAWNING_CHANCE = 32; @@ -100,7 +98,7 @@ public class TileEntityRift extends TileEntity //This code should execute once every 10 seconds if (updateTimer > 200) { - this.spawnEndermen(); + //this.spawnEndermen(); this.grow(mod_pocketDim.properties); updateTimer = 0; } @@ -334,53 +332,16 @@ public class TileEntityRift extends TileEntity return; } - // The probability of rifts trying to spread increases if more rifts are nearby - // Players should see rifts spread faster within clusters than at the edges of clusters + // The probability of rifts trying to spread increases if more rifts are nearby. + // Players should see rifts spread faster within clusters than at the edges of clusters. // Also, single rifts CANNOT spread. - int nearRifts = dimension.findRiftsInRange(this.worldObj, 5, xCoord, yCoord, zCoord).size(); + int nearRifts = dimension.findRiftsInRange(worldObj, 5, xCoord, yCoord, zCoord).size(); if (nearRifts == 0 || random.nextInt(nearRifts) == 0) { return; } - - int x, y, z; - int spreadAttempts = 0; - for (int searchAttempts = 0; searchAttempts < MAX_SEARCH_ATTEMPTS; searchAttempts++) - { - x = xCoord + MathHelper.getRandomIntegerInRange(random, -6, 6); - y = yCoord + MathHelper.getRandomIntegerInRange(random, -4, 4); - z = zCoord + MathHelper.getRandomIntegerInRange(random, -6, 6); - - if (y >= 0 && y < worldObj.getActualHeight() && worldObj.isAirBlock(x, y, z)) - { - Vec3 position = worldObj.getWorldVec3Pool().getVecFromPool(xCoord, yCoord, zCoord); - Vec3 spreadTarget = worldObj.getWorldVec3Pool().getVecFromPool(x, y, z); - MovingObjectPosition hit = worldObj.clip(position, spreadTarget, false); - if (hit == null || !mod_pocketDim.blockRift.isBlockImmune(worldObj, hit.blockX, hit.blockY, hit.blockZ)) - { - if(hit!=null) - { - dimension.createChildLink(hit.blockX, hit.blockY, hit.blockZ, link); - this.worldObj.setBlock(hit.blockX, hit.blockY, hit.blockZ, mod_pocketDim.blockRift.blockID); - } - else - { - dimension.createChildLink(x,y,z,link); - this.worldObj.setBlock(x,y,z, mod_pocketDim.blockRift.blockID); - } - hasGrownRifts = true; - break; - } - else - { - spreadAttempts++; - if (spreadAttempts >= MAX_SPREAD_ATTEMPTS) - { - break; - } - } - } - } + + hasGrownRifts = mod_pocketDim.blockRift.spreadRift(dimension, link, worldObj, random); } @Override