diff --git a/StevenDimDoors/mod_pocketDim/CommonTickHandler.java b/StevenDimDoors/mod_pocketDim/CommonTickHandler.java index 5270fb1..5fee0a4 100644 --- a/StevenDimDoors/mod_pocketDim/CommonTickHandler.java +++ b/StevenDimDoors/mod_pocketDim/CommonTickHandler.java @@ -4,14 +4,11 @@ import java.util.ArrayList; import java.util.EnumSet; import java.util.Random; +import net.minecraft.entity.Entity; +import net.minecraft.world.World; import StevenDimDoors.mod_pocketDim.helpers.dimHelper; import StevenDimDoors.mod_pocketDim.helpers.yCoordHelper; import StevenDimDoors.mod_pocketDim.ticking.MobObelisk; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockContainer; -import net.minecraft.entity.Entity; -import net.minecraft.world.World; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.ITickHandler; import cpw.mods.fml.common.TickType; @@ -19,16 +16,19 @@ import cpw.mods.fml.relauncher.Side; public class CommonTickHandler implements ITickHandler { - private Random rand = new Random(); - public int tickCount=0; - public int tickCount2=0; + private int tickCount = 0; private static DDProperties properties = null; - public static ArrayList chunksToPopulate= new ArrayList(); + public static ArrayList chunksToPopulate = new ArrayList(); + + private static final Random rand = new Random(); + public static final int MAX_MONOLITH_SPAWNING_CHANCE = 100; + private static final String label = "Dimensional Doors: Common Tick"; private static final int MAX_MONOLITH_SPAWN_Y = 245; private static final int CHUNK_SIZE = 16; + private static final int RIFT_REGENERATION_INTERVAL = 100; //Regenerate random rifts every 100 ticks + private static final int LIMBO_DECAY_INTERVAL = 10; //Apply spread decay every 10 ticks - public CommonTickHandler() { if (properties == null) @@ -40,7 +40,7 @@ public class CommonTickHandler implements ITickHandler { if (type.equals(EnumSet.of(TickType.SERVER))) { - onTickInGame(); + onServerTick(); } } @@ -51,9 +51,12 @@ public class CommonTickHandler implements ITickHandler { if(!CommonTickHandler.chunksToPopulate.isEmpty()) { - for(int[] chunkData : CommonTickHandler.chunksToPopulate) + //TODO: This is bad. =/ We should not be passing around arrays of magic numbers. + //We should have an object that contains this information. ~SenseiKiwi + + for (int[] chunkData : CommonTickHandler.chunksToPopulate) { - if(chunkData[0]==properties.LimboDimensionID) + if(chunkData[0] == properties.LimboDimensionID) { this.placeMonolithsInLimbo(chunkData[0], chunkData[1], chunkData[2]); } @@ -61,45 +64,47 @@ public class CommonTickHandler implements ITickHandler { this.placeMonolithsInPockets(chunkData[0], chunkData[1], chunkData[2]); } - + } } CommonTickHandler.chunksToPopulate.clear(); } } - public EnumSet ticks() + @Override + public EnumSet ticks() { return EnumSet.of(TickType.SERVER); } + @Override public String getLabel() { - return null; + return label; //Used for profiling! } private void placeMonolithsInPockets(int worldID, int chunkX, int chunkZ) { World worldObj = dimHelper.getWorld(worldID); DimData dimData = dimHelper.dimList.get(worldObj.provider.dimensionId); - int sanity = 0; - int blockID = 0; - boolean didSpawn=false; - - if (dimData == null || - dimData.dungeonGenerator == null || - dimData.dungeonGenerator.isOpen) - { - return; - } - + int sanity = 0; + int blockID = 0; + boolean didSpawn=false; + + if (dimData == null || + dimData.dungeonGenerator == null || + dimData.dungeonGenerator.isOpen) + { + return; + } + //The following initialization code is based on code from ChunkProviderGenerate. //It makes our generation depend on the world seed. Random random = new Random(worldObj.getSeed()); - long factorA = random.nextLong() / 2L * 2L + 1L; - long factorB = random.nextLong() / 2L * 2L + 1L; - random.setSeed((long)chunkX * factorA + (long)chunkZ * factorB ^ worldObj.getSeed()); - + long factorA = random.nextLong() / 2L * 2L + 1L; + long factorB = random.nextLong() / 2L * 2L + 1L; + random.setSeed(chunkX * factorA + chunkZ * factorB ^ worldObj.getSeed()); + int x, y, z; do { @@ -108,12 +113,12 @@ public class CommonTickHandler implements ITickHandler z = chunkZ * CHUNK_SIZE + random.nextInt(CHUNK_SIZE); y = MAX_MONOLITH_SPAWN_Y; blockID = worldObj.getBlockId(x, y, z); - + while (blockID == 0 &&y>0) { y--; blockID = worldObj.getBlockId(x, y, z); - + } while((blockID == mod_pocketDim.blockDimWall.blockID||blockID == mod_pocketDim.blockDimWallPerm.blockID)&&y>0) { @@ -124,26 +129,26 @@ public class CommonTickHandler implements ITickHandler { y--; blockID = worldObj.getBlockId(x, y, z); - + } if(y > 0) { - - + + int jumpSanity=0; int jumpHeight=0; do { - + jumpHeight = y+random.nextInt(10); - + jumpSanity++; } while(!worldObj.isAirBlock(x,jumpHeight+6 , z)&&jumpSanity<20); - - - + + + Entity mob = new MobObelisk(worldObj); mob.setLocationAndAngles(x, jumpHeight, z, 1, 1); @@ -152,15 +157,15 @@ public class CommonTickHandler implements ITickHandler } sanity++; - + } while (sanity<5&&!didSpawn); } - + private void placeMonolithsInLimbo(int worldID, int var2, int var3) { World world = dimHelper.getWorld(worldID); - + if (rand.nextInt(MAX_MONOLITH_SPAWNING_CHANCE) < properties.MonolithSpawningChance) { int y =0; @@ -169,176 +174,105 @@ public class CommonTickHandler implements ITickHandler int yTest; do { - + x = var2*16 + rand.nextInt(16); z = var3*16 + rand.nextInt(16); - + while(world.getBlockId(x, y, z)==0&&y<255) { y++; } y = yCoordHelper.getFirstUncovered(world,x , y+2, z); - + yTest=yCoordHelper.getFirstUncovered(world,x , y+5, z); if(yTest>245) { return; } - + int jumpSanity=0; int jumpHeight=0; do { jumpHeight = y+rand.nextInt(25); - + jumpSanity++; } while(!world.isAirBlock(x,jumpHeight+6 , z)&&jumpSanity<20); - - + + Entity mob = new MobObelisk(world); mob.setLocationAndAngles(x, jumpHeight, z, 1, 1); - - + + world.spawnEntityInWorld(mob); - + } while (yTest > y); } } - //replaces rifts in game that have been destroyed/have blocks placed over them. - private void onTickInGame() - { + private void onServerTick() + { + tickCount++; //There is no need to reset the counter. Let it overflow. Really. + + if (tickCount % RIFT_REGENERATION_INTERVAL == 0) + { + regenerateRifts(); + } + + if (tickCount % LIMBO_DECAY_INTERVAL == 0) + { + LimboDecay.ApplyRandomFastDecay(); + } + + if (mod_pocketDim.teleTimer > 0) + { + mod_pocketDim.teleTimer--; + } + } + + private void regenerateRifts() + { try { + //Regenerate rifts that have been replaced (not permanently removed) by players - if(tickCount>100) + int i = 0; + + while (i < 15 && FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) { - tickCount=0; - int i=0; + i++; + LinkData link; + //actually gets the random rift based on the size of the list + link = (LinkData) dimHelper.instance.getRandomLinkData(true); - while (i<15&&FMLCommonHandler.instance().getEffectiveSide()==Side.SERVER) + if(link!=null) { - i++; - LinkData link; - //actually gets the random rift based on the size of the list - link = (LinkData) dimHelper.instance.getRandomLinkData(true); - - - - if(link!=null) + if (dimHelper.getWorld(link.locDimID)!=null) { + World world = dimHelper.getWorld(link.locDimID); - if(dimHelper.getWorld(link.locDimID)!=null) + int blocktoReplace = world.getBlockId(link.locXCoord, link.locYCoord, link.locZCoord); + + if(!mod_pocketDim.blocksImmuneToRift.contains(blocktoReplace))//makes sure the rift doesn't replace a door or something { - World world=dimHelper.getWorld(link.locDimID); - - int blocktoReplace = world.getBlockId(link.locXCoord, link.locYCoord, link.locZCoord); - - if(!mod_pocketDim.blocksImmuneToRift.contains(blocktoReplace))//makes sure the rift doesn't replace a door or something + if(dimHelper.instance.getLinkDataFromCoords(link.locXCoord, link.locYCoord, link.locZCoord, link.locDimID) != null) { - if(dimHelper.instance.getLinkDataFromCoords(link.locXCoord, link.locYCoord, link.locZCoord, link.locDimID)==null) - { - } - else - { - dimHelper.getWorld(link.locDimID).setBlock(link.locXCoord, link.locYCoord, link.locZCoord, properties.RiftBlockID); - TileEntityRift.class.cast(dimHelper.getWorld(link.locDimID).getBlockTileEntity(link.locXCoord, link.locYCoord, link.locZCoord)).hasGrownRifts=true; - } + dimHelper.getWorld(link.locDimID).setBlock(link.locXCoord, link.locYCoord, link.locZCoord, properties.RiftBlockID); + TileEntityRift.class.cast(dimHelper.getWorld(link.locDimID).getBlockTileEntity(link.locXCoord, link.locYCoord, link.locZCoord)).hasGrownRifts=true; } } } } } - - } catch (Exception e) { - tickCount++; - System.out.println("something on tick went wrong: " + e); + System.out.println("An exception occurred in CommonTickHandler.onServerTick():"); e.printStackTrace(); } - tickCount++; - - //this section regulates decay in Limbo- it records any blocks placed by the player and later progresss them through the decay cycle - if(tickCount2>10&&dimHelper.blocksToDecay!=null) - { - tickCount2=0; - if(!dimHelper.blocksToDecay.isEmpty()&&dimHelper.getWorld(properties.LimboDimensionID)!=null) - { - - - if(dimHelper.blocksToDecay.size()>rand.nextInt(400)) - { - int index = rand.nextInt(dimHelper.blocksToDecay.size()); - Point3D point = (Point3D) dimHelper.blocksToDecay.get(index); - - int blockID = dimHelper.getWorld(properties.LimboDimensionID).getBlockId(point.getX(), point.getY(), point.getZ()); - int idToSet=Block.stone.blockID; - - if(blockID==0||blockID==properties.LimboBlockID) - { - dimHelper.blocksToDecay.remove(index); - } - else - { - if(Block.blocksList[idToSet] instanceof BlockContainer) - { - idToSet=-1; - dimHelper.blocksToDecay.remove(index); - } - - - - if(blockID==Block.cobblestone.blockID) - { - idToSet=Block.gravel.blockID; - } - if(blockID==Block.stone.blockID) - { - idToSet=Block.cobblestone.blockID; - - } - if(blockID==Block.gravel.blockID&&!dimHelper.getWorld(properties.LimboDimensionID).isAirBlock(point.getX(), point.getY()-1, point.getZ())) - { - idToSet=properties.LimboBlockID; - dimHelper.getWorld(properties.LimboDimensionID).scheduleBlockUpdate(point.getX(), point.getY(), point.getZ(),10, idToSet); - - } - else if(blockID==Block.gravel.blockID) - { - dimHelper.blocksToDecay.remove(index); - idToSet=-1; - - } - - if(idToSet!=-1) - { - - dimHelper.getWorld(properties.LimboDimensionID).setBlock(point.getX(), point.getY(), point.getZ(), idToSet); - - } - } - } - } - } - - tickCount2++; - - if(mod_pocketDim.teleTimer>0) - { - mod_pocketDim.teleTimer--; - } - - - - - - } - } diff --git a/StevenDimDoors/mod_pocketDim/EventHookContainer.java b/StevenDimDoors/mod_pocketDim/EventHookContainer.java index 1a28375..e7218b7 100644 --- a/StevenDimDoors/mod_pocketDim/EventHookContainer.java +++ b/StevenDimDoors/mod_pocketDim/EventHookContainer.java @@ -1,50 +1,17 @@ package StevenDimDoors.mod_pocketDim; -import java.io.File; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Random; - -import StevenDimDoors.mod_pocketDim.helpers.dimHelper; -import StevenDimDoors.mod_pocketDim.items.ItemRiftBlade; -import StevenDimDoors.mod_pocketDim.world.LimboGenerator; -import StevenDimDoors.mod_pocketDim.world.LimboProvider; -import StevenDimDoors.mod_pocketDim.world.PocketGenerator; -import StevenDimDoors.mod_pocketDim.world.pocketProvider; - -import cpw.mods.fml.client.FMLClientHandler; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - -import net.minecraft.block.Block; -import net.minecraft.client.Minecraft; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.monster.EntityEnderman; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.ItemBlock; -import net.minecraft.item.ItemStack; -import net.minecraft.util.AxisAlignedBB; -import net.minecraft.util.EnumMovingObjectType; -import net.minecraft.util.MathHelper; -import net.minecraft.util.MovingObjectPosition; -import net.minecraft.util.Vec3; import net.minecraft.world.World; -import net.minecraft.world.WorldServer; import net.minecraftforge.client.event.sound.SoundLoadEvent; -import net.minecraftforge.event.Event.Result; import net.minecraftforge.event.ForgeSubscribe; import net.minecraftforge.event.entity.living.LivingFallEvent; import net.minecraftforge.event.entity.player.PlayerDropsEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.event.entity.player.PlayerInteractEvent; -import net.minecraftforge.event.terraingen.PopulateChunkEvent; import net.minecraftforge.event.world.WorldEvent; +import StevenDimDoors.mod_pocketDim.helpers.dimHelper; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; public class EventHookContainer { - private static Random rand = new Random(); private static DDProperties properties = null; public EventHookContainer() @@ -57,8 +24,6 @@ public class EventHookContainer @ForgeSubscribe public void onSoundLoad(SoundLoadEvent event) { - File dataDir = Minecraft.getMinecraft().mcDataDir; - event.manager.soundPoolSounds.addSound("mods/DimDoors/sfx/monk.ogg", (mod_pocketDim.class.getResource("/mods/DimDoors/sfx/monk.ogg"))); event.manager.soundPoolSounds.addSound("mods/DimDoors/sfx/crack.ogg", (mod_pocketDim.class.getResource("/mods/DimDoors/sfx/crack.ogg"))); event.manager.soundPoolSounds.addSound("mods/DimDoors/sfx/tearing.ogg", (mod_pocketDim.class.getResource("/mods/DimDoors/sfx/tearing.ogg"))); @@ -67,40 +32,39 @@ public class EventHookContainer event.manager.soundPoolSounds.addSound("mods/DimDoors/sfx/riftEnd.ogg", (mod_pocketDim.class.getResource("/mods/DimDoors/sfx/riftEnd.ogg"))); event.manager.soundPoolSounds.addSound("mods/DimDoors/sfx/riftClose.ogg", (mod_pocketDim.class.getResource("/mods/DimDoors/sfx/riftClose.ogg"))); event.manager.soundPoolSounds.addSound("mods/DimDoors/sfx/riftDoor.ogg", (mod_pocketDim.class.getResource("/mods/DimDoors/sfx/riftDoor.ogg"))); - } @ForgeSubscribe public void onWorldLoad(WorldEvent.Load event) { - if(!mod_pocketDim.hasInitDims&&event.world.provider.dimensionId==0&&!event.world.isRemote) + if (!mod_pocketDim.hasInitDims && event.world.provider.dimensionId == 0 && !event.world.isRemote) { System.out.println("Registering Pocket Dims"); - mod_pocketDim.hasInitDims=true; + mod_pocketDim.hasInitDims = true; dimHelper.instance.unregsisterDims(); dimHelper.dimList.clear(); dimHelper.instance.interDimLinkList.clear(); dimHelper.instance.initPockets(); } - for(Integer ids : dimHelper.getIDs()) + for (Integer ids : dimHelper.getIDs()) { World world = dimHelper.getWorld(ids); - int linkCount=0; + int linkCount = 0; - if(dimHelper.dimList.containsKey(world.provider.dimensionId)) + if (dimHelper.dimList.containsKey(world.provider.dimensionId)) { //TODO added temporary Try/catch block to prevent a crash here, getLinksInDim needs to be looked at try { - for(LinkData link:dimHelper.dimList.get(world.provider.dimensionId).getLinksInDim()) + for (LinkData link:dimHelper.dimList.get(world.provider.dimensionId).getLinksInDim()) { - if(linkCount>100) + if(linkCount>100) //TODO: Wtf? wouldn't this cause some links to not load on servers with several links? Not sure what's going on here. ~SenseiKiwi { break; } linkCount++; int blocktoReplace = world.getBlockId(link.locXCoord, link.locYCoord, link.locZCoord); - if(!mod_pocketDim.blocksImmuneToRift.contains(blocktoReplace)) + if (!mod_pocketDim.blocksImmuneToRift.contains(blocktoReplace)) { dimHelper.getWorld(link.locDimID).setBlock(link.locXCoord, link.locYCoord, link.locZCoord, properties.RiftBlockID); } @@ -114,65 +78,24 @@ public class EventHookContainer } } - - - @ForgeSubscribe - public void EntityJoinWorldEvent(net.minecraftforge.event.entity.EntityJoinWorldEvent event) - { - if(event.entity instanceof EntityPlayer) - { - // System.out.println(event.entity.worldObj.provider.dimensionId); - // PacketDispatcher.sendPacketToPlayer(DimUpdatePacket.sendPacket(event.world.provider.dimensionId,1),(Player) event.entity); - } - } @ForgeSubscribe public void onPlayerFall(LivingFallEvent event) { - event.setCanceled(event.entity.worldObj.provider.dimensionId==properties.LimboDimensionID); + event.setCanceled(event.entity.worldObj.provider.dimensionId == properties.LimboDimensionID); } - - @ForgeSubscribe - public void onPlayerInteract(PlayerInteractEvent event) - { - if(event.entityPlayer.worldObj.provider.dimensionId==properties.LimboDimensionID&&event.action==PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) - { - int x = event.x; - int y = event.y; - int z = event.z; - - if(event.entityPlayer.getHeldItem()!=null) - { - if(event.entityPlayer.getHeldItem().getItem() instanceof ItemBlock) - { - if(event.entityPlayer instanceof EntityPlayerMP) - { - Point3D point = new Point3D(x,y,z); - dimHelper.blocksToDecay.add(point); - } - } - } - } - } - @ForgeSubscribe public void onPlayerDrops(PlayerDropsEvent event) { + //TODO: I have some doubts. Is this triggered even if you die outside Limbo? And do you still drop items that others could pick up? We don't cancel the event. ~SenseiKiwi mod_pocketDim.limboSpawnInventory.put(event.entityPlayer.username, event.drops); } - @ForgeSubscribe - public void onWorldunload(WorldEvent.Unload event) - { - - - } - @ForgeSubscribe public void onWorldsave(WorldEvent.Save event) { - if(mod_pocketDim.hasInitDims&&event.world.provider.dimensionId==0) + if (mod_pocketDim.hasInitDims && event.world.provider.dimensionId == 0) { dimHelper.instance.save(); } diff --git a/StevenDimDoors/mod_pocketDim/LimboDecay.java b/StevenDimDoors/mod_pocketDim/LimboDecay.java new file mode 100644 index 0000000..fc10e3e --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/LimboDecay.java @@ -0,0 +1,170 @@ +package StevenDimDoors.mod_pocketDim; + +import java.util.Random; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockContainer; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.World; +import StevenDimDoors.mod_pocketDim.helpers.dimHelper; + +/** + * Provides methods for applying Limbo decay. Limbo decay refers to the effect that most blocks placed in Limbo + * naturally change into stone, then cobble, then gravel, and finally Unraveled Fabric as time passes. + */ +public class LimboDecay { + + private static final int MAX_DECAY_SPREAD_CHANCE = 100; + private static final int DECAY_SPREAD_CHANCE = 50; + private static final int CHUNK_SIZE = 16; + private static final int SECTION_HEIGHT = 16; + + //Provides a reversed list of the block IDs that blocks cycle through during decay. + //Must be initialized later since it requires DDProperties to be initialized (for LimboBlockID). + private static int[] decaySequence = null; + + private static Random random = new Random(); + private static DDProperties properties = null; + + private LimboDecay() { } + + /** + * Initializes the array containing the reversed sequence of block IDs that blocks cycle through during decay. + */ + private static void InitializeDecaySequence() + { + if (decaySequence == null) + { + if (properties == null) + properties = DDProperties.instance(); + + decaySequence = new int[] { + properties.LimboBlockID, + Block.gravel.blockID, + Block.cobblestone.blockID, + Block.stone.blockID + }; + } + } + + /** + * Checks the blocks orthogonally around a given location (presumably the location of an Unraveled Fabric block) + * and applies Limbo decay to them. This gives the impression that decay spreads outward from Unraveled Fabric. + */ + public static void ApplySpreadDecay(World world, int x, int y, int z) + { + if (properties == null) + properties = DDProperties.instance(); + + //Check if we randomly apply decay spread or not. This can be used to moderate the frequency of + //full spread decay checks, which can also shift its performance impact on the game. + if (random.nextInt(MAX_DECAY_SPREAD_CHANCE) < DECAY_SPREAD_CHANCE) + { + //Apply decay to the blocks above, below, and on all four sides. + //World.getBlockId() implements bounds checking, so we don't have to worry about reaching out of the world + DecayBlock(world, x - 1, y, z); + DecayBlock(world, x + 1, y, z); + DecayBlock(world, x, y, z - 1); + DecayBlock(world, x, y, z + 1); + DecayBlock(world, x, y - 1, z); + DecayBlock(world, x, y + 1, z); + } + } + + /** + * Picks random blocks from each active chunk in Limbo and, if decay is applicable, converts them directly to Unraveled Fabric. + * This decay method is designed to stop players from avoiding Limbo decay by building floating structures. + */ + public static void ApplyRandomFastDecay() + { + if (properties == null) + properties = DDProperties.instance(); + + int x, y, z; + int sectionY; + int limboHeight; + World limbo = dimHelper.getWorld(properties.LimboDimensionID); + + if (limbo != null) + { + limboHeight = limbo.getHeight(); + + //Obtain the coordinates of active chunks in Limbo. For each section of each chunk, + //pick a random block and try to apply fast decay. + for (Object coordObject : limbo.activeChunkSet) + { + ChunkCoordIntPair chunkCoord = (ChunkCoordIntPair) coordObject; + + //Loop through each chunk section and fast-decay a random block + //Apply the changes using the world object instead of directly to the chunk so that clients are always notified. + for (sectionY = 0; sectionY < limboHeight; sectionY += SECTION_HEIGHT) + { + x = chunkCoord.chunkXPos * CHUNK_SIZE + random.nextInt(CHUNK_SIZE); + z = chunkCoord.chunkZPos * CHUNK_SIZE + random.nextInt(CHUNK_SIZE); + y = sectionY + random.nextInt(SECTION_HEIGHT); + DecayBlockFast(limbo, x, y, z); + } + } + } + } + + /** + * Checks if a block can be decayed and, if so, changes it directly into Unraveled Fabric. + */ + private static boolean DecayBlockFast(World world, int x, int y, int z) + { + int blockID = world.getBlockId(x, y, z); + if (CanDecayBlock(blockID)) + { + world.setBlock(x, y, z, properties.LimboBlockID); + return true; + } + return false; + } + + /** + * Checks if a block can be decayed and, if so, changes it to the next block ID along the decay sequence. + */ + private static boolean DecayBlock(World world, int x, int y, int z) + { + //Make sure the decay sequence is initialized + InitializeDecaySequence(); + + int index; + int blockID = world.getBlockId(x, y, z); + if (CanDecayBlock(blockID)) + { + //Loop over the block IDs that decay can go through. + //Find an index matching the current blockID, if any. + for (index = 0; index < decaySequence.length; index++) + { + if (decaySequence[index] == blockID) + { + break; + } + } + + //Since the decay sequence is a reversed list, the block ID in the index before our match + //is the block ID we should change this block into. A trick in this approach is that if + //we loop over the array without finding a match, then (index - 1) will contain the + //last ID in the array, which is the first one that all blocks decay into. + //We assume that Unraveled Fabric is NOT decayable. Otherwise, this will go out of bounds! + + world.setBlock(x, y, z, decaySequence[index - 1]); + return true; + } + return false; + } + + /** + * Checks if a block can decay. We will not decay air, Unraveled Fabric, Eternal Fabric, or containers. + */ + private static boolean CanDecayBlock(int blockID) + { + if (blockID == 0 || blockID == properties.LimboBlockID || blockID == properties.PermaFabricBlockID) + return false; + + Block block = Block.blocksList[blockID]; + return (block == null || !(block instanceof BlockContainer)); + } +} diff --git a/StevenDimDoors/mod_pocketDim/blocks/BlockLimbo.java b/StevenDimDoors/mod_pocketDim/blocks/BlockLimbo.java index 65c79f0..bfbd133 100644 --- a/StevenDimDoors/mod_pocketDim/blocks/BlockLimbo.java +++ b/StevenDimDoors/mod_pocketDim/blocks/BlockLimbo.java @@ -5,113 +5,58 @@ import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.client.renderer.texture.IconRegister; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.Icon; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -import StevenDimDoors.mod_pocketDim.Point3D; +import StevenDimDoors.mod_pocketDim.LimboDecay; import StevenDimDoors.mod_pocketDim.mod_pocketDim; -import StevenDimDoors.mod_pocketDim.helpers.dimHelper; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public class BlockLimbo extends Block { - Random rand= new Random(); - Icon blockIcon0; - Icon blockIcon1; - Icon blockIcon2; - Icon blockIcon3; + private final int limboDimensionID; - public BlockLimbo(int i, int j, Material par2Material) + public BlockLimbo(int i, int j, Material par2Material, int limboDimensionID) { - super(i, Material.ground); - setTickRandomly(false); - this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab); - - - + super(i, Material.ground); + this.limboDimensionID = limboDimensionID; + this.setTickRandomly(true); + this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab); } - @SideOnly(Side.CLIENT) - /** - * Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side - */ - public Icon getBlockTexture(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) - { - return this.getIcon(par5, par1IBlockAccess.getBlockMetadata(par2, par3, par4)); - } - public void registerIcons(IconRegister par1IconRegister) - { - this.blockIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName2()); - this.blockIcon0 = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName2()+0); - this.blockIcon1 = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName2()+1); - this.blockIcon2 = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName2()+2); - this.blockIcon3 = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName2()+3); + /** + * Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side + */ + @SideOnly(Side.CLIENT) + @Override + public Icon getBlockTexture(IBlockAccess blockAccess, int x, int y, int z, int side) + { + return this.getIcon(side, blockAccess.getBlockMetadata(x, y, z)); + } - } - - public Icon getIcon(int par1, int par2) - { - /** - switch(par2) - { - case 0: return this.blockIcon0; - case 1: return this.blockIcon1; - - case 2: return this.blockIcon2; - case 3: return this.blockIcon3; - } - **/ - - - return this.blockIcon; - } + @Override + public void registerIcons(IconRegister iconRegister) + { + this.blockIcon = iconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName2()); + } + + @Override + public Icon getIcon(int par1, int par2) + { + return this.blockIcon; + } - public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5) {} - - //part of the decay mech, if a block has fallen onto it, when it turns, it makes sure any block above it gets added too. + /** + * If the block is in Limbo, attempt to decay surrounding blocks upon receiving a random update tick. + */ @Override - - public int quantityDropped(Random par1Random) + public void updateTick(World world, int x, int y, int z, Random random) { - - - return 1; - - } - - public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer entityPlayer, int par6, float par7, float par8, float par9) - { - - return false; - - } - //if a block lands on it and its gravel, adds it to the decay list - public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) - { - - if(par1World.getBlockId(par2, par3+1, par4)==Block.gravel.blockID) + //Make sure this block is in Limbo + if (world.provider.dimensionId == limboDimensionID) { - Point3D point = new Point3D(par2,par3+1,par4); - dimHelper.blocksToDecay.add(point); - } - - } - public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) - { - if(par1World.getBlockId(par2, par3+1, par4)==Block.gravel.blockID) - { - Point3D point = new Point3D(par2,par3+1,par4); - dimHelper.blocksToDecay.add(point); + LimboDecay.ApplySpreadDecay(world, x, y, z); } } - @Override - public void onBlockAdded(World par1World, int par2, int par3, int par4) - { - // par1World.setBlockMetadataWithNotify(par2, par3, par4, this.rand.nextInt(4), 0); - } - - - //TODO set render color!! } diff --git a/StevenDimDoors/mod_pocketDim/helpers/DungeonHelper.java b/StevenDimDoors/mod_pocketDim/helpers/DungeonHelper.java index d74c8ca..6ba3378 100644 --- a/StevenDimDoors/mod_pocketDim/helpers/DungeonHelper.java +++ b/StevenDimDoors/mod_pocketDim/helpers/DungeonHelper.java @@ -409,7 +409,7 @@ public class DungeonHelper xEnd = centerX + MAX_EXPORT_RADIUS; zEnd = centerZ + MAX_EXPORT_RADIUS; - yEnd = Math.min(centerY + MAX_EXPORT_RADIUS, world.getActualHeight()); + yEnd = Math.min(centerY + MAX_EXPORT_RADIUS, world.getHeight()); //This could be done more efficiently, but honestly, this is the simplest approach and it //makes it easy for us to verify that the code is correct. diff --git a/StevenDimDoors/mod_pocketDim/helpers/yCoordHelper.java b/StevenDimDoors/mod_pocketDim/helpers/yCoordHelper.java index 66d0bab..7b65623 100644 --- a/StevenDimDoors/mod_pocketDim/helpers/yCoordHelper.java +++ b/StevenDimDoors/mod_pocketDim/helpers/yCoordHelper.java @@ -2,66 +2,71 @@ package StevenDimDoors.mod_pocketDim.helpers; import StevenDimDoors.mod_pocketDim.LinkData; import net.minecraft.block.Block; +import net.minecraft.block.material.Material; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; public class yCoordHelper { + private static final int MAXIMUM_UNCOVERED_Y = 245; + public static int getFirstUncovered(LinkData pointerLink) { - return yCoordHelper.getFirstUncovered(pointerLink.destDimID, pointerLink.destXCoord,pointerLink.destYCoord, pointerLink.destZCoord); + return yCoordHelper.getFirstUncovered( + pointerLink.destDimID, + pointerLink.destXCoord, + pointerLink.destYCoord, + pointerLink.destZCoord); } + public static int getFirstUncovered(int worldID, int x, int yStart, int z) { - if(dimHelper.getWorld(worldID)==null||dimHelper.getWorld(worldID).provider==null) + if (dimHelper.getWorld(worldID) == null || + dimHelper.getWorld(worldID).provider == null) { dimHelper.initDimension(worldID); } - return yCoordHelper.getFirstUncovered(dimHelper.getWorld(worldID),x,yStart,z); + return yCoordHelper.getFirstUncovered(dimHelper.getWorld(worldID), x, yStart, z); } + public static int getFirstUncovered(World world, int x, int yStart, int z) { - int yCoord=yStart; - - Chunk chunk = world.getChunkProvider().loadChunk(x >> 4, z >> 4); - - int xC=(x % 16)< 0 ? (x % 16)+16 : (x % 16); - int yC=yCoord; - int zC=(z % 16)< 0 ? (z % 16)+16 : (z % 16); - - - boolean flag=false; - - do - { - flag=false; - if(yC>0&&chunk.getBlockID(xC, yC-1, zC)!=0) - { - if(!Block.blocksList[chunk.getBlockID(xC, yC-1, zC)].blockMaterial.isReplaceable()||Block.blocksList[chunk.getBlockID(xC, yC-1, zC)].blockMaterial.isLiquid()) - { - - flag=true; - - } - } - - if(yC>0&&chunk.getBlockID(xC, yC, zC)!=0) - { - if(!Block.blocksList[chunk.getBlockID(xC, yC, zC)].blockMaterial.isReplaceable()||Block.blocksList[chunk.getBlockID(xC, yC, zC)].blockMaterial.isLiquid()) - { - - flag=true; - - } - } - - yC++; - } - while(flag&&yC<245); - - - return yC-1; + Chunk chunk = world.getChunkProvider().loadChunk(x >> 4, z >> 4); + + int localX = x < 0 ? (x % 16) + 16 : (x % 16); + int localZ = z < 0 ? (z % 16) + 16 : (z % 16); + int height = MAXIMUM_UNCOVERED_Y; //world.getHeight(); + int y; + + boolean covered = true; + for (y = yStart; y < height && covered; y++) + { + covered = IsCoveredBlock(chunk, localX, y - 1, localZ) || IsCoveredBlock(chunk, localX, y, localZ); + } + + return y; + } + + public static boolean IsCoveredBlock(Chunk chunk, int localX, int y, int localZ) + { + int blockID; + Block block; + Material material; + + if (y < 0) + return false; + + blockID = chunk.getBlockID(localX, y, localZ); + if (blockID == 0) + return false; + + block = Block.blocksList[blockID]; + if (block == null) + return false; + + material = block.blockMaterial; + return (!material.isLiquid() && !material.isReplaceable()); } } \ No newline at end of file diff --git a/StevenDimDoors/mod_pocketDim/mod_pocketDim.java b/StevenDimDoors/mod_pocketDim/mod_pocketDim.java index 89d6146..eadedad 100644 --- a/StevenDimDoors/mod_pocketDim/mod_pocketDim.java +++ b/StevenDimDoors/mod_pocketDim/mod_pocketDim.java @@ -182,7 +182,7 @@ public class mod_pocketDim blockDimWallPerm = (new BlockDimWallPerm(properties.PermaFabricBlockID, 0, Material.iron)).setLightValue(1.0F).setBlockUnbreakable().setResistance(6000000.0F).setUnlocalizedName("blockDimWallPerm"); ExitDoor = (new ExitDoor(properties.WarpDoorID, Material.wood)).setHardness(1.0F) .setUnlocalizedName("dimDoorWarp"); blockRift = (new BlockRift(properties.RiftBlockID, 0, Material.air).setHardness(1.0F) .setUnlocalizedName("rift")); - blockLimbo = (new BlockLimbo(properties.LimboBlockID, 15, Material.iron).setHardness(.2F).setUnlocalizedName("BlockLimbo").setLightValue(.0F)); + blockLimbo = (new BlockLimbo(properties.LimboBlockID, 15, Material.iron, properties.LimboDimensionID).setHardness(.2F).setUnlocalizedName("BlockLimbo").setLightValue(.0F)); chaosDoor = (new ChaosDoor(properties.UnstableDoorID, Material.iron).setHardness(.2F).setUnlocalizedName("chaosDoor").setLightValue(.0F) ); dimDoor = (new dimDoor(properties.DimensionalDoorID, Material.iron)).setHardness(1.0F).setResistance(2000.0F) .setUnlocalizedName("dimDoor"); dimHatch = (new dimHatch(properties.TransTrapdoorID, 84, Material.iron)).setHardness(1.0F) .setUnlocalizedName("dimHatch");