d923e98942
Reimplemented Limbo Decay in two forms. Firstly, Unraveled Fabric accepts random ticks now and has a 50% chance of searching the 6 blocks against its faces for blocks to decay. The average time for this decay to occur is about 2 minutes and 17 seconds. The decay progresses a little slowly because of having to go through stages. We might want to consider decaying straight into Unraveled Fabric, or at least having fewer stages. This approach is better than randomly decaying isolated blocks because it looks like decay is spreading from the Unraveled Fabric. Secondly, every tick, we pick a random block from each active section in Limbo and turn it into Unraveled Fabric immediately. Note that a section is a 16x16x16 block cube inside a chunk. This is "fast decay", and it's meant to stop players from avoiding Limbo decay by building floating structures. It's not immediately obvious if you place a single block, but if you build a 5x5 block platform, the average time for some block to get converted drops to about 8 seconds, and it spreads from there. Most of the logic for this is in a new class: LimboDecay. It's worth studying whether this new implementation affects Minecraft's performance. I'm not completely sure whether that would be an issue. The frequency of either decay type can be decreased to improve performance.
274 lines
6.6 KiB
Java
274 lines
6.6 KiB
Java
package StevenDimDoors.mod_pocketDim;
|
|
|
|
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 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
|
|
{
|
|
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 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
|
|
|
|
public CommonTickHandler()
|
|
{
|
|
if (properties == null)
|
|
properties = DDProperties.instance();
|
|
}
|
|
|
|
@Override
|
|
public void tickStart(EnumSet<TickType> type, Object... tickData)
|
|
{
|
|
if (type.equals(EnumSet.of(TickType.SERVER)))
|
|
{
|
|
onServerTick();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void tickEnd(EnumSet<TickType> type, Object... tickData)
|
|
{
|
|
if (type.equals(EnumSet.of(TickType.SERVER)))
|
|
{
|
|
if(!CommonTickHandler.chunksToPopulate.isEmpty())
|
|
{
|
|
//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]);
|
|
}
|
|
|
|
}
|
|
}
|
|
CommonTickHandler.chunksToPopulate.clear();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public EnumSet<TickType> ticks()
|
|
{
|
|
return EnumSet.of(TickType.SERVER);
|
|
}
|
|
|
|
@Override
|
|
public String getLabel()
|
|
{
|
|
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;
|
|
}
|
|
|
|
//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 void onServerTick()
|
|
{
|
|
tickCount++; //There is no need to reset the counter. Let it overflow. Really.
|
|
|
|
if (tickCount % RIFT_REGENERATION_INTERVAL == 0)
|
|
{
|
|
regenerateRifts();
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|