Overhauled Tick Sending by CommonTickHandler

Overhauled the way in which CommonTickHandler triggers tick-based
actions such as Limbo decay, spawning Monoliths, and regenerating rifts.
Now CommonTickHandler implements an interface called IRegularTickSender,
which indicates that it will periodically call on classes that implement
IRegulatTickReceiver to perform some task. I added classes for each
regularly scheduled task we were performing: MonolithSpawner and
RiftRegenerator, plus converted LimboDecay to a normal class instead of
a static class.  Modified several classes so that they have access to
the MonolithSpawner instance to request MonolithSpawning when needed.
This improves the structure of our code and gets us away from the way we
did things before, which was accessing a public static list inside
CommonTickHandler from other classes and adding arrays to specify chunk
coordinates. We should not be exposing the internal state of classes
like that! And we should be using clearly defined objects to pass
information.
This commit is contained in:
SenseiKiwi
2013-07-26 05:15:44 -04:00
parent bfc532da1f
commit 687a75f4d5
15 changed files with 461 additions and 366 deletions

View File

@@ -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,

View File

@@ -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() { }
/**
* Initializes the array containing the reversed sequence of block IDs that blocks cycle through during decay.
*/
private static void initializeDecaySequence()
public LimboDecay(IRegularTickSender tickSender, DDProperties properties)
{
if (decaySequence == null)
{
if (properties == null)
properties = DDProperties.instance();
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);
}
/**
* Applies fast Limbo decay periodically.
*/
@Override
public void notifyTick()
{
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)
public 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)
@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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");
@@ -248,9 +260,6 @@ 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");

View File

@@ -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<int[]> chunksToPopulate = new ArrayList<int[]>();
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<RegularTickReceiverInfo> receivers;
public CommonTickHandler()
{
if (properties == null)
properties = DDProperties.instance();
this.receivers = new ArrayList<RegularTickReceiverInfo>();
}
@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<TickType> 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();
}
}
}

View File

@@ -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();
}

View File

@@ -0,0 +1,8 @@
package StevenDimDoors.mod_pocketDim.ticking;
public interface IRegularTickSender {
public void registerForTicking(IRegularTickReceiver receiver, int interval, boolean onTickStart);
}

View File

@@ -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<ChunkLocation> locations;
public MonolithSpawner(IRegularTickSender sender, DDProperties properties)
{
this.properties = properties;
this.locations = new ArrayList<ChunkLocation>();
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);
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
if (properties == null)
properties = DDProperties.instance();
this.worldObj = world;
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)
{
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

View File

@@ -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)

View File

@@ -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
@@ -59,7 +47,7 @@ public class PocketGenerator extends ChunkProviderGenerate implements IChunkProv
if(!chunk.isTerrainPopulated)
{
chunk.isTerrainPopulated = true;
CommonTickHandler.chunksToPopulate.add(new int[] {chunk.worldObj.provider.dimensionId,chunkX,chunkZ});
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)
{

View File

@@ -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.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