diff --git a/StevenDimDoors/mod_pocketDim/DDProperties.java b/StevenDimDoors/mod_pocketDim/DDProperties.java index ac9df12..51b0fb2 100644 --- a/StevenDimDoors/mod_pocketDim/DDProperties.java +++ b/StevenDimDoors/mod_pocketDim/DDProperties.java @@ -2,9 +2,8 @@ package StevenDimDoors.mod_pocketDim; import java.io.File; -import StevenDimDoors.mod_pocketDim.ticking.CommonTickHandler; - import net.minecraftforge.common.Configuration; +import StevenDimDoors.mod_pocketDim.ticking.MonolithSpawner; public class DDProperties { @@ -208,7 +207,7 @@ public class DDProperties "Sets whether dungeon rifts generate in dimensions other than Limbo").getBoolean(true); MonolithSpawningChance = config.get(Configuration.CATEGORY_GENERAL, "Monolith Spawning Chance", 28, - "Sets the chance (out of " + CommonTickHandler.MAX_MONOLITH_SPAWNING_CHANCE + ") that Monoliths will " + + "Sets the chance (out of " + MonolithSpawner.MAX_MONOLITH_SPAWNING_CHANCE + ") that Monoliths will " + "spawn in a given Limbo chunk. The default chance is 28.").getInt(); ClusterGenerationChance = config.get(Configuration.CATEGORY_GENERAL, "Cluster Generation Chance", 3, diff --git a/StevenDimDoors/mod_pocketDim/LimboDecay.java b/StevenDimDoors/mod_pocketDim/LimboDecay.java index 80322a2..8038541 100644 --- a/StevenDimDoors/mod_pocketDim/LimboDecay.java +++ b/StevenDimDoors/mod_pocketDim/LimboDecay.java @@ -7,55 +7,56 @@ import net.minecraft.block.BlockContainer; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.World; import StevenDimDoors.mod_pocketDim.helpers.dimHelper; +import StevenDimDoors.mod_pocketDim.ticking.IRegularTickReceiver; +import StevenDimDoors.mod_pocketDim.ticking.IRegularTickSender; /** * 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 { +public class LimboDecay implements IRegularTickReceiver { 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; + private static final int LIMBO_DECAY_INTERVAL = 10; //Apply spread decay every 10 ticks //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 final int[] decaySequence; - private static Random random = new Random(); - private static DDProperties properties = null; + private Random random; + private DDProperties properties = null; - private LimboDecay() { } + public LimboDecay(IRegularTickSender tickSender, DDProperties properties) + { + decaySequence = new int[] { + properties.LimboBlockID, + Block.gravel.blockID, + Block.cobblestone.blockID, + Block.stone.blockID + }; + + this.properties = properties; + this.random = new Random(); + tickSender.registerForTicking(this, LIMBO_DECAY_INTERVAL, false); + } /** - * Initializes the array containing the reversed sequence of block IDs that blocks cycle through during decay. + * Applies fast Limbo decay periodically. */ - private static void initializeDecaySequence() + @Override + public void notifyTick() { - if (decaySequence == null) - { - if (properties == null) - properties = DDProperties.instance(); - - decaySequence = new int[] { - properties.LimboBlockID, - Block.gravel.blockID, - Block.cobblestone.blockID, - Block.stone.blockID - }; - } + applyRandomFastDecay(); } - + /** * 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(); - + public void applySpreadDecay(World world, int x, int y, int z) + { //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) @@ -75,11 +76,8 @@ public class LimboDecay { * 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() + private void applyRandomFastDecay() { - if (properties == null) - properties = DDProperties.instance(); - int x, y, z; int sectionY; int limboHeight; @@ -111,7 +109,7 @@ public class LimboDecay { /** * 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) + private boolean decayBlockFast(World world, int x, int y, int z) { int blockID = world.getBlockId(x, y, z); if (canDecayBlock(blockID)) @@ -125,11 +123,8 @@ public class LimboDecay { /** * 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) + private 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)) @@ -159,7 +154,7 @@ public class LimboDecay { /** * Checks if a block can decay. We will not decay air, Unraveled Fabric, Eternal Fabric, or containers. */ - private static boolean canDecayBlock(int blockID) + private boolean canDecayBlock(int blockID) { if (blockID == 0 || blockID == properties.LimboBlockID || blockID == properties.PermaFabricBlockID) return false; diff --git a/StevenDimDoors/mod_pocketDim/blocks/BlockLimbo.java b/StevenDimDoors/mod_pocketDim/blocks/BlockLimbo.java index 1c30ae9..8d43ab6 100644 --- a/StevenDimDoors/mod_pocketDim/blocks/BlockLimbo.java +++ b/StevenDimDoors/mod_pocketDim/blocks/BlockLimbo.java @@ -16,11 +16,13 @@ import cpw.mods.fml.relauncher.SideOnly; public class BlockLimbo extends Block { private final int limboDimensionID; + private final LimboDecay decay; - public BlockLimbo(int i, int j, Material par2Material, int limboDimensionID) + public BlockLimbo(int i, int j, Material par2Material, int limboDimensionID, LimboDecay decay) { super(i, Material.ground); this.limboDimensionID = limboDimensionID; + this.decay = decay; this.setTickRandomly(true); this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab); } @@ -56,7 +58,7 @@ public class BlockLimbo extends Block //Make sure this block is in Limbo if (world.provider.dimensionId == limboDimensionID) { - LimboDecay.applySpreadDecay(world, x, y, z); + decay.applySpreadDecay(world, x, y, z); } } } diff --git a/StevenDimDoors/mod_pocketDim/mod_pocketDim.java b/StevenDimDoors/mod_pocketDim/mod_pocketDim.java index e16dd13..e86dde4 100644 --- a/StevenDimDoors/mod_pocketDim/mod_pocketDim.java +++ b/StevenDimDoors/mod_pocketDim/mod_pocketDim.java @@ -24,6 +24,7 @@ import StevenDimDoors.mod_pocketDim.blocks.ExitDoor; import StevenDimDoors.mod_pocketDim.blocks.dimDoor; import StevenDimDoors.mod_pocketDim.blocks.dimHatch; import StevenDimDoors.mod_pocketDim.commands.CommandCreateDungeonRift; +import StevenDimDoors.mod_pocketDim.commands.CommandCreatePocket; import StevenDimDoors.mod_pocketDim.commands.CommandDeleteAllLinks; import StevenDimDoors.mod_pocketDim.commands.CommandDeleteDimensionData; import StevenDimDoors.mod_pocketDim.commands.CommandDeleteRifts; @@ -31,7 +32,6 @@ import StevenDimDoors.mod_pocketDim.commands.CommandExportDungeon; import StevenDimDoors.mod_pocketDim.commands.CommandPrintDimensionData; import StevenDimDoors.mod_pocketDim.commands.CommandPruneDimensions; import StevenDimDoors.mod_pocketDim.commands.CommandResetDungeons; -import StevenDimDoors.mod_pocketDim.commands.CommandCreatePocket; import StevenDimDoors.mod_pocketDim.helpers.BlockRotationHelper; import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper; import StevenDimDoors.mod_pocketDim.helpers.dimHelper; @@ -46,6 +46,8 @@ import StevenDimDoors.mod_pocketDim.items.itemLinkSignature; import StevenDimDoors.mod_pocketDim.items.itemRiftRemover; import StevenDimDoors.mod_pocketDim.ticking.CommonTickHandler; import StevenDimDoors.mod_pocketDim.ticking.MobObelisk; +import StevenDimDoors.mod_pocketDim.ticking.MonolithSpawner; +import StevenDimDoors.mod_pocketDim.ticking.RiftRegenerator; import StevenDimDoors.mod_pocketDim.world.BiomeGenLimbo; import StevenDimDoors.mod_pocketDim.world.BiomeGenPocket; import StevenDimDoors.mod_pocketDim.world.LimboProvider; @@ -131,7 +133,8 @@ public class mod_pocketDim public static boolean hasInitDims = false; public static boolean isPlayerWearingGoogles = false; - private static DDProperties properties; + public static DDProperties properties; + public static MonolithSpawner spawner; //Added this field temporarily. Will be refactored out later. public static RiftGenerator riftGen; public static long genTime; @@ -176,6 +179,15 @@ public class mod_pocketDim @Init public void Init(FMLInitializationEvent event) { + CommonTickHandler commonTickHandler = new CommonTickHandler(); + TickRegistry.registerTickHandler(new ClientTickHandler(), Side.CLIENT); + TickRegistry.registerTickHandler(commonTickHandler, Side.SERVER); + + //MonolithSpawner should be initialized before any provider instances are created + //Register the other regular tick receivers as well + spawner = new MonolithSpawner(commonTickHandler, properties); + new RiftRegenerator(commonTickHandler); //No need to store the reference + LimboDecay decay = new LimboDecay(commonTickHandler, properties); transientDoor = (new TransientDoor(properties.TransientDoorID, Material.iron)).setHardness(1.0F) .setUnlocalizedName("transientDoor"); @@ -183,7 +195,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, properties.LimboDimensionID).setHardness(.2F).setUnlocalizedName("BlockLimbo").setLightValue(.0F)); + blockLimbo = (new BlockLimbo(properties.LimboBlockID, 15, Material.iron, properties.LimboDimensionID, decay).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"); @@ -247,10 +259,7 @@ public class mod_pocketDim LanguageRegistry.instance().addStringLocalization("itemGroup.dimDoorsCustomTab", "en_US", "Dimensional Doors Items"); - - TickRegistry.registerTickHandler(new ClientTickHandler(), Side.CLIENT); - TickRegistry.registerTickHandler(new CommonTickHandler(), Side.SERVER); - + //GameRegistry.registerTileEntity(TileEntityDimDoor.class, "TileEntityDimRail"); GameRegistry.registerTileEntity(TileEntityDimDoor.class, "TileEntityDimDoor"); diff --git a/StevenDimDoors/mod_pocketDim/ticking/CommonTickHandler.java b/StevenDimDoors/mod_pocketDim/ticking/CommonTickHandler.java index 100b64d..6cf3ecd 100644 --- a/StevenDimDoors/mod_pocketDim/ticking/CommonTickHandler.java +++ b/StevenDimDoors/mod_pocketDim/ticking/CommonTickHandler.java @@ -2,45 +2,29 @@ package StevenDimDoors.mod_pocketDim.ticking; import java.util.ArrayList; import java.util.EnumSet; -import java.util.Random; -import net.minecraft.entity.Entity; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.GameRules; -import net.minecraft.world.World; -import StevenDimDoors.mod_pocketDim.DDProperties; -import StevenDimDoors.mod_pocketDim.DimData; -import StevenDimDoors.mod_pocketDim.LimboDecay; -import StevenDimDoors.mod_pocketDim.LinkData; -import StevenDimDoors.mod_pocketDim.TileEntityRift; import StevenDimDoors.mod_pocketDim.mod_pocketDim; -import StevenDimDoors.mod_pocketDim.helpers.dimHelper; -import StevenDimDoors.mod_pocketDim.helpers.yCoordHelper; -import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.ITickHandler; import cpw.mods.fml.common.TickType; -import cpw.mods.fml.relauncher.Side; -public class CommonTickHandler implements ITickHandler +public class CommonTickHandler implements ITickHandler, IRegularTickSender { - private int tickCount = 0; - private static DDProperties properties = null; - 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 PROFILING_LABEL = "Dimensional Doors: Common Tick"; - private static final String MOB_SPAWNING_RULE = "doMobSpawning"; - 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 + + private int tickCount = 0; + private ArrayList receivers; + public CommonTickHandler() { - if (properties == null) - properties = DDProperties.instance(); + this.receivers = new ArrayList(); + } + + @Override + public void registerForTicking(IRegularTickReceiver receiver, int interval, boolean onTickStart) + { + RegularTickReceiverInfo info = new RegularTickReceiverInfo(receiver, interval, onTickStart); + receivers.add(info); } @Override @@ -48,35 +32,34 @@ public class CommonTickHandler implements ITickHandler { if (type.equals(EnumSet.of(TickType.SERVER))) { - onServerTick(); + for (RegularTickReceiverInfo info : receivers) + { + if (info.OnTickStart && tickCount % info.Interval == 0) + { + info.RegularTickReceiver.notifyTick(); + } + } + } + + //TODO: Stuck this in here because it's already rather hackish. + //We should standardize this as an IRegularTickReceiver in the future. ~SenseiKiwi + if (mod_pocketDim.teleTimer > 0) + { + mod_pocketDim.teleTimer--; } } @Override public void tickEnd(EnumSet type, Object... tickData) { - if (type.equals(EnumSet.of(TickType.SERVER))) + for (RegularTickReceiverInfo info : receivers) { - if(!CommonTickHandler.chunksToPopulate.isEmpty() && IsMobSpawningAllowed()) + if (!info.OnTickStart && tickCount % info.Interval == 0) { - //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) - { - this.placeMonolithsInLimbo(chunkData[0], chunkData[1], chunkData[2]); - } - else - { - this.placeMonolithsInPockets(chunkData[0], chunkData[1], chunkData[2]); - } - - } + info.RegularTickReceiver.notifyTick(); } - CommonTickHandler.chunksToPopulate.clear(); } + tickCount++; //There is no need to reset the counter. Let it overflow. } @Override @@ -90,206 +73,4 @@ public class CommonTickHandler implements ITickHandler { return PROFILING_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; - } - - //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(chunkX * factorA + chunkZ * factorB ^ worldObj.getSeed()); - - int x, y, z; - do - { - //Select a random column within the chunk - x = chunkX * CHUNK_SIZE + random.nextInt(CHUNK_SIZE); - 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) - { - y--; - blockID = worldObj.getBlockId(x, y, z); - } - while (blockID == 0 &&y>0) - { - 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); - worldObj.spawnEntityInWorld(mob); - didSpawn=true; - } - - 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; - int x = var2*16 + rand.nextInt(16); - int z = var3*16 + rand.nextInt(16); - 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); - } - } - - private static boolean IsMobSpawningAllowed() - { - //This function is used to retrieve the value of doMobSpawning. The code is the same - //as the code used by Minecraft. Jaitsu requested this to make testing easier. ~SenseiKiwi - - GameRules rules = MinecraftServer.getServer().worldServerForDimension(0).getGameRules(); - return rules.getGameRuleBooleanValue(MOB_SPAWNING_RULE); - } - - 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 - - int i = 0; - - while (i < 15 && FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) - { - 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); - - 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) - { - 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) - { - System.out.println("An exception occurred in CommonTickHandler.onServerTick():"); - e.printStackTrace(); - } - } } diff --git a/StevenDimDoors/mod_pocketDim/ticking/IRegularTickReceiver.java b/StevenDimDoors/mod_pocketDim/ticking/IRegularTickReceiver.java new file mode 100644 index 0000000..97edb70 --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/ticking/IRegularTickReceiver.java @@ -0,0 +1,10 @@ +package StevenDimDoors.mod_pocketDim.ticking; + + +public interface IRegularTickReceiver { + + /** + * This method is called periodically to execute code based on ticks elapsed. + */ + public void notifyTick(); +} diff --git a/StevenDimDoors/mod_pocketDim/ticking/IRegularTickSender.java b/StevenDimDoors/mod_pocketDim/ticking/IRegularTickSender.java new file mode 100644 index 0000000..6ed2dca --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/ticking/IRegularTickSender.java @@ -0,0 +1,8 @@ +package StevenDimDoors.mod_pocketDim.ticking; + + +public interface IRegularTickSender { + + public void registerForTicking(IRegularTickReceiver receiver, int interval, boolean onTickStart); + +} diff --git a/StevenDimDoors/mod_pocketDim/ticking/MonolithSpawner.java b/StevenDimDoors/mod_pocketDim/ticking/MonolithSpawner.java new file mode 100644 index 0000000..2e6d269 --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/ticking/MonolithSpawner.java @@ -0,0 +1,203 @@ +package StevenDimDoors.mod_pocketDim.ticking; + +import java.util.ArrayList; +import java.util.Random; + +import net.minecraft.entity.Entity; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.GameRules; +import net.minecraft.world.World; +import StevenDimDoors.mod_pocketDim.DDProperties; +import StevenDimDoors.mod_pocketDim.DimData; +import StevenDimDoors.mod_pocketDim.helpers.dimHelper; +import StevenDimDoors.mod_pocketDim.helpers.yCoordHelper; +import StevenDimDoors.mod_pocketDim.util.ChunkLocation; + +public class MonolithSpawner implements IRegularTickReceiver { + + public static final int MAX_MONOLITH_SPAWNING_CHANCE = 100; + private static final String MOB_SPAWNING_RULE = "doMobSpawning"; + private static final int MAX_MONOLITH_SPAWN_Y = 245; + private static final int CHUNK_SIZE = 16; + private static final int MONOLITH_SPAWNING_INTERVAL = 1; + + private DDProperties properties; + private ArrayList locations; + + public MonolithSpawner(IRegularTickSender sender, DDProperties properties) + { + this.properties = properties; + this.locations = new ArrayList(); + sender.registerForTicking(this, MONOLITH_SPAWNING_INTERVAL, false); + } + + @Override + public void notifyTick() { + + //Check if any new spawning requests have come in + if (!locations.isEmpty()) + { + //Check if mob spawning is allowed + if (isMobSpawningAllowed()) + { + //Loop over the locations and call the appropriate function depending + //on whether the request is for Limbo or for a pocket dimension. + for (ChunkLocation location : locations) + { + if (location.DimensionID == properties.LimboDimensionID) + { + //Limbo chunk + placeMonolithsInLimbo(location.DimensionID, location.ChunkX, location.ChunkZ); + } + else + { + //Pocket dimension chunk + placeMonolithsInPocket(location.DimensionID, location.ChunkX, location.ChunkZ); + } + } + } + + locations.clear(); + } + } + + public void registerChunkForPopulation(int dimensionID, int chunkX, int chunkZ) + { + ChunkLocation location = new ChunkLocation(dimensionID, chunkX, chunkZ); + locations.add(location); + } + + private void placeMonolithsInPocket(int dimensionID, int chunkX, int chunkZ) + { + World pocket = dimHelper.getWorld(dimensionID); + DimData dimData = dimHelper.dimList.get(dimensionID); + int sanity = 0; + int blockID = 0; + boolean didSpawn = false; + + if (pocket == null || + 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(pocket.getSeed()); + long factorA = random.nextLong() / 2L * 2L + 1L; + long factorB = random.nextLong() / 2L * 2L + 1L; + random.setSeed(chunkX * factorA + chunkZ * factorB ^ pocket.getSeed()); + + //The following code really, really needs to be rewritten... "sanity" is not a proper variable name. ~SenseiKiwi + int x, y, z; + do + { + //Select a random column within the chunk + x = chunkX * CHUNK_SIZE + random.nextInt(CHUNK_SIZE); + z = chunkZ * CHUNK_SIZE + random.nextInt(CHUNK_SIZE); + y = MAX_MONOLITH_SPAWN_Y; + blockID = pocket.getBlockId(x, y, z); + + while (blockID == 0 &&y>0) + { + y--; + blockID = pocket.getBlockId(x, y, z); + + } + while ((blockID == properties.FabricBlockID || blockID == properties.PermaFabricBlockID) && y > 0) + { + y--; + blockID = pocket.getBlockId(x, y, z); + } + while (blockID == 0 && y > 0) + { + y--; + blockID = pocket.getBlockId(x, y, z); + } + if(y > 0) + { + int jumpSanity = 0; + int jumpHeight = 0; + do + { + jumpHeight = y + random.nextInt(10); + jumpSanity++; + } + while (!pocket.isAirBlock(x,jumpHeight+6 , z)&&jumpSanity<20); + + Entity monolith = new MobObelisk(pocket); + monolith.setLocationAndAngles(x, jumpHeight, z, 1, 1); + pocket.spawnEntityInWorld(monolith); + didSpawn = true; + } + sanity++; + } + while (sanity < 5 && !didSpawn); + } + + private void placeMonolithsInLimbo(int dimensionID, int chunkX, int chunkZ) + { + World limbo = dimHelper.getWorld(dimensionID); + + if (limbo == null) + { + return; + } + + //The following initialization code is based on code from ChunkProviderGenerate. + //It makes our generation depend on the world seed. + Random random = new Random(limbo.getSeed()); + long factorA = random.nextLong() / 2L * 2L + 1L; + long factorB = random.nextLong() / 2L * 2L + 1L; + random.setSeed(chunkX * factorA + chunkZ * factorB ^ limbo.getSeed()); + + //Okay, the following code is full of magic constants and makes little sense. =/ ~SenseiKiwi + if (random.nextInt(MAX_MONOLITH_SPAWNING_CHANCE) < properties.MonolithSpawningChance) + { + int y = 0; + int yTest; + do + { + int x = chunkX * CHUNK_SIZE + random.nextInt(CHUNK_SIZE); + int z = chunkZ * CHUNK_SIZE + random.nextInt(CHUNK_SIZE); + + while (limbo.getBlockId(x, y, z) == 0 && y <255) + { + y++; + } + y = yCoordHelper.getFirstUncovered(limbo, x, y + 2, z); + yTest = yCoordHelper.getFirstUncovered(limbo, x, y + 5, z); + if (yTest > 245) + { + return; + } + + int jumpSanity = 0; + int jumpHeight = 0; + do + { + jumpHeight = y + random.nextInt(25); + jumpSanity++; + } + while (!limbo.isAirBlock(x, jumpHeight + 6, z) && jumpSanity < 20); + + + Entity monolith = new MobObelisk(limbo); + monolith.setLocationAndAngles(x, jumpHeight, z, 1, 1); + limbo.spawnEntityInWorld(monolith); + } + while (yTest > y); + } + } + + private static boolean isMobSpawningAllowed() + { + //This function is used to retrieve the value of doMobSpawning. The code is the same + //as the code used by Minecraft. Jaitsu requested this to make testing easier. ~SenseiKiwi + + GameRules rules = MinecraftServer.getServer().worldServerForDimension(0).getGameRules(); + return rules.getGameRuleBooleanValue(MOB_SPAWNING_RULE); + } +} diff --git a/StevenDimDoors/mod_pocketDim/ticking/RegularTickReceiverInfo.java b/StevenDimDoors/mod_pocketDim/ticking/RegularTickReceiverInfo.java new file mode 100644 index 0000000..2c49bb2 --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/ticking/RegularTickReceiverInfo.java @@ -0,0 +1,16 @@ +package StevenDimDoors.mod_pocketDim.ticking; + +public class RegularTickReceiverInfo { + + public IRegularTickReceiver RegularTickReceiver; + public int Interval; + public boolean OnTickStart; + + public RegularTickReceiverInfo(IRegularTickReceiver regularTickReceiver, int interval, boolean onTickStart) + { + this.RegularTickReceiver = regularTickReceiver; + this.Interval = interval; + this.OnTickStart = onTickStart; + } + +} diff --git a/StevenDimDoors/mod_pocketDim/ticking/RiftRegenerator.java b/StevenDimDoors/mod_pocketDim/ticking/RiftRegenerator.java new file mode 100644 index 0000000..389c71d --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/ticking/RiftRegenerator.java @@ -0,0 +1,72 @@ +package StevenDimDoors.mod_pocketDim.ticking; + +import net.minecraft.world.World; +import StevenDimDoors.mod_pocketDim.DDProperties; +import StevenDimDoors.mod_pocketDim.LinkData; +import StevenDimDoors.mod_pocketDim.TileEntityRift; +import StevenDimDoors.mod_pocketDim.mod_pocketDim; +import StevenDimDoors.mod_pocketDim.helpers.dimHelper; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.relauncher.Side; + +public class RiftRegenerator implements IRegularTickReceiver { + + private static final int RIFT_REGENERATION_INTERVAL = 100; //Regenerate random rifts every 100 ticks + + private DDProperties properties; + + public RiftRegenerator(IRegularTickSender sender) + { + sender.registerForTicking(this, RIFT_REGENERATION_INTERVAL, false); + } + + @Override + public void notifyTick() + { + regenerate(); + } + + private void regenerate() + { + try + { + //Regenerate rifts that have been replaced (not permanently removed) by players + + int i = 0; + + while (i < 15 && FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) + { + 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); + + 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) + { + 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) + { + System.out.println("An exception occurred in RiftRegenerator.regenerate():"); + e.printStackTrace(); + } + } +} diff --git a/StevenDimDoors/mod_pocketDim/util/ChunkLocation.java b/StevenDimDoors/mod_pocketDim/util/ChunkLocation.java new file mode 100644 index 0000000..0f1c5c1 --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/util/ChunkLocation.java @@ -0,0 +1,15 @@ +package StevenDimDoors.mod_pocketDim.util; + +public class ChunkLocation { + + public int ChunkX; + public int ChunkZ; + public int DimensionID; + + public ChunkLocation(int dimensionID, int chunkX, int chunkZ) + { + this.DimensionID = dimensionID; + this.ChunkX = chunkX; + this.ChunkZ = chunkZ; + } +} diff --git a/StevenDimDoors/mod_pocketDim/world/LimboGenerator.java b/StevenDimDoors/mod_pocketDim/world/LimboGenerator.java index 8983afd..9ea9aa3 100644 --- a/StevenDimDoors/mod_pocketDim/world/LimboGenerator.java +++ b/StevenDimDoors/mod_pocketDim/world/LimboGenerator.java @@ -3,15 +3,6 @@ package StevenDimDoors.mod_pocketDim.world; import java.util.List; import java.util.Random; -import StevenDimDoors.mod_pocketDim.DDProperties; -import StevenDimDoors.mod_pocketDim.mod_pocketDim; -import StevenDimDoors.mod_pocketDim.helpers.dimHelper; -import StevenDimDoors.mod_pocketDim.helpers.yCoordHelper; -import StevenDimDoors.mod_pocketDim.ticking.CommonTickHandler; -import StevenDimDoors.mod_pocketDim.ticking.MobObelisk; - -import net.minecraft.block.Block; -import net.minecraft.entity.Entity; import net.minecraft.entity.EnumCreatureType; import net.minecraft.util.IProgressUpdate; import net.minecraft.util.MathHelper; @@ -31,6 +22,9 @@ import net.minecraft.world.gen.structure.MapGenVillage; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.Event.Result; import net.minecraftforge.event.terraingen.ChunkProviderEvent; +import StevenDimDoors.mod_pocketDim.DDProperties; +import StevenDimDoors.mod_pocketDim.ticking.CommonTickHandler; +import StevenDimDoors.mod_pocketDim.ticking.MonolithSpawner; public class LimboGenerator extends ChunkProviderGenerate implements IChunkProvider { @@ -110,20 +104,21 @@ public class LimboGenerator extends ChunkProviderGenerate implements IChunkProvi // caveGenerator = TerrainGen.getModdedMapGen(caveGenerator, CAVE); } - private static DDProperties properties = null; + private DDProperties properties; + private MonolithSpawner spawner; - public LimboGenerator(World par1World, long par2) + public LimboGenerator(World world, long seed, MonolithSpawner spawner, DDProperties properties) { - super(par1World, par2, false); - //par2 = 90899090; - this.rand = new Random(par2); - this.noiseGen1 = new NoiseGeneratorOctaves(this.rand, 16); //base terrain - this.noiseGen2 = new NoiseGeneratorOctaves(this.rand, 16); //hillyness - this.noiseGen3 = new NoiseGeneratorOctaves(this.rand, 80); //seems to adjust the size of features, how stretched things are -default 8 - this.noiseGen4 = new NoiseGeneratorOctaves(this.rand, 4); - this.noiseGen5 = new NoiseGeneratorOctaves(this.rand, 10); - this.noiseGen6 = new NoiseGeneratorOctaves(this.rand, 16); - this.mobSpawnerNoise = new NoiseGeneratorOctaves(this.rand, 8); + super(world, seed, false); + + LimboGenerator.rand = new Random(seed); + this.noiseGen1 = new NoiseGeneratorOctaves(LimboGenerator.rand, 16); //base terrain + this.noiseGen2 = new NoiseGeneratorOctaves(LimboGenerator.rand, 16); //hillyness + this.noiseGen3 = new NoiseGeneratorOctaves(LimboGenerator.rand, 80); //seems to adjust the size of features, how stretched things are -default 8 + this.noiseGen4 = new NoiseGeneratorOctaves(LimboGenerator.rand, 4); + this.noiseGen5 = new NoiseGeneratorOctaves(LimboGenerator.rand, 10); + this.noiseGen6 = new NoiseGeneratorOctaves(LimboGenerator.rand, 16); + this.mobSpawnerNoise = new NoiseGeneratorOctaves(LimboGenerator.rand, 8); NoiseGeneratorOctaves[] noiseGens = {noiseGen1, noiseGen2, noiseGen3, noiseGen4, noiseGen5, noiseGen6, mobSpawnerNoise}; // noiseGens = TerrainGen.getModdedNoiseGenerators(par1World, this.rand, noiseGens); @@ -134,11 +129,11 @@ public class LimboGenerator extends ChunkProviderGenerate implements IChunkProvi this.noiseGen5 = noiseGens[4]; this.noiseGen6 = noiseGens[5]; this.mobSpawnerNoise = noiseGens[6]; - // TODO Auto-generated constructor stub - this.worldObj=par1World; + + this.worldObj = world; - if (properties == null) - properties = DDProperties.instance(); + this.spawner = spawner; + this.properties = properties; } @Override @@ -153,24 +148,23 @@ public class LimboGenerator extends ChunkProviderGenerate implements IChunkProvi } @Override - public Chunk provideChunk(int par1, int par2) + public Chunk provideChunk(int chunkX, int chunkZ) { - this.rand.setSeed((long)par1 * 341873128712L + (long)par2 * 132897987541L); + //TODO: Wtf? Why do you reinitialize the seed when we already initialized it in the constructor?! ~SenseiKiwi + LimboGenerator.rand.setSeed((long) chunkX * 341873128712L + (long) chunkZ * 132897987541L); byte[] var3 = new byte[32768]; - this.generateTerrain(par1, par2, var3); - Chunk var4 = new Chunk(this.worldObj, var3, par1, par2); + this.generateTerrain(chunkX, chunkZ, var3); + Chunk var4 = new Chunk(this.worldObj, var3, chunkX, chunkZ); var4.generateSkylightMap(); - if(!var4.isTerrainPopulated) + if (!var4.isTerrainPopulated) { var4.isTerrainPopulated=true; - CommonTickHandler.chunksToPopulate.add(new int[] {properties.LimboDimensionID,par1,par2}); + spawner.registerChunkForPopulation(properties.LimboDimensionID, chunkX, chunkZ); } - - - return var4; } + @Override public Chunk loadChunk(int var1, int var2) { // TODO Auto-generated method stub diff --git a/StevenDimDoors/mod_pocketDim/world/LimboProvider.java b/StevenDimDoors/mod_pocketDim/world/LimboProvider.java index 02e7b82..99737fd 100644 --- a/StevenDimDoors/mod_pocketDim/world/LimboProvider.java +++ b/StevenDimDoors/mod_pocketDim/world/LimboProvider.java @@ -12,6 +12,7 @@ import net.minecraftforge.client.IRenderHandler; import StevenDimDoors.mod_pocketDim.CloudRenderBlank; import StevenDimDoors.mod_pocketDim.DDProperties; import StevenDimDoors.mod_pocketDim.mod_pocketDim; +import StevenDimDoors.mod_pocketDim.ticking.MonolithSpawner; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -23,14 +24,15 @@ public class LimboProvider extends WorldProvider } private IRenderHandler skyRenderer; - private DDProperties properties = null; + private DDProperties properties; + private MonolithSpawner spawner; public LimboProvider() { this.hasNoSky = false; this.skyRenderer = new limboSkyProvider(); - if (properties == null) - properties = DDProperties.instance(); + this.spawner = mod_pocketDim.spawner; + this.properties = mod_pocketDim.properties; } @SideOnly(Side.CLIENT) @@ -39,12 +41,10 @@ public class LimboProvider extends WorldProvider return this.skyRenderer; } - @Override protected void registerWorldChunkManager() { super.worldChunkMgr = new WorldChunkManagerHell(mod_pocketDim.limboBiome,1,1); - //this.dimensionId = ConfigAtum.dimensionID; } @Override @@ -154,7 +154,8 @@ public class LimboProvider extends WorldProvider @Override public IChunkProvider createChunkGenerator() { - return new LimboGenerator(worldObj, 45); + //TODO: ...We're passing the LimboGenerator a fixed seed. We should be passing the world seed! @_@ ~SenseiKiwi + return new LimboGenerator(worldObj, 45, spawner, properties); } public boolean canBlockFreeze(int x, int y, int z, boolean byWater) diff --git a/StevenDimDoors/mod_pocketDim/world/PocketGenerator.java b/StevenDimDoors/mod_pocketDim/world/PocketGenerator.java index 014b2d8..1744f7e 100644 --- a/StevenDimDoors/mod_pocketDim/world/PocketGenerator.java +++ b/StevenDimDoors/mod_pocketDim/world/PocketGenerator.java @@ -1,41 +1,29 @@ package StevenDimDoors.mod_pocketDim.world; import java.util.List; -import java.util.Random; -import cpw.mods.fml.common.network.PacketDispatcher; - -import net.minecraft.entity.Entity; import net.minecraft.entity.EnumCreatureType; -import net.minecraft.network.packet.Packet34EntityTeleport; import net.minecraft.world.ChunkPosition; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.gen.ChunkProviderGenerate; -import StevenDimDoors.mod_pocketDim.DDProperties; import StevenDimDoors.mod_pocketDim.DimData; -import StevenDimDoors.mod_pocketDim.mod_pocketDim; import StevenDimDoors.mod_pocketDim.helpers.dimHelper; -import StevenDimDoors.mod_pocketDim.helpers.yCoordHelper; -import StevenDimDoors.mod_pocketDim.ticking.CommonTickHandler; -import StevenDimDoors.mod_pocketDim.ticking.MobObelisk; +import StevenDimDoors.mod_pocketDim.ticking.MonolithSpawner; public class PocketGenerator extends ChunkProviderGenerate implements IChunkProvider { private World worldObj; - private DDProperties properties = null; - - + private MonolithSpawner spawner; - public PocketGenerator(World par1World, long par2, boolean par4) + public PocketGenerator(World par1World, long par2, boolean par4, MonolithSpawner spawner) { super(par1World, par2, par4); this.worldObj = par1World; - if (properties == null) - properties = DDProperties.instance(); + this.spawner = spawner; } @Override @@ -58,8 +46,8 @@ public class PocketGenerator extends ChunkProviderGenerate implements IChunkProv if(!chunk.isTerrainPopulated) { - chunk.isTerrainPopulated=true; - CommonTickHandler.chunksToPopulate.add(new int[] {chunk.worldObj.provider.dimensionId,chunkX,chunkZ}); + chunk.isTerrainPopulated = true; + spawner.registerChunkForPopulation(worldObj.provider.dimensionId, chunkX, chunkZ); } return chunk; @@ -77,6 +65,7 @@ public class PocketGenerator extends ChunkProviderGenerate implements IChunkProv } + @SuppressWarnings("rawtypes") @Override public List getPossibleCreatures(EnumCreatureType var1, int var2, int var3, int var4) { diff --git a/StevenDimDoors/mod_pocketDim/world/pocketProvider.java b/StevenDimDoors/mod_pocketDim/world/pocketProvider.java index 9f61609..c2981e7 100644 --- a/StevenDimDoors/mod_pocketDim/world/pocketProvider.java +++ b/StevenDimDoors/mod_pocketDim/world/pocketProvider.java @@ -1,16 +1,16 @@ package StevenDimDoors.mod_pocketDim.world; -import StevenDimDoors.mod_pocketDim.CloudRenderBlank; -import StevenDimDoors.mod_pocketDim.DDProperties; -import StevenDimDoors.mod_pocketDim.mod_pocketDim; -import StevenDimDoors.mod_pocketDim.helpers.dimHelper; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.util.Vec3; import net.minecraft.world.WorldProvider; import net.minecraft.world.biome.WorldChunkManagerHell; import net.minecraft.world.chunk.IChunkProvider; -import net.minecraftforge.common.DimensionManager; +import StevenDimDoors.mod_pocketDim.CloudRenderBlank; +import StevenDimDoors.mod_pocketDim.DDProperties; +import StevenDimDoors.mod_pocketDim.mod_pocketDim; +import StevenDimDoors.mod_pocketDim.helpers.dimHelper; +import StevenDimDoors.mod_pocketDim.ticking.MonolithSpawner; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -24,13 +24,14 @@ public class pocketProvider extends WorldProvider public boolean isSavingSchematic= false; public int dimToSave; - private static DDProperties properties = null; + private DDProperties properties; + private MonolithSpawner spawner; public pocketProvider() { - this.hasNoSky=true; - if (properties == null) - properties = DDProperties.instance(); + this.hasNoSky = true; + this.spawner = mod_pocketDim.spawner; + this.properties = mod_pocketDim.properties; } @Override @@ -79,7 +80,7 @@ public class pocketProvider extends WorldProvider @Override public IChunkProvider createChunkGenerator() { - return new PocketGenerator(worldObj, dimensionId, false); + return new PocketGenerator(worldObj, dimensionId, false, spawner); } @Override