package pneumaticCraft.common.tileentity; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraftforge.common.util.ForgeDirection; import pneumaticCraft.common.network.DescSynced; import pneumaticCraft.common.network.LazySynced; import pneumaticCraft.common.util.PneumaticCraftUtils; import pneumaticCraft.lib.TileEntityConstants; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public abstract class TileEntityAssemblyRobot extends TileEntityBase implements IAssemblyMachine, IResettable{ public float[] oldAngles = new float[5]; @DescSynced @LazySynced public float[] angles = new float[5]; @DescSynced public float[] targetAngles = new float[5]; public ForgeDirection[] targetDirection = new ForgeDirection[]{ForgeDirection.UNKNOWN, ForgeDirection.UNKNOWN}; @DescSynced public boolean slowMode; //used for the drill when drilling, the slowmode moves the arm 10x as slow as normal. @DescSynced protected float speed = 1.0F; protected enum EnumAngles{ TURN, BASE, MIDDLE, TAIL, HEAD } public TileEntityAssemblyRobot(){ gotoHomePosition(); for(int i = 0; i < 5; i++) { angles[i] = targetAngles[i]; oldAngles[i] = targetAngles[i]; } } @Override public void updateEntity(){ super.updateEntity(); //set the old angles to the last tick calculated angles (used in rendering) // while(isDone()) { // gotoNeighbour(ForgeDirection.SOUTH, ForgeDirection.EAST); // if(!isDone()) break; // gotoHomePosition(); // for(int i = 0; i < 5; i++) { oldAngles[i] = angles[i]; } //move the arms and claw more to their destination for(int i = 0; i < 5; i++) { if(angles[i] > targetAngles[i]) { angles[i] = Math.max(angles[i] - TileEntityConstants.ASSEMBLY_IO_UNIT_ARM_SPEED * (slowMode ? 0.1F : 1) * speed, targetAngles[i]); } else if(angles[i] < targetAngles[i]) { angles[i] = Math.min(angles[i] + TileEntityConstants.ASSEMBLY_IO_UNIT_ARM_SPEED * (slowMode ? 0.1F : 1) * speed, targetAngles[i]); } } } public void gotoHomePosition(){ targetAngles[EnumAngles.TURN.ordinal()] = 0F; targetAngles[EnumAngles.BASE.ordinal()] = 0F; targetAngles[EnumAngles.MIDDLE.ordinal()] = 55F; targetAngles[EnumAngles.TAIL.ordinal()] = 35F; targetAngles[EnumAngles.HEAD.ordinal()] = 0F; } public boolean gotoTarget(){ if(targetDirection == null) return false; this.gotoNeighbour(targetDirection[0], targetDirection[1]); return isDoneMoving(); } public void gotoNeighbour(ForgeDirection direction){ gotoNeighbour(direction, ForgeDirection.UNKNOWN); } /** * Goes to the neighbour, and returns true if the neighbour was diagonal to this arm. * @param primaryDir * @param secondaryDir * @return */ @SuppressWarnings("incomplete-switch") public boolean gotoNeighbour(ForgeDirection primaryDir, ForgeDirection secondaryDir){ targetDirection = new ForgeDirection[]{primaryDir, secondaryDir}; boolean diagonal = true; boolean diagonalAllowed = canMoveToDiagonalNeighbours(); switch(primaryDir){ case SOUTH: if(secondaryDir == ForgeDirection.EAST && diagonalAllowed) { targetAngles[EnumAngles.TURN.ordinal()] = -45F; targetAngles[EnumAngles.HEAD.ordinal()] = 40F; } else if(secondaryDir == ForgeDirection.WEST && diagonalAllowed) { targetAngles[EnumAngles.TURN.ordinal()] = 45F; targetAngles[EnumAngles.HEAD.ordinal()] = -40F; } else { targetAngles[EnumAngles.TURN.ordinal()] = 0F; targetAngles[EnumAngles.HEAD.ordinal()] = 90F; diagonal = false; } break; case EAST: targetAngles[EnumAngles.TURN.ordinal()] = -90F; targetAngles[EnumAngles.HEAD.ordinal()] = 0F; diagonal = false; break; case NORTH: if(secondaryDir == ForgeDirection.EAST && diagonalAllowed) { targetAngles[EnumAngles.TURN.ordinal()] = -135F; targetAngles[EnumAngles.HEAD.ordinal()] = -40F; } else if(secondaryDir == ForgeDirection.WEST && diagonalAllowed) { targetAngles[EnumAngles.TURN.ordinal()] = 135F; targetAngles[EnumAngles.HEAD.ordinal()] = 40F; } else { targetAngles[EnumAngles.TURN.ordinal()] = 180F; targetAngles[EnumAngles.HEAD.ordinal()] = 90F; diagonal = false; } break; case WEST: targetAngles[EnumAngles.TURN.ordinal()] = 90F; targetAngles[EnumAngles.HEAD.ordinal()] = 0F; diagonal = false; break; } if(diagonal) { targetAngles[EnumAngles.BASE.ordinal()] = 160F; targetAngles[EnumAngles.MIDDLE.ordinal()] = -85F; targetAngles[EnumAngles.TAIL.ordinal()] = -20F; } else { targetAngles[EnumAngles.BASE.ordinal()] = 100F; targetAngles[EnumAngles.MIDDLE.ordinal()] = -10F; targetAngles[EnumAngles.TAIL.ordinal()] = 0F; } return diagonal; } public boolean hoverOverTarget(){ if(targetDirection == null) return false; return this.hoverOverNeighbour(targetDirection); } public boolean hoverOverNeighbour(ForgeDirection[] directions){ hoverOverNeighbour(directions[0], directions[1]); return isDoneMoving(); } public void hoverOverNeighbour(ForgeDirection primaryDir, ForgeDirection secondaryDir){ boolean diagonal = gotoNeighbour(primaryDir, secondaryDir); if(diagonal) { targetAngles[EnumAngles.BASE.ordinal()] = 160F; targetAngles[EnumAngles.MIDDLE.ordinal()] = -95F; targetAngles[EnumAngles.TAIL.ordinal()] = -10F; } else { targetAngles[EnumAngles.BASE.ordinal()] = 100F; targetAngles[EnumAngles.MIDDLE.ordinal()] = -20F; targetAngles[EnumAngles.TAIL.ordinal()] = 10F; } } public TileEntity getTileEntityForCurrentDirection(){ return getTileEntityForDirection(targetDirection[0], targetDirection[1]); } public TileEntity getTileEntityForDirection(ForgeDirection[] directions){ return getTileEntityForDirection(directions[0], directions[1]); } public TileEntity getTileEntityForDirection(ForgeDirection firstDir, ForgeDirection secondDir){ return worldObj.getTileEntity(xCoord + firstDir.offsetX + secondDir.offsetX, yCoord + firstDir.offsetY + secondDir.offsetY, zCoord + firstDir.offsetZ + secondDir.offsetZ); } protected boolean isDoneMoving(){ for(int i = 0; i < 5; i++) { if(!PneumaticCraftUtils.areFloatsEqual(angles[i], targetAngles[i])) return false; } return true; } public boolean isDoneRotatingYaw(){ return PneumaticCraftUtils.areFloatsEqual(angles[EnumAngles.TURN.ordinal()], targetAngles[EnumAngles.TURN.ordinal()]); } @Override public void readFromNBT(NBTTagCompound tag){ super.readFromNBT(tag); for(int i = 0; i < 5; i++) { angles[i] = tag.getFloat("angle" + i); targetAngles[i] = tag.getFloat("targetAngle" + i); } slowMode = tag.getBoolean("slowMode"); speed = tag.getFloat("speed"); targetDirection[0] = ForgeDirection.values()[tag.getInteger("targetDir1")]; targetDirection[1] = ForgeDirection.values()[tag.getInteger("targetDir2")]; } @Override public void writeToNBT(NBTTagCompound tag){ super.writeToNBT(tag); for(int i = 0; i < 5; i++) { tag.setFloat("angle" + i, angles[i]); tag.setFloat("targetAngle" + i, targetAngles[i]); } tag.setBoolean("slowMode", slowMode); tag.setFloat("speed", speed); if(targetDirection != null) { if(targetDirection.length > 0) tag.setInteger("targetDir1", targetDirection[0].ordinal()); if(targetDirection.length > 1) tag.setInteger("targetDir2", targetDirection[1].ordinal()); } } public abstract boolean canMoveToDiagonalNeighbours(); public ForgeDirection[] getPlatformDirection(){ for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { if(dir != ForgeDirection.UP && dir != ForgeDirection.DOWN) { if(worldObj.getTileEntity(xCoord + dir.offsetX, yCoord, zCoord + dir.offsetZ) instanceof TileEntityAssemblyPlatform) return new ForgeDirection[]{dir, ForgeDirection.UNKNOWN}; } } if(canMoveToDiagonalNeighbours()) { if(worldObj.getTileEntity(xCoord + ForgeDirection.NORTH.offsetX + ForgeDirection.WEST.offsetX, yCoord, zCoord + ForgeDirection.NORTH.offsetZ + ForgeDirection.WEST.offsetZ) instanceof TileEntityAssemblyPlatform) return new ForgeDirection[]{ForgeDirection.NORTH, ForgeDirection.WEST}; if(worldObj.getTileEntity(xCoord + ForgeDirection.NORTH.offsetX + ForgeDirection.EAST.offsetX, yCoord, zCoord + ForgeDirection.NORTH.offsetZ + ForgeDirection.EAST.offsetZ) instanceof TileEntityAssemblyPlatform) return new ForgeDirection[]{ForgeDirection.NORTH, ForgeDirection.EAST}; if(worldObj.getTileEntity(xCoord + ForgeDirection.SOUTH.offsetX + ForgeDirection.WEST.offsetX, yCoord, zCoord + ForgeDirection.SOUTH.offsetZ + ForgeDirection.WEST.offsetZ) instanceof TileEntityAssemblyPlatform) return new ForgeDirection[]{ForgeDirection.SOUTH, ForgeDirection.WEST}; if(worldObj.getTileEntity(xCoord + ForgeDirection.SOUTH.offsetX + ForgeDirection.EAST.offsetX, yCoord, zCoord + ForgeDirection.SOUTH.offsetZ + ForgeDirection.EAST.offsetZ) instanceof TileEntityAssemblyPlatform) return new ForgeDirection[]{ForgeDirection.SOUTH, ForgeDirection.EAST}; } return null; } @Override @SideOnly(Side.CLIENT) public AxisAlignedBB getRenderBoundingBox(){ return AxisAlignedBB.getBoundingBox(xCoord - 1, yCoord - 1, zCoord - 1, xCoord + 2, yCoord + 2, zCoord + 2); } @Override public void setSpeed(float speed){ this.speed = speed; } }