package blusunrize.immersiveengineering.common.blocks.wooden; import blusunrize.immersiveengineering.api.energy.IRotationAcceptor; import blusunrize.immersiveengineering.common.Config.IEConfig; import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IDirectionalTile; import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IHasDummyBlocks; import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IHasObjProperty; import blusunrize.immersiveengineering.common.blocks.TileEntityIEBase; import blusunrize.immersiveengineering.common.util.Utils; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing.Axis; import net.minecraft.util.ITickable; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import java.util.ArrayList; public class TileEntityWatermill extends TileEntityIEBase implements ITickable, IDirectionalTile, IHasDummyBlocks, IHasObjProperty { public EnumFacing facing = EnumFacing.NORTH; public int[] offset={0,0}; public float rotation=0; private Vec3d rotationVec = null; public boolean canTurn = false; public boolean multiblock = false; public float prevRotation = 0; private boolean formed = true; public double perTick; // @Override // public boolean hasFastRenderer() // { // return true; // } @Override public void update() { if(offset[0]!=0||offset[1]!=0||worldObj==null) return; if(isBlocked()) { canTurn=false; return; } else canTurn = multiblock||getRotationVec().lengthVector() != 0; if(worldObj.getTotalWorldTime()%64==((getPos().getX()^getPos().getZ())&63)) { rotationVec=null; } prevRotation = rotation; TileEntity acc = worldObj.getTileEntity(getPos().offset(facing.getOpposite())); if(!multiblock&&acc instanceof IRotationAcceptor) { double power = getPower(); int l=1; TileEntity tileEntity = worldObj.getTileEntity(getPos().offset(facing, l)); while (l<3 && canUse(tileEntity)) { power += ((TileEntityWatermill)tileEntity).getPower(); l++; tileEntity = worldObj.getTileEntity(getPos().offset(facing, l)); } perTick = 1f/1440 * power/l; canTurn = perTick!=0; rotation += perTick; rotation %= 1; for(int l2=1; l2<l; l2++) { tileEntity = worldObj.getTileEntity(getPos().offset(facing, l2)); if(tileEntity instanceof TileEntityWatermill) { ((TileEntityWatermill)tileEntity).rotation = rotation; ((TileEntityWatermill)tileEntity).canTurn = canTurn; ((TileEntityWatermill)tileEntity).perTick = perTick; ((TileEntityWatermill)tileEntity).multiblock = true; } } if(!worldObj.isRemote) { IRotationAcceptor dynamo = (IRotationAcceptor)acc; // if((facing.getAxis()==Axis.Z)&&dynamo.facing!=2&&dynamo.facing!=3) // return; // else if((facing.getAxis()==Axis.X)&&dynamo.facing!=4&&dynamo.facing!=5) // return; dynamo.inputRotation(Math.abs(power*.75), facing.getOpposite()); } } else if(!multiblock) { perTick = 1f/1440 * getPower(); canTurn = perTick!=0; rotation += perTick; rotation %= 1; } if(multiblock) multiblock=false; } private boolean canUse(TileEntity tileEntity) { return tileEntity instanceof TileEntityWatermill && ((TileEntityWatermill)tileEntity).offset[0]==0 && ((TileEntityWatermill)tileEntity).offset[1]==0 && ( ((TileEntityWatermill)tileEntity).facing==facing || ((TileEntityWatermill)tileEntity).facing==facing.getOpposite() ) && !((TileEntityWatermill)tileEntity).isBlocked() &&!((TileEntityWatermill)tileEntity).multiblock; } public boolean isBlocked() { if(worldObj==null) return true; for(EnumFacing fdY : new EnumFacing[]{EnumFacing.UP,EnumFacing.DOWN}) for(EnumFacing fdW : facing.getAxis()==Axis.Z?new EnumFacing[]{EnumFacing.EAST,EnumFacing.WEST}: new EnumFacing[]{EnumFacing.SOUTH,EnumFacing.NORTH}) { BlockPos pos = getPos().offset(fdW,2).offset(fdY,2); IBlockState state = worldObj.getBlockState(pos); if(state==null) return false; if(state.isSideSolid(worldObj, pos, fdW.getOpposite())) return true; if(state.isSideSolid(worldObj, pos, fdY.getOpposite())) return true; } return false; } public double getPower() { return facing.getAxis()==Axis.Z?-getRotationVec().xCoord:getRotationVec().zCoord; } public void resetRotationVec() { rotationVec=null; } public Vec3d getRotationVec() { if(rotationVec==null) { rotationVec = new Vec3d(0, 0, 0); Vec3d dirHoz = getHorizontalVec(); Vec3d dirVer = getVerticalVec(); rotationVec = Utils.addVectors(rotationVec, dirHoz); rotationVec = Utils.addVectors(rotationVec, dirVer); // worldObj.addBlockEvent(xCoord, yCoord, zCoord, getBlockType(), (int)((float)rotationVec.xCoord*10000f), (int)((float)rotationVec.zCoord*10000f)); } return rotationVec; } Vec3d getHorizontalVec() { Vec3d dir = new Vec3d(0, 0, 0); boolean faceZ = facing.ordinal()<=3; dir = Utils.addVectors(dir, Utils.getFlowVector(worldObj, getPos().add(-(faceZ?1:0), +3, -(faceZ?0:1)))); dir = Utils.addVectors(dir, Utils.getFlowVector(worldObj, getPos().add(0, +3, 0))); dir = Utils.addVectors(dir, Utils.getFlowVector(worldObj, getPos().add(+(faceZ?1:0), +3, +(faceZ?0:1)))); dir = Utils.addVectors(dir, Utils.getFlowVector(worldObj, getPos().add(-(faceZ?2:0), +2, -(faceZ?0:2)))); dir = Utils.addVectors(dir, Utils.getFlowVector(worldObj, getPos().add(+(faceZ?2:0), +2, +(faceZ?0:2)))); dir = dir.subtract(Utils.getFlowVector(worldObj, getPos().add(-(faceZ?2:0), -2, -(faceZ?0:2)))); dir = dir.subtract(Utils.getFlowVector(worldObj, getPos().add(+(faceZ?2:0), -2, +(faceZ?0:2)))); dir = dir.subtract(Utils.getFlowVector(worldObj, getPos().add(-(faceZ?1:0), -3, -(faceZ?0:1)))); dir = dir.subtract(Utils.getFlowVector(worldObj, getPos().add(0, -3, 0))); dir = dir.subtract(Utils.getFlowVector(worldObj, getPos().add(+(faceZ?1:0), -3, +(faceZ?0:1)))); return dir; } Vec3d getVerticalVec() { Vec3d dir = new Vec3d(0, 0, 0); Vec3d dirNeg = new Vec3d(0, 0, 0); dirNeg = Utils.addVectors(dirNeg, Utils.getFlowVector(worldObj, getPos().add(-(facing.getAxis()==Axis.Z?2:0), 2,-(facing.getAxis()==Axis.Z?0:2)))); dirNeg = Utils.addVectors(dirNeg, Utils.getFlowVector(worldObj, getPos().add(-(facing.getAxis()==Axis.Z?3:0), 1,-(facing.getAxis()==Axis.Z?0:3)))); dirNeg = Utils.addVectors(dirNeg, Utils.getFlowVector(worldObj, getPos().add(-(facing.getAxis()==Axis.Z?3:0), 0,-(facing.getAxis()==Axis.Z?0:3)))); dirNeg = Utils.addVectors(dirNeg, Utils.getFlowVector(worldObj, getPos().add(-(facing.getAxis()==Axis.Z?3:0),-1,-(facing.getAxis()==Axis.Z?0:3)))); dirNeg = Utils.addVectors(dirNeg, Utils.getFlowVector(worldObj, getPos().add(-(facing.getAxis()==Axis.Z?2:0),-2,-(facing.getAxis()==Axis.Z?0:2)))); Vec3d dirPos = new Vec3d(0, 0, 0); dirPos = Utils.addVectors(dirPos, Utils.getFlowVector(worldObj, getPos().add((facing.getAxis()==Axis.Z?2:0), 2,(facing.getAxis()==Axis.Z?0:2)))); dirPos = Utils.addVectors(dirPos, Utils.getFlowVector(worldObj, getPos().add((facing.getAxis()==Axis.Z?3:0), 1,(facing.getAxis()==Axis.Z?0:3)))); dirPos = Utils.addVectors(dirPos, Utils.getFlowVector(worldObj, getPos().add((facing.getAxis()==Axis.Z?3:0), 0,(facing.getAxis()==Axis.Z?0:3)))); dirPos = Utils.addVectors(dirPos, Utils.getFlowVector(worldObj, getPos().add((facing.getAxis()==Axis.Z?3:0),-1,(facing.getAxis()==Axis.Z?0:3)))); dirPos = Utils.addVectors(dirPos, Utils.getFlowVector(worldObj, getPos().add((facing.getAxis()==Axis.Z?2:0),-2,(facing.getAxis()==Axis.Z?0:2)))); if(facing.getAxis()==Axis.Z) dir = dir.addVector(dirNeg.yCoord-dirPos.yCoord,0,0); else dir = dir.addVector(0,0,dirNeg.yCoord-dirPos.yCoord); return dir; } public static boolean _Immovable() { return true; } @Override public boolean receiveClientEvent(int id, int arg) { rotationVec = new Vec3d(id/10000f, 0, arg/10000f); return true; } @Override public void readCustomNBT(NBTTagCompound nbt, boolean descPacket) { facing = EnumFacing.getFront(nbt.getInteger("facing")); prevRotation = nbt.getFloat("prevRotation"); offset = nbt.getIntArray("offset"); rotation = nbt.getFloat("rotation"); if(offset==null||offset.length<2) offset=new int[]{0,0}; } @Override public void writeCustomNBT(NBTTagCompound nbt, boolean descPacket) { nbt.setInteger("facing", facing.ordinal()); nbt.setFloat("prevRotation", prevRotation); nbt.setIntArray("offset", offset); nbt.setFloat("rotation", rotation); } @SideOnly(Side.CLIENT) private AxisAlignedBB renderAABB; @SideOnly(Side.CLIENT) @Override public AxisAlignedBB getRenderBoundingBox() { if(renderAABB==null) if(offset[0]==0&&offset[1]==0) renderAABB = new AxisAlignedBB(getPos().getX()-(facing.getAxis()==Axis.Z?2:0),getPos().getY()-2,getPos().getZ()-(facing.getAxis()==Axis.Z?0:2), getPos().getX()+(facing.getAxis()==Axis.Z?3:0),getPos().getY()+3,getPos().getZ()+(facing.getAxis()==Axis.Z?0:3)); else renderAABB = new AxisAlignedBB(getPos().getX(),getPos().getY(),getPos().getZ(), getPos().getX()+1,getPos().getY()+1,getPos().getZ()+1); return renderAABB; } @Override public double getMaxRenderDistanceSquared() { return super.getMaxRenderDistanceSquared()* IEConfig.increasedTileRenderdistance; // if(Config.getBoolean("increasedTileRenderdistance")) // return super.getMaxRenderDistanceSquared()*1.5; // return super.getMaxRenderDistanceSquared(); } @Override public EnumFacing getFacing() { return facing; } @Override public void setFacing(EnumFacing facing) { this.facing = facing; } @Override public int getFacingLimitation() { return 2; } @Override public boolean mirrorFacingOnPlacement(EntityLivingBase placer) { return true; } @Override public boolean canHammerRotate(EnumFacing side, float hitX, float hitY, float hitZ, EntityLivingBase entity) { return false; } @Override public boolean canRotate(EnumFacing axis) { return false; } @Override public boolean isDummy() { return offset[0]!=0||offset[1]!=0; } @Override public void placeDummies(BlockPos pos, IBlockState state, EnumFacing side, float hitX, float hitY, float hitZ) { for(int hh=-2; hh<=2; hh++) for(int ww=-2; ww<=2; ww++) if((hh>-2&&hh<2)||(ww>-2&&ww<2)) { BlockPos pos2 = pos.add(facing.getAxis()==Axis.Z?ww:0, hh, facing.getAxis()==Axis.Z?0:ww); worldObj.setBlockState(pos2, state); TileEntityWatermill dummy = (TileEntityWatermill)worldObj.getTileEntity(pos2); dummy.facing = facing; dummy.offset = new int[]{ww,hh}; } } @Override public void breakDummies(BlockPos pos, IBlockState state) { if (!formed) return; BlockPos initPos = pos.add(facing.getAxis()==Axis.Z?-offset[0]:0, -offset[1], facing.getAxis()==Axis.X?-offset[0]:0); for(int hh=-2; hh<=2; hh++) for(int ww=-2; ww<=2; ww++) if((hh>-2&&hh<2)||(ww>-2&&ww<2)) { BlockPos pos2 = initPos.add(facing.getAxis()==Axis.Z?ww:0, hh, facing.getAxis()==Axis.X?ww:0); TileEntity te = worldObj.getTileEntity(pos2); if(te instanceof TileEntityWatermill) { ((TileEntityWatermill) te).formed = false; worldObj.setBlockToAir(pos2); } } } static ArrayList<String> emptyDisplayList = new ArrayList(); @Override public ArrayList<String> compileDisplayList() { return emptyDisplayList; } }