@Override
 public void handlePlacement(World world, int turns, int x, int y, int z) {
   Entity e = EntityList.createEntityByName(mobID, world);
   float x1 = BlockTools.rotateFloatX(xOffset, zOffset, turns);
   float z1 = BlockTools.rotateFloatZ(xOffset, zOffset, turns);
   float yaw = (rotation + 90.f * turns) % 360.f;
   e.setPosition(x + x1, y + yOffset, z + z1);
   e.rotationYaw = yaw;
   world.spawnEntityInWorld(e);
 }
  /** Place an entity in a nearby portal which already exists. */
  @SuppressWarnings("unchecked")
  public boolean placeInExistingPortal(
      Entity par1Entity, double par2, double par4, double par6, float par8) {
    short short1 = 128;
    double d3 = -1.0D;
    int i = 0;
    int j = 0;
    int k = 0;
    int l = MathHelper.floor_double(par1Entity.posX);
    int i1 = MathHelper.floor_double(par1Entity.posZ);
    long j1 = ChunkCoordIntPair.chunkXZ2Int(l, i1);
    boolean flag = true;
    double d4;
    int k1;

    if (this.field_85191_c.containsItem(j1)) {
      PortalPosition portalposition = (PortalPosition) this.field_85191_c.getValueByKey(j1);
      d3 = 0.0D;
      i = portalposition.posX;
      j = portalposition.posY;
      k = portalposition.posZ;
      portalposition.lastUpdateTime = this.worldServerInstance.getTotalWorldTime();
      flag = false;
    } else {
      for (k1 = l - short1; k1 <= l + short1; ++k1) {
        double d5 = (double) k1 + 0.5D - par1Entity.posX;

        for (int l1 = i1 - short1; l1 <= i1 + short1; ++l1) {
          double d6 = (double) l1 + 0.5D - par1Entity.posZ;

          for (int i2 = this.worldServerInstance.getActualHeight() - 1; i2 >= 0; --i2) {
            if (this.worldServerInstance.getBlock(k1, i2, l1) == DimBlocks.BlockDebug) {
              while (this.worldServerInstance.getBlock(k1, i2 - 1, l1) == DimBlocks.BlockDebug) {
                --i2;
              }

              d4 = (double) i2 + 0.5D - par1Entity.posY;
              double d7 = d5 * d5 + d4 * d4 + d6 * d6;

              if (d3 < 0.0D || d7 < d3) {
                d3 = d7;
                i = k1;
                j = i2;
                k = l1;
              }
            }
          }
        }
      }
    }

    if (d3 >= 0.0D) {
      if (flag) {
        // TODO ERROR?
        this.field_85191_c.add(
            j1, new PortalPosition(i, j, k, this.worldServerInstance.getTotalWorldTime()));
        this.field_85190_d.add(Long.valueOf(j1));
      }

      double d8 = (double) i + 0.5D;
      double d9 = (double) j + 0.5D;
      d4 = (double) k + 0.5D;
      int j2 = -1;

      if (this.worldServerInstance.getBlock(i - 1, j, k) == DimBlocks.BlockDebug) {
        j2 = 2;
      }

      if (this.worldServerInstance.getBlock(i + 1, j, k) == DimBlocks.BlockDebug) {
        j2 = 0;
      }

      if (this.worldServerInstance.getBlock(i, j, k - 1) == DimBlocks.BlockDebug) {
        j2 = 3;
      }

      if (this.worldServerInstance.getBlock(i, j, k + 1) == DimBlocks.BlockDebug) {
        j2 = 1;
      }

      int k2 = par1Entity.getTeleportDirection();

      if (j2 > -1) {
        int l2 = Direction.rotateLeft[j2];
        int i3 = Direction.offsetX[j2];
        int j3 = Direction.offsetZ[j2];
        int k3 = Direction.offsetX[l2];
        int l3 = Direction.offsetZ[l2];
        boolean flag1 =
            !this.worldServerInstance.isAirBlock(i + i3 + k3, j, k + j3 + l3)
                || !this.worldServerInstance.isAirBlock(i + i3 + k3, j + 1, k + j3 + l3);
        boolean flag2 =
            !this.worldServerInstance.isAirBlock(i + i3, j, k + j3)
                || !this.worldServerInstance.isAirBlock(i + i3, j + 1, k + j3);

        if (flag1 && flag2) {
          j2 = Direction.rotateOpposite[j2];
          l2 = Direction.rotateOpposite[l2];
          i3 = Direction.offsetX[j2];
          j3 = Direction.offsetZ[j2];
          k3 = Direction.offsetX[l2];
          l3 = Direction.offsetZ[l2];
          k1 = i - k3;
          d8 -= (double) k3;
          int i4 = k - l3;
          d4 -= (double) l3;
          flag1 =
              !this.worldServerInstance.isAirBlock(k1 + i3 + k3, j, i4 + j3 + l3)
                  || !this.worldServerInstance.isAirBlock(k1 + i3 + k3, j + 1, i4 + j3 + l3);
          flag2 =
              !this.worldServerInstance.isAirBlock(k1 + i3, j, i4 + j3)
                  || !this.worldServerInstance.isAirBlock(k1 + i3, j + 1, i4 + j3);
        }

        float f1 = 0.5F;
        float f2 = 0.5F;

        if (!flag1 && flag2) {
          f1 = 1.0F;
        } else if (flag1 && !flag2) {
          f1 = 0.0F;
        } else if (flag1 && flag2) {
          f2 = 0.0F;
        }

        d8 += (double) ((float) k3 * f1 + f2 * (float) i3);
        d4 += (double) ((float) l3 * f1 + f2 * (float) j3);
        float f3 = 0.0F;
        float f4 = 0.0F;
        float f5 = 0.0F;
        float f6 = 0.0F;

        if (j2 == k2) {
          f3 = 1.0F;
          f4 = 1.0F;
        } else if (j2 == Direction.rotateOpposite[k2]) {
          f3 = -1.0F;
          f4 = -1.0F;
        } else if (j2 == Direction.rotateRight[k2]) {
          f5 = 1.0F;
          f6 = -1.0F;
        } else {
          f5 = -1.0F;
          f6 = 1.0F;
        }

        double d10 = par1Entity.motionX;
        double d11 = par1Entity.motionZ;
        par1Entity.motionX = d10 * (double) f3 + d11 * (double) f6;
        par1Entity.motionZ = d10 * (double) f5 + d11 * (double) f4;
        par1Entity.rotationYaw = par8 - (float) (k2 * 90) + (float) (j2 * 90);
      } else {
        par1Entity.motionX = par1Entity.motionY = par1Entity.motionZ = 0.0D;
      }

      par1Entity.setLocationAndAngles(d8, d9, d4, par1Entity.rotationYaw, par1Entity.rotationPitch);
      return true;
    } else {
      return false;
    }
  }
  @Override
  public void updateWeather() {
    super.updateWeather();

    if (!this.worldObj.isRemote) {
      if (this.dataNotLoaded) {
        this.savefile = OrbitSpinSaveData.initWorldData(this.worldObj);
        this.readFromNBT(this.savefile.datacompound);
        if (ConfigManagerCore.enableDebug)
          System.out.println(
              "Loading data from save: " + this.savefile.datacompound.getFloat("omegaSky"));
        this.dataNotLoaded = false;
      }

      if (this.doSpinning) {
        boolean updateNeeded = true;
        if (this.angularVelocityTarget < this.angularVelocityRadians) {
          float newAngle = this.angularVelocityRadians - this.angularVelocityAccel;
          if (newAngle < this.angularVelocityTarget) {
            newAngle = this.angularVelocityTarget;
          }
          this.setSpinRate(newAngle);
          this.thrustersFiring = true;
        } else if (this.angularVelocityTarget > this.angularVelocityRadians) {
          float newAngle = this.angularVelocityRadians + this.angularVelocityAccel;
          if (newAngle > this.angularVelocityTarget) {
            newAngle = this.angularVelocityTarget;
          }
          this.setSpinRate(newAngle);
          this.thrustersFiring = true;
        } else if (this.thrustersFiring) {
          this.thrustersFiring = false;
        } else {
          updateNeeded = false;
        }

        if (updateNeeded) {
          this.writeToNBT(this.savefile.datacompound);
          this.savefile.markDirty();

          List<Object> objList = new ArrayList<Object>();
          objList.add(Float.valueOf(this.angularVelocityRadians));
          objList.add(Boolean.valueOf(this.thrustersFiring));
          GalacticraftCore.packetPipeline.sendToDimension(
              new PacketSimple(EnumSimplePacket.C_UPDATE_STATION_SPIN, objList),
              this.spaceStationDimensionID);
        }

        // Update entity positions if in freefall
        this.loadedEntities.clear();
        this.loadedEntities.addAll(this.worldObj.loadedEntityList);
        for (Entity e : this.loadedEntities) {
          if ((e instanceof EntityItem
                  || e instanceof EntityLivingBase && !(e instanceof EntityPlayer)
                  || e instanceof EntityTNTPrimed
                  || e instanceof EntityFallingBlock)
              && !e.onGround) {
            boolean freefall = true;
            if (e.boundingBox.maxX >= this.ssBoundsMinX
                && e.boundingBox.minX <= this.ssBoundsMaxX
                && e.boundingBox.maxY >= this.ssBoundsMinY
                && e.boundingBox.minY <= this.ssBoundsMaxY
                && e.boundingBox.maxZ >= this.ssBoundsMinZ
                && e.boundingBox.minZ <= this.ssBoundsMaxZ) {
              // Entity is somewhere within the space station boundaries

              // Check if the entity's bounding box is in the same block coordinates as any
              // non-vacuum block (including torches etc)
              // If so, it's assumed the entity has something close enough to catch onto, so is not
              // in freefall
              // Note: breatheable air here means the entity is definitely not in freefall
              int xmx = MathHelper.floor_double(e.boundingBox.maxX + 0.2D);
              int ym = MathHelper.floor_double(e.boundingBox.minY - 0.1D);
              int yy = MathHelper.floor_double(e.boundingBox.maxY + 0.1D);
              int zm = MathHelper.floor_double(e.boundingBox.minZ - 0.2D);
              int zz = MathHelper.floor_double(e.boundingBox.maxZ + 0.2D);
              BLOCKCHECK:
              for (int x = MathHelper.floor_double(e.boundingBox.minX - 0.2D); x <= xmx; x++) {
                for (int y = ym; y <= yy; y++) {
                  for (int z = zm; z <= zz; z++) {
                    if (this.worldObj.blockExists(x, y, z)
                        && this.worldObj.getBlock(x, y, z) != Blocks.air) {
                      freefall = false;
                      break BLOCKCHECK;
                    }
                  }
                }
              }
            }

            if (freefall) {
              // Do the rotation
              if (this.angularVelocityRadians != 0F) {
                float angle;
                final double xx = e.posX - this.spinCentreX;
                final double zz = e.posZ - this.spinCentreZ;
                double arc = Math.sqrt(xx * xx + zz * zz);
                if (xx == 0D) {
                  angle = zz > 0 ? 3.141592536F / 2 : -3.141592536F / 2;
                } else {
                  angle = (float) Math.atan(zz / xx);
                }
                if (xx < 0D) {
                  angle += 3.141592536F;
                }
                angle += this.angularVelocityRadians / 3F;
                arc = arc * this.angularVelocityRadians;
                final double offsetX = -arc * MathHelper.sin(angle);
                final double offsetZ = arc * MathHelper.cos(angle);
                e.posX += offsetX;
                e.posZ += offsetZ;
                e.lastTickPosX += offsetX;
                e.lastTickPosZ += offsetZ;

                // Rotated into an unloaded chunk (probably also drifted out to there): byebye
                if (!this.worldObj.blockExists(
                    MathHelper.floor_double(e.posX), 64, MathHelper.floor_double(e.posZ))) {
                  e.setDead();
                }

                e.boundingBox.offset(offsetX, 0.0D, offsetZ);
                // TODO check for block collisions here - if so move the entity appropriately and
                // apply fall damage
                // Moving the entity = slide along / down
                e.rotationYaw += this.skyAngularVelocity;
                while (e.rotationYaw > 360F) {
                  e.rotationYaw -= 360F;
                }
              }

              // Undo deceleration
              if (e instanceof EntityLivingBase) {
                e.motionX /= 0.91F;
                e.motionZ /= 0.91F;
                if (e instanceof EntityFlying) {
                  e.motionY /= 0.91F;
                } else if (e instanceof EntityFallingBlock) {
                  e.motionY /= 0.9800000190734863D;
                  // e.motionY += 0.03999999910593033D;
                  // e.posY += 0.03999999910593033D;
                  // e.lastTickPosY += 0.03999999910593033D;
                } else {
                  e.motionY /= 0.9800000190734863D;
                }
              } else {
                e.motionX /= 0.9800000190734863D;
                e.motionY /= 0.9800000190734863D;
                e.motionZ /= 0.9800000190734863D;
              }
            }
          }
        }
      }
    }
  }