Created build.gradle
Restructured folder structure for ForgeGradle Signed-off-by: deathrat <deathrat43@gmail.com>
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
package StevenDimDoors.mod_pocketDim.ticking;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.core.DDTeleporter;
|
||||
import cpw.mods.fml.common.ITickHandler;
|
||||
import cpw.mods.fml.common.TickType;
|
||||
|
||||
public class CommonTickHandler implements ITickHandler, IRegularTickSender
|
||||
{
|
||||
private static final String PROFILING_LABEL = "Dimensional Doors: Common Tick";
|
||||
|
||||
private int tickCount = 0;
|
||||
private ArrayList<RegularTickReceiverInfo> receivers;
|
||||
|
||||
|
||||
public CommonTickHandler()
|
||||
{
|
||||
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
|
||||
public void tickStart(EnumSet<TickType> type, Object... tickData)
|
||||
{
|
||||
if (type.equals(EnumSet.of(TickType.SERVER)))
|
||||
{
|
||||
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 (DDTeleporter.cooldown > 0)
|
||||
{
|
||||
DDTeleporter.cooldown--;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tickEnd(EnumSet<TickType> type, Object... tickData)
|
||||
{
|
||||
for (RegularTickReceiverInfo info : receivers)
|
||||
{
|
||||
if (!info.OnTickStart && tickCount % info.Interval == 0)
|
||||
{
|
||||
info.RegularTickReceiver.notifyTick();
|
||||
}
|
||||
}
|
||||
tickCount++; //There is no need to reset the counter. Let it overflow.
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<TickType> ticks()
|
||||
{
|
||||
return EnumSet.of(TickType.SERVER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel()
|
||||
{
|
||||
return PROFILING_LABEL; //Used for profiling!
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package StevenDimDoors.mod_pocketDim.ticking;
|
||||
|
||||
|
||||
public interface IRegularTickSender {
|
||||
|
||||
public void registerForTicking(IRegularTickReceiver receiver, int interval, boolean onTickStart);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package StevenDimDoors.mod_pocketDim.ticking;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockContainer;
|
||||
import net.minecraft.world.ChunkCoordIntPair;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
|
||||
/**
|
||||
* 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 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.
|
||||
private final int[] decaySequence;
|
||||
|
||||
private final Random random;
|
||||
private final DDProperties properties;
|
||||
private final int[] blocksImmuneToDecay;
|
||||
|
||||
public LimboDecay(IRegularTickSender tickSender, DDProperties properties)
|
||||
{
|
||||
decaySequence = new int[] {
|
||||
properties.LimboBlockID,
|
||||
Block.gravel.blockID,
|
||||
Block.cobblestone.blockID,
|
||||
Block.stone.blockID
|
||||
};
|
||||
|
||||
blocksImmuneToDecay = new int[] {
|
||||
properties.LimboBlockID,
|
||||
properties.PermaFabricBlockID,
|
||||
properties.TransientDoorID,
|
||||
properties.DimensionalDoorID,
|
||||
properties.WarpDoorID,
|
||||
properties.RiftBlockID,
|
||||
properties.UnstableDoorID
|
||||
};
|
||||
|
||||
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 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)
|
||||
{
|
||||
//Apply decay to the blocks above, below, and on all four sides.
|
||||
//World.getBlockId() implements bounds checking, so we don't have to worry about reaching out of the world
|
||||
decayBlock(world, x - 1, y, z);
|
||||
decayBlock(world, x + 1, y, z);
|
||||
decayBlock(world, x, y, z - 1);
|
||||
decayBlock(world, x, y, z + 1);
|
||||
decayBlock(world, x, y - 1, z);
|
||||
decayBlock(world, x, y + 1, z);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Picks random blocks from each active chunk in Limbo and, if decay is applicable, converts them directly to Unraveled Fabric.
|
||||
* This decay method is designed to stop players from avoiding Limbo decay by building floating structures.
|
||||
*/
|
||||
private void applyRandomFastDecay()
|
||||
{
|
||||
int x, y, z;
|
||||
int sectionY;
|
||||
int limboHeight;
|
||||
World limbo = DimensionManager.getWorld(properties.LimboDimensionID);
|
||||
|
||||
if (limbo != null)
|
||||
{
|
||||
limboHeight = limbo.getHeight();
|
||||
|
||||
//Obtain the coordinates of active chunks in Limbo. For each section of each chunk,
|
||||
//pick a random block and try to apply fast decay.
|
||||
for (Object coordObject : limbo.activeChunkSet)
|
||||
{
|
||||
ChunkCoordIntPair chunkCoord = (ChunkCoordIntPair) coordObject;
|
||||
|
||||
//Loop through each chunk section and fast-decay a random block
|
||||
//Apply the changes using the world object instead of directly to the chunk so that clients are always notified.
|
||||
for (sectionY = 0; sectionY < limboHeight; sectionY += SECTION_HEIGHT)
|
||||
{
|
||||
x = chunkCoord.chunkXPos * CHUNK_SIZE + random.nextInt(CHUNK_SIZE);
|
||||
z = chunkCoord.chunkZPos * CHUNK_SIZE + random.nextInt(CHUNK_SIZE);
|
||||
y = sectionY + random.nextInt(SECTION_HEIGHT);
|
||||
decayBlockFast(limbo, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a block can be decayed and, if so, changes it directly into Unraveled Fabric.
|
||||
*/
|
||||
private boolean decayBlockFast(World world, int x, int y, int z)
|
||||
{
|
||||
int blockID = world.getBlockId(x, y, z);
|
||||
if (canDecayBlock(blockID))
|
||||
{
|
||||
world.setBlock(x, y, z, properties.LimboBlockID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a block can be decayed and, if so, changes it to the next block ID along the decay sequence.
|
||||
*/
|
||||
private boolean decayBlock(World world, int x, int y, int z)
|
||||
{
|
||||
int index;
|
||||
int blockID = world.getBlockId(x, y, z);
|
||||
if (canDecayBlock(blockID))
|
||||
{
|
||||
//Loop over the block IDs that decay can go through.
|
||||
//Find an index matching the current blockID, if any.
|
||||
for (index = 0; index < decaySequence.length; index++)
|
||||
{
|
||||
if (decaySequence[index] == blockID)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Since the decay sequence is a reversed list, the block ID in the index before our match
|
||||
//is the block ID we should change this block into. A trick in this approach is that if
|
||||
//we loop over the array without finding a match, then (index - 1) will contain the
|
||||
//last ID in the array, which is the first one that all blocks decay into.
|
||||
//We assume that Unraveled Fabric is NOT decayable. Otherwise, this will go out of bounds!
|
||||
|
||||
world.setBlock(x, y, z, decaySequence[index - 1]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a block can decay. We will not decay air, certain DD blocks, or containers.
|
||||
*/
|
||||
private boolean canDecayBlock(int blockID)
|
||||
{
|
||||
if (blockID == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int k = 0; k < blocksImmuneToDecay.length; k++)
|
||||
{
|
||||
if (blockID == blocksImmuneToDecay[k])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Block block = Block.blocksList[blockID];
|
||||
return (block == null || !(block instanceof BlockContainer));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
package StevenDimDoors.mod_pocketDim.ticking;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.entity.DataWatcher;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityFlying;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.SharedMonsterAttributes;
|
||||
import net.minecraft.entity.monster.IMob;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.ChunkCoordinates;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.ForgeHooks;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.DDTeleporter;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
import StevenDimDoors.mod_pocketDim.world.LimboProvider;
|
||||
import StevenDimDoors.mod_pocketDim.world.PocketProvider;
|
||||
|
||||
public class MobMonolith extends EntityFlying implements IMob
|
||||
{
|
||||
|
||||
float soundTime = 0;
|
||||
int aggro = 0;
|
||||
byte textureState = 0;
|
||||
|
||||
float scaleFactor = 0;
|
||||
int aggroMax;
|
||||
int destX = 0; // unused fields?
|
||||
int destY = 0;
|
||||
int destZ = 0;
|
||||
|
||||
@Override
|
||||
protected void damageEntity(DamageSource par1DamageSource, float par2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean attackEntityFrom(DamageSource par1DamageSource, float par2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public MobMonolith(World par1World)
|
||||
{
|
||||
super(par1World);
|
||||
this.setSize(3F, 9.0F);
|
||||
this.noClip=true;
|
||||
this.scaleFactor= (float) ((rand.nextDouble()/2)+1);
|
||||
this.aggroMax=rand.nextInt(245)+200;
|
||||
|
||||
if (properties == null)
|
||||
properties = DDProperties.instance();
|
||||
}
|
||||
|
||||
private static DDProperties properties = null;
|
||||
|
||||
@Override
|
||||
public boolean canDespawn()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyEntityAttributes()
|
||||
{
|
||||
super.applyEntityAttributes();
|
||||
this.getAttributeMap().getAttributeInstance(SharedMonsterAttributes.maxHealth).setAttribute(20);
|
||||
}
|
||||
|
||||
public boolean canBePushed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getRenderSizeModifier()
|
||||
{
|
||||
return this.scaleFactor;
|
||||
}
|
||||
|
||||
public void setEntityPosition(Entity entity, double x, double y, double z)
|
||||
{
|
||||
entity.lastTickPosX = entity.prevPosX = entity.posX = x;
|
||||
entity.lastTickPosY = entity.prevPosY = entity.posY = y + entity.yOffset;
|
||||
entity.lastTickPosZ = entity.prevPosZ = entity.posZ = z;
|
||||
entity.setPosition(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void entityInit()
|
||||
{
|
||||
super.entityInit();
|
||||
this.dataWatcher.addObject(16, Byte.valueOf((byte)0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntityUpdate()
|
||||
{
|
||||
if (!(this.worldObj.provider instanceof LimboProvider || this.worldObj.provider instanceof PocketProvider))
|
||||
{
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
super.onEntityUpdate();
|
||||
|
||||
if (this.isEntityAlive() && this.isEntityInsideOpaqueBlock())
|
||||
{
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
EntityPlayer entityPlayer = this.worldObj.getClosestPlayerToEntity(this, 30);
|
||||
|
||||
if (entityPlayer != null)
|
||||
{
|
||||
if(this.soundTime<=0)
|
||||
{
|
||||
this.playSound(mod_pocketDim.modid+":monk", 1F, 1F);
|
||||
this.soundTime=100;
|
||||
}
|
||||
|
||||
this.faceEntity(entityPlayer, 1, 1);
|
||||
|
||||
if (shouldAttackPlayer(entityPlayer))
|
||||
{
|
||||
if (aggro<470)
|
||||
{
|
||||
if (rand.nextInt(11)>this.textureState||this.aggro>=300||rand.nextInt(13)>this.textureState&&this.aggroMax>this.aggro)
|
||||
{
|
||||
aggro++;
|
||||
}
|
||||
if (this.worldObj.provider instanceof PocketProvider||this.worldObj.getClosestPlayerToEntity(this, 5)!=null)
|
||||
{
|
||||
aggro++;
|
||||
aggro++;
|
||||
|
||||
if (rand.nextBoolean())
|
||||
{
|
||||
aggro++;
|
||||
}
|
||||
|
||||
}
|
||||
if (aggro>430&&this.soundTime<100)
|
||||
{
|
||||
this.worldObj.playSoundEffect(entityPlayer.posX, entityPlayer.posY, entityPlayer.posZ,mod_pocketDim.modid+":tearing",2F, 1F);
|
||||
this.soundTime=100;
|
||||
}
|
||||
if (aggro>445&&this.soundTime<200)
|
||||
{
|
||||
this.worldObj.playSoundEffect(entityPlayer.posX, entityPlayer.posY, entityPlayer.posZ,mod_pocketDim.modid+":tearing",5F, 1F);
|
||||
this.soundTime=200;
|
||||
}
|
||||
}
|
||||
else if (!this.worldObj.isRemote && !entityPlayer.capabilities.isCreativeMode)
|
||||
{
|
||||
ChunkCoordinates coords = LimboProvider.getLimboSkySpawn(entityPlayer.worldObj.rand);
|
||||
Point4D destination = new Point4D((int) (coords.posX+entityPlayer.posX), coords.posY, (int) (coords.posZ+entityPlayer.posZ ), mod_pocketDim.properties.LimboDimensionID);
|
||||
DDTeleporter.teleportEntity(entityPlayer, destination, false);
|
||||
|
||||
this.aggro = 0;
|
||||
entityPlayer.worldObj.playSoundAtEntity(entityPlayer,mod_pocketDim.modid+":crack",13, 1);
|
||||
}
|
||||
if (!(this.worldObj.provider instanceof LimboProvider || this.worldObj.getClosestPlayerToEntity(this, 5) != null) || this.aggro > 300)
|
||||
{
|
||||
for (int i = 0; i < -1+this.textureState/2; ++i)
|
||||
{
|
||||
entityPlayer.worldObj.spawnParticle("portal", entityPlayer.posX + (this.rand.nextDouble() - 0.5D) * this.width, entityPlayer.posY + this.rand.nextDouble() * entityPlayer.height - 0.75D, entityPlayer.posZ + (this.rand.nextDouble() - 0.5D) * entityPlayer.width, (this.rand.nextDouble() - 0.5D) * 2.0D, -this.rand.nextDouble(), (this.rand.nextDouble() - 0.5D) * 2.0D);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(aggro>0)
|
||||
{
|
||||
if(rand.nextInt(10)==0)
|
||||
{
|
||||
aggro--;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(aggro>0)
|
||||
{
|
||||
aggro--;
|
||||
|
||||
if(rand.nextBoolean())
|
||||
{
|
||||
aggro--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (soundTime>=0)
|
||||
{
|
||||
soundTime--;
|
||||
}
|
||||
this.textureState= (byte) (this.aggro/25);
|
||||
if (!this.worldObj.isRemote)
|
||||
{
|
||||
this.dataWatcher.updateObject(16, Byte.valueOf(this.textureState));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean shouldAttackPlayer(EntityPlayer par1EntityPlayer)
|
||||
{
|
||||
return par1EntityPlayer.canEntityBeSeen(this);
|
||||
}
|
||||
|
||||
public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
|
||||
{
|
||||
if(!(par1DamageSource == DamageSource.inWall))
|
||||
{
|
||||
this.aggro=400;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.posY=posY+1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void faceEntity(Entity par1Entity, float par2, float par3)
|
||||
{
|
||||
double d0 = par1Entity.posX - this.posX;
|
||||
double d1 = par1Entity.posZ - this.posZ;
|
||||
double d2;
|
||||
|
||||
if (par1Entity instanceof EntityLiving)
|
||||
{
|
||||
EntityLiving entityliving = (EntityLiving)par1Entity;
|
||||
d2 = entityliving.posY + entityliving.getEyeHeight() - (this.posY + this.getEyeHeight());
|
||||
}
|
||||
else
|
||||
{
|
||||
d2 = (par1Entity.boundingBox.minY + par1Entity.boundingBox.maxY) - (this.posY + this.getEyeHeight());
|
||||
}
|
||||
|
||||
double d3 = MathHelper.sqrt_double(d0 * d0 + d1 * d1);
|
||||
float f2 = (float)(Math.atan2(d1, d0) * 180.0D / Math.PI) - 90.0F;
|
||||
float f3 = (float)(-(Math.atan2(d2, d3) * 180.0D / Math.PI));
|
||||
this.rotationPitch = f3;
|
||||
this.rotationYaw = f2;
|
||||
|
||||
this.rotationYaw = f2;
|
||||
this.rotationYawHead=f2;
|
||||
this.renderYawOffset=this.rotationYaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getRotationYawHead()
|
||||
{
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
|
||||
{
|
||||
super.writeEntityToNBT(par1NBTTagCompound);
|
||||
par1NBTTagCompound.setFloat("soundTime", this.soundTime);
|
||||
par1NBTTagCompound.setInteger("aggro", this.aggro);
|
||||
par1NBTTagCompound.setInteger("aggroMax", this.aggroMax);
|
||||
par1NBTTagCompound.setByte("textureState", this.textureState);
|
||||
par1NBTTagCompound.setFloat("scaleFactor", this.scaleFactor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
|
||||
{
|
||||
super.readEntityFromNBT(par1NBTTagCompound);
|
||||
this.soundTime = par1NBTTagCompound.getFloat("soundTime");
|
||||
this.aggro = par1NBTTagCompound.getInteger("aggro");
|
||||
this.aggroMax = par1NBTTagCompound.getInteger("aggroMax");
|
||||
this.textureState = par1NBTTagCompound.getByte("textureState");
|
||||
this.scaleFactor = par1NBTTagCompound.getFloat("scaleFactor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getCanSpawnHere()
|
||||
{
|
||||
@SuppressWarnings("rawtypes")
|
||||
List list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, AxisAlignedBB.getBoundingBox( this.posX-15, posY-4, this.posZ-15, this.posX+15, this.posY+15, this.posZ+15));
|
||||
|
||||
if(this.worldObj.provider.dimensionId==DDProperties.instance().LimboDimensionID)
|
||||
{
|
||||
if(list.size()>0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
else if(this.worldObj.provider instanceof PocketProvider)
|
||||
{
|
||||
if (list.size() > 5 ||
|
||||
this.worldObj.canBlockSeeTheSky((int)this.posX, (int)this.posY, (int)this.posZ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return this.worldObj.checkNoEntityCollision(this.boundingBox) &&
|
||||
this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty() &&
|
||||
!this.worldObj.isAnyLiquid(this.boundingBox);
|
||||
}
|
||||
|
||||
public DataWatcher getDataWatcher()
|
||||
{
|
||||
return this.dataWatcher;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
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 net.minecraftforge.common.DimensionManager;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
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)
|
||||
{
|
||||
NewDimData dimension = PocketManager.getDimensionData(dimensionID);
|
||||
World pocket = DimensionManager.getWorld(dimensionID);
|
||||
|
||||
if (pocket == null ||
|
||||
dimension == null ||
|
||||
dimension.dungeon() == null ||
|
||||
dimension.dungeon().isOpen())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int sanity = 0;
|
||||
int blockID = 0;
|
||||
boolean didSpawn = false;
|
||||
|
||||
//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() ^ 0xA210FE65F20017D6L);
|
||||
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 MobMonolith(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 = DimensionManager.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() ^ 0xB5130C4ACC71A822L);
|
||||
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 MobMonolith(limbo);
|
||||
monolith.setLocationAndAngles(x, jumpHeight, z, 1, 1);
|
||||
limbo.spawnEntityInWorld(monolith);
|
||||
}
|
||||
while (yTest > y);
|
||||
}
|
||||
}
|
||||
|
||||
public 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package StevenDimDoors.mod_pocketDim.ticking;
|
||||
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
|
||||
public class RiftRegenerator implements IRegularTickReceiver {
|
||||
|
||||
private static final int RIFT_REGENERATION_INTERVAL = 200; //Regenerate random rifts every 200 ticks
|
||||
private static final int RIFTS_REGENERATED_PER_DIMENSION = 5;
|
||||
|
||||
public RiftRegenerator(IRegularTickSender sender)
|
||||
{
|
||||
sender.registerForTicking(this, RIFT_REGENERATION_INTERVAL, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyTick()
|
||||
{
|
||||
regenerateRiftsInAllWorlds();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void regenerateRiftsInAllWorlds()
|
||||
{
|
||||
//Regenerate rifts that have been replaced (not permanently removed) by players
|
||||
DDProperties properties = DDProperties.instance();
|
||||
|
||||
for (NewDimData dimension : PocketManager.getDimensions())
|
||||
{
|
||||
if (dimension.linkCount() > 0)
|
||||
{
|
||||
World world = DimensionManager.getWorld(dimension.id());
|
||||
|
||||
if (world != null)
|
||||
{
|
||||
for (int count = 0; count < RIFTS_REGENERATED_PER_DIMENSION; count++)
|
||||
{
|
||||
DimLink link = dimension.getRandomLink();
|
||||
Point4D source = link.source();
|
||||
if (!mod_pocketDim.blockRift.isBlockImmune(world, source.getX(), source.getY(), source.getZ())&& world.getChunkProvider().chunkExists(source.getX() >> 4, source.getZ() >> 4))
|
||||
{
|
||||
world.setBlock(source.getX(), source.getY(), source.getZ(), properties.RiftBlockID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user