package me.ichun.mods.sync.common.tileentity; import cofh.api.energy.IEnergyHandler; import net.minecraft.util.ITickable; import net.minecraft.util.math.AxisAlignedBB; import net.minecraftforge.fml.common.Optional; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.particle.EntityDiggingFX; import net.minecraft.client.particle.EntitySmokeFX; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.passive.EntityTameable; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.MathHelper; import me.ichun.mods.sync.common.Sync; import java.util.List; @Optional.Interface(iface = "cofh.api.energy.IEnergyHandler", modid = "CoFHCore") public class TileEntityTreadmill extends TileEntity implements IEnergyHandler, ITickable { public TileEntityTreadmill pair; public boolean back; public int face; public EntityLiving latchedEnt; public int latchedEntId; public float latchedHealth; public int timeRunning; public boolean resync; public TileEntityTreadmill() { pair = null; back = false; latchedEnt = null; face = 0; resync = false; } @Override public void update() { if(resync) { TileEntity te = worldObj.getTileEntity(back ? (face == 1 ? xCoord + 1 : face == 3 ? xCoord - 1 : xCoord) : (face == 1 ? xCoord - 1 : face == 3 ? xCoord + 1 : xCoord), yCoord, back ? (face == 0 ? zCoord - 1 : face == 2 ? zCoord + 1 : zCoord) : (face == 0 ? zCoord + 1 : face == 2 ? zCoord - 1 : zCoord)); if(te != null && te.getClass() == this.getClass()) { TileEntityTreadmill sc = (TileEntityTreadmill)te; sc.pair = this; pair = sc; } if(latchedEntId != -1) { if(worldObj.isRemote) { Entity ent = worldObj.getEntityByID(latchedEntId); if(ent != null && ent.getDistance(getMidCoord(0), yCoord + 0.175D, getMidCoord(1)) < 7D) { latchedEnt = (EntityLiving)ent; latchedHealth = latchedEnt.getHealth(); } } else { AxisAlignedBB aabb = new AxisAlignedBB(getMidCoord(0), yCoord + 0.175D, getMidCoord(1), getMidCoord(0), yCoord + 0.175D, getMidCoord(1)).expand(0.4D, 0.4D, 0.4D); List list = worldObj.getEntitiesWithinAABB(Entity.class, aabb); for (Object aList : list) { Entity ent = (Entity) aList; if (isEntityValidForTreadmill(ent)) { if (ent.posX > aabb.minX && ent.posX < aabb.maxX && ent.posY > aabb.minY && ent.posY < aabb.maxY && ent.posZ > aabb.minZ && ent.posZ < aabb.maxZ) { latchedEnt = (EntityLiving) ent; latchedHealth = latchedEnt.getHealth(); latchedEnt.setLocationAndAngles(getMidCoord(0), yCoord + 0.175D, getMidCoord(1), (face - 2) * 90F, 0.0F); worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); break; } } } } } else if(latchedEnt != null) { latchedEnt = null; timeRunning = 0; worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); } } resync = false; if(worldObj.isRemote && !back) { if(latchedEnt == null && latchedEntId != -1 && worldObj.getWorldTime() % 27L == 0L) { Entity ent = worldObj.getEntityByID(latchedEntId); if(ent != null && ent.getDistance(getMidCoord(0), yCoord + 0.175D, getMidCoord(1)) < 3D) { latchedEnt = (EntityLiving)ent; latchedHealth = latchedEnt.getHealth(); } } if(latchedEnt != null && latchedEnt.isDead) { Entity ent = worldObj.getEntityByID(latchedEntId); if(ent != null && ent.getDistance(getMidCoord(0), yCoord + 0.175D, getMidCoord(1)) < 7D) { latchedEnt = (EntityLiving)ent; latchedHealth = latchedEnt.getHealth(); } } if(latchedEnt != null) { latchedEnt.setLocationAndAngles(getMidCoord(0), yCoord + 0.175D, getMidCoord(1), (face - 2) * 90F, 0.0F); timeRunning++; if(timeRunning > 12000) { timeRunning = 12000; } if(0.3F + (MathHelper.clamp_float((float)timeRunning / 12000F, 0.0F, 1.0F) * 0.7F) > worldObj.rand.nextFloat()) { spawnParticles(); } } } if(!worldObj.isRemote && !back) { AxisAlignedBB aabb = latchedEnt != null ? latchedEnt.getEntityBoundingBox().contract(0.1D) : new AxisAlignedBB(getMidCoord(0), yCoord + 0.175D, getMidCoord(1), getMidCoord(0), yCoord + 0.175D, getMidCoord(1)).expand(0.15D, 0.005D, 0.15D); List list = worldObj.getEntitiesWithinAABB(Entity.class, aabb); if(latchedEnt != null) { boolean remove = false; if(latchedEnt instanceof EntityTameable) { EntityTameable entityTameable = (EntityTameable)latchedEnt; //Remove sitting entities if(entityTameable.isSitting()) { timeRunning = 0; worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); remove = true; } if(entityTameable.isTamed()) { latchedEnt.setLocationAndAngles(getMidCoord(0), yCoord + 0.175D, getMidCoord(1), (face - 2) * 90F, 0.0F); aabb = latchedEnt.getEntityBoundingBox().contract(0.1D); list = worldObj.getEntitiesWithinAABB(EntityLivingBase.class, aabb); } else { entityTameable.ticksExisted = 1200; //anti despawn methods } } for (Object aList : list) { Entity ent = (Entity) aList; if (ent != latchedEnt && ent instanceof EntityLivingBase && !(ent instanceof EntityPlayer)) { double velo = 0.9D; switch (face) { case 0: { ent.motionZ = velo; break; } case 1: { ent.motionX = -velo; break; } case 2: { ent.motionZ = -velo; break; } case 3: { ent.motionX = velo; break; } } remove = true; } } if(latchedEnt != null && (!list.contains(latchedEnt) || remove || latchedHealth > latchedEnt.getHealth())) { if(latchedHealth <= latchedEnt.getHealth()) { double velo = 1.3D; switch(face) { case 0: { latchedEnt.motionZ = velo; break; } case 1: { latchedEnt.motionX = -velo; break; } case 2: { latchedEnt.motionZ = -velo; break; } case 3: { latchedEnt.motionX = velo; break; } } } latchedEnt = null; timeRunning = 0; worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); } if(latchedEnt != null) { latchedHealth = latchedEnt.getHealth(); latchedEnt.setLocationAndAngles(getMidCoord(0), yCoord + 0.175D, getMidCoord(1), (face - 2) * 90F, 0.0F); latchedEnt.getNavigator().clearPathEntity(); if (timeRunning < 12000) { timeRunning++; } //Still running. This sends RF power to nearby IEnergyHandlers if (Sync.hasCoFHCore) { this.sendRFEnergyToNearbyDevices(); } } } else { for (Object aList : list) { Entity ent = (Entity) aList; if (TileEntityTreadmill.isEntityValidForTreadmill(ent)) { if (ent.posX > aabb.minX && ent.posX < aabb.maxX && ent.posY > aabb.minY && ent.posY < aabb.maxY && ent.posZ > aabb.minZ && ent.posZ < aabb.maxZ) { latchedEnt = (EntityLiving) ent; latchedHealth = latchedEnt.getHealth(); timeRunning = 0; latchedEnt.setLocationAndAngles(getMidCoord(0), yCoord + 0.175D, getMidCoord(1), (face - 2) * 90F, 0.0F); worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); break; } } } } } } @Optional.Method(modid = "CoFHCore") private void sendRFEnergyToNearbyDevices() { float power = powerOutput() / (float)Sync.config.ratioRF; //2PW = 1RF int handlerCount = 0; IEnergyHandler[] handlers = new IEnergyHandler[ForgeDirection.VALID_DIRECTIONS.length]; for(ForgeDirection dir:ForgeDirection.VALID_DIRECTIONS) { if(dir == ForgeDirection.UP) { continue; } TileEntity te = worldObj.getTileEntity(xCoord + dir.offsetX, yCoord + dir.offsetY, zCoord + dir.offsetZ); if(te instanceof IEnergyHandler && !(te instanceof TileEntityDualVertical)) { IEnergyHandler energy = (IEnergyHandler) te; if(energy.canConnectEnergy(dir.getOpposite())) { handlerCount++; //Test if they can recieve power via simulate if(energy.receiveEnergy(dir.getOpposite(), (int)power, true) > 0) { handlers[dir.getOpposite().ordinal()] = energy; } } } } for(int i = 0; i < handlers.length; i++) { IEnergyHandler handler = handlers[i]; if(handler != null) { //Sends power equally to all nearby IEnergyHandlers that can receive it handler.receiveEnergy(ForgeDirection.getOrientation(i), Math.max(Math.round(power / (float)handlerCount), 1), false); } } } @SideOnly(Side.CLIENT) public void spawnParticles() { if(latchedEnt != null && pair != null) { double xVelo = (face == 1 ? -30D : face == 3 ? 30.0D : 0.0D); double zVelo = face == 0 ? 30D : face == 2 ? -30D : 0.0D; if(worldObj.rand.nextFloat() < 0.5F) { Minecraft.getMinecraft().effectRenderer.addEffect((new EntityDiggingFX(worldObj, pair.xCoord + worldObj.rand.nextFloat(), pair.yCoord + 0.4D, pair.zCoord + worldObj.rand.nextFloat(), xVelo, 0.0D, zVelo, Sync.blockDualVertical, 2)).applyRenderColor(2)); } else { Minecraft.getMinecraft().effectRenderer.addEffect((new EntityDiggingFX(worldObj, xCoord + worldObj.rand.nextFloat(), yCoord + 0.4D, zCoord + worldObj.rand.nextFloat(), xVelo, 0.0D, zVelo, Sync.blockDualVertical, 2)).applyRenderColor(2)); } if(timeRunning == 12000 && worldObj.rand.nextFloat() < 0.2F) { xVelo *= 0.01D; zVelo *= 0.01D; Minecraft.getMinecraft().effectRenderer.addEffect(new EntitySmokeFX(worldObj, xCoord + worldObj.rand.nextFloat(), yCoord + 0.4D, zCoord + worldObj.rand.nextFloat(), xVelo, 0.0D, zVelo)); } } } public double getMidCoord(int i) { if(back && pair != null) { return pair.getMidCoord(i); } if(i == 0)//x coord { return (face == 1 ? xCoord : face == 3 ? xCoord + 1 : xCoord + 0.5D); } else //z coord { return (face == 0 ? zCoord + 1 : face == 2 ? zCoord : zCoord + 0.5D); } } public float powerOutput() { if(back && pair != null) { return pair.powerOutput(); } float power = 0.0F; if(latchedEnt != null) { power = Sync.TREADMILL_ENTITY_HASH_MAP.get(latchedEnt.getClass()); if (latchedEnt instanceof EntityTameable && ((EntityTameable) latchedEnt).isTamed()) power = (power / 2) + (power / 4); //Decrease power if the entity isn't tamed power += MathHelper.clamp_float((float)timeRunning / 12000F, 0.0F, 1.0F) * 2F; } return power; } public void setup(TileEntityTreadmill sc, boolean b, int face2) { pair = sc; back = b; face = face2; } @Override public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { readFromNBT(pkt.func_148857_g()); } @Override public Packet getDescriptionPacket() { NBTTagCompound tag = new NBTTagCompound(); writeToNBT(tag); return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 0, tag); } @Override public void writeToNBT(NBTTagCompound tag) { super.writeToNBT(tag); tag.setBoolean("back", back); tag.setInteger("face", face); tag.setInteger("latchedID", latchedEnt != null ? latchedEnt.getEntityId() : -1); tag.setInteger("timeRunning", timeRunning); } @Override public void readFromNBT(NBTTagCompound tag) { super.readFromNBT(tag); back = tag.getBoolean("back"); face = tag.getInteger("face"); latchedEntId = tag.getInteger("latchedID"); timeRunning = tag.getInteger("timeRunning"); resync = true; } @Override @SideOnly(Side.CLIENT) public AxisAlignedBB getRenderBoundingBox() { return AxisAlignedBB.getBoundingBox(xCoord - 1, yCoord, zCoord - 1, xCoord + 2, yCoord + 1, zCoord + 2); } @Override public Block getBlockType() { return Sync.blockDualVertical; } //Will return true if the entity can use the treadmill public static boolean isEntityValidForTreadmill(Entity entity) { return Sync.TREADMILL_ENTITY_HASH_MAP.containsKey(entity.getClass()) && !((EntityLiving) entity).isChild() && !(entity instanceof EntityTameable && ((EntityTameable) entity).isSitting()); } // TE methods @Override @Optional.Method(modid = "CoFHCore") public int receiveEnergy(ForgeDirection from, int maxReceive, boolean simulate) { return 0; } @Override @Optional.Method(modid = "CoFHCore") public int extractEnergy(ForgeDirection from, int maxExtract, boolean doExtract) { return 0; } @Override @Optional.Method(modid = "CoFHCore") public boolean canConnectEnergy(ForgeDirection from) { return !back; } @Override @Optional.Method(modid = "CoFHCore") public int getEnergyStored(ForgeDirection from) { return 0; } @Override @Optional.Method(modid = "CoFHCore") public int getMaxEnergyStored(ForgeDirection from) { return 0; } }