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:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user