@SideOnly(Side.CLIENT)
  private void spawnParticle(World world, int x, int y, int z) {
    int p = Minecraft.getMinecraft().gameSettings.particleSetting;
    if (rand.nextInt(1 + p / 2) == 0) {
      double d = 1.25;
      double rx = ReikaRandomHelper.getRandomPlusMinus(x + 0.5, d);
      double ry = ReikaRandomHelper.getRandomPlusMinus(y + 0.5, d);
      double rz = ReikaRandomHelper.getRandomPlusMinus(z + 0.5, d);
      EntityFlareFX fx = new EntityFlareFX(color, world, rx, ry, rz);
      Minecraft.getMinecraft().effectRenderer.addEffect(fx);
    }

    if (this.isEnhanced()) {
      int n = 2 + (int) Math.sin(Math.toRadians(this.getTicksExisted()));
      for (int i = 0; i < n; i++) {
        float s = (float) ReikaRandomHelper.getRandomPlusMinus(2D, 1);
        int l = 10 + rand.nextInt(50);
        EntityFloatingSeedsFX fx =
            new EntityFloatingSeedsFX(
                world,
                x + 0.5,
                y + 0.5,
                z + 0.5,
                rand.nextInt(360),
                ReikaRandomHelper.getRandomPlusMinus(0, 90));
        fx.fadeColors(ReikaColorAPI.mixColors(color.getColor(), 0xffffff, 0.375F), color.getColor())
            .setScale(s)
            .setLife(l)
            .setRapidExpand();
        fx.freedom *= 3;
        fx.velocity *= 3;
        Minecraft.getMinecraft().effectRenderer.addEffect(fx);
      }
    }
  }
  @Override
  protected void drawGuiContainerForegroundLayer(int par1, int par2) {
    super.drawGuiContainerForegroundLayer(par1, par2);

    int j = (width - xSize) / 2;
    int k = (height - ySize) / 2;
    int minx = 120;
    int miny = 24;
    int w = 36;
    int maxx = minx + w;
    int maxy = miny + w;

    if (mode == AspectMode.DEMAND) {
      // api.drawRectFrame(minx, miny, w, w, ReikaColorAPI.mixColors(this.getActive().getColor(),
      // 0x1e1e1e, clickDelay/90F));
      // Color.HSBtoRGB(hsb[0], Math.min(clickDelay/90F, hsb[1]), Math.min(bright/255F, hsb[2]))
      int color = ReikaColorAPI.mixColors(0x010101, 0xffffff, 1 - bright / 255F - clickDelay / 90F);
      color = ReikaColorAPI.mixColors(color, this.getActive().getColor(), 1 - clickDelay / 90F);
      api.drawRectFrame(minx, miny, w, w, color);
      if (api.isMouseInBox(j + minx, j + maxx, k + miny, k + maxy)) {
        bright = Math.min(bright + 12, 255);
      } else {
        bright = Math.max(bright - 4, 30);
      }
      if (clickDelay > 0) {
        clickDelay = Math.max(clickDelay - 4, 0);
      }

      ElementTagCompound tag = TileEntityAspectFormer.getAspectCost(this.getActive());
      int dx = 18;
      int dy = 21;
      boolean text =
          GuiScreen.isCtrlKeyDown()
              && api.isMouseInBox(
                  j + dx + 32 - 20, j + dx + 32 + 20, k + dy + 20 - 20, k + dy + 20 + 20);
      Proportionality<CrystalElement> p = text ? null : new Proportionality();
      HashMap<CrystalElement, Integer> colors = text ? null : new HashMap();
      for (CrystalElement e : tag.elementSet()) {
        if (text) {
          String s = e.displayName + ": " + tag.getValue(e) + " L/Vis";
          fontRendererObj.drawString(
              s, dx, dy, ReikaColorAPI.mixColors(e.getColor(), 0xffffff, 0.75F));
          dy += fontRendererObj.FONT_HEIGHT;
        } else {
          p.addValue(e, tag.getValue(e));
          colors.put(e, e.getColor());
        }
      }
      if (!text) {
        p.renderAsPie(dx + 32, dy + 20, 20, 0, colors);
        api.drawCircle(dx + 32, dy + 20, 20.25, 0x000000);
      }
    }
  }
  private void renderGlow(
      TileEntityChromaLamp te, double par2, double par4, double par6, float par8) {
    ElementTagCompound tag = te.getColors();
    Tessellator v5 = Tessellator.instance;
    GL11.glEnable(GL11.GL_BLEND);
    GL11.glDisable(GL11.GL_LIGHTING);
    BlendMode.ADDITIVEDARK.apply();
    ReikaTextureHelper.bindTexture(ChromatiCraft.class, "Textures/clouds/bubble.png");
    int tick = te.getTicksExisted();
    double s = 0.3875;
    double h = 0.875;

    for (CrystalElement e : tag.elementSet()) {
      GL11.glPushMatrix();
      double ang = Math.toRadians(map[e.ordinal()]);
      double ang2 = e.ordinal() * 22.5;
      double vu = Math.cos(ang);
      double vv = Math.sin(ang);
      int alpha = Math.max(0, (int) (255 * Math.sin(Math.toRadians(ang2 + tick + par8))));
      double u = (vu * (tick) % 32) / 32D;
      double v = (vv * (tick) % 32) / 32D;
      double du = 1 + u;
      double dv = 1 + v;
      int color = ReikaColorAPI.mixColors(e.getColor(), 0, alpha / 255F);
      v5.startDrawingQuads();
      v5.setColorOpaque_I(color);
      v5.setBrightness(240);
      v5.addVertexWithUV(0.5 - s, h, 0.5 - s, u, dv);
      v5.addVertexWithUV(0.5 + s, h, 0.5 - s, du, dv);
      v5.addVertexWithUV(0.5 + s, 0, 0.5 - s, du, v);
      v5.addVertexWithUV(0.5 - s, 0, 0.5 - s, u, v);

      v5.addVertexWithUV(0.5 - s, 0, 0.5 + s, du, v);
      v5.addVertexWithUV(0.5 + s, 0, 0.5 + s, u, v);
      v5.addVertexWithUV(0.5 + s, h, 0.5 + s, u, dv);
      v5.addVertexWithUV(0.5 - s, h, 0.5 + s, du, dv);

      v5.addVertexWithUV(0.5 + s, h, 0.5 - s, u, dv);
      v5.addVertexWithUV(0.5 + s, h, 0.5 + s, du, dv);
      v5.addVertexWithUV(0.5 + s, 0, 0.5 + s, du, v);
      v5.addVertexWithUV(0.5 + s, 0, 0.5 - s, u, v);

      v5.addVertexWithUV(0.5 - s, 0, 0.5 - s, du, v);
      v5.addVertexWithUV(0.5 - s, 0, 0.5 + s, u, v);
      v5.addVertexWithUV(0.5 - s, h, 0.5 + s, u, dv);
      v5.addVertexWithUV(0.5 - s, h, 0.5 - s, du, dv);
      v5.draw();
      GL11.glPopMatrix();
    }
    BlendMode.DEFAULT.apply();
    GL11.glEnable(GL11.GL_LIGHTING);
    GL11.glDisable(GL11.GL_BLEND);
  }
 private void renderCrystal(int posX, int posY) {
   float mod = 2000F;
   int tick = (int) ((System.currentTimeMillis() / (double) mod) % 16);
   CrystalElement e1 = CrystalElement.elements[tick];
   CrystalElement e2 = CrystalElement.elements[(tick + 1) % 16];
   float mix = (float) (System.currentTimeMillis() % (double) mod) / mod;
   mix = Math.min(mix * 2, 1);
   int c1 = ((CrystalBlock) ChromaBlocks.CRYSTAL.getBlockInstance()).getTintColor(e1.ordinal());
   int c2 = ((CrystalBlock) ChromaBlocks.CRYSTAL.getBlockInstance()).getTintColor(e2.ordinal());
   int color = ReikaColorAPI.mixColors(c2, c1, mix);
   CrystalRenderer.staticColor = color;
   this.drawBlockRender(
       posX, posY, ChromaBlocks.CRYSTAL.getBlockInstance(), CrystalElement.WHITE.ordinal());
   CrystalRenderer.staticColor = -1;
 }
 private void renderElementPage(CrystalElement e, int posX, int posY, int px, int c) {
   String s = ChromaDescriptions.getElementDescription(e);
   fontRendererObj.drawSplitString(String.format("%s", s), px, posY + descY, 242, c);
   IIcon ico = e.getGlowRune();
   ReikaTextureHelper.bindTerrainTexture();
   this.drawTexturedModelRectFromIcon(posX + 153, posY + 12, ico, 64, 64);
 }
 @Override
 public String
     getId() { // Normally based on world coords, but uses just color to make each pylon color
               // scannable once
   return "Pylon_"
       + color
           .toString(); // "Pylon_"+worldObj.provider.dimensionId+":"+xCoord+":"+yCoord+":"+zCoord;
 }
  @Override
  protected void writeSyncTag(NBTTagCompound NBT) {
    super.writeSyncTag(NBT);

    NBT.setInteger("color", color.ordinal());
    NBT.setBoolean("multi", hasMultiblock);
    NBT.setInteger("energy", energy);
    NBT.setBoolean("enhance", enhanced);
  }
 @Override
 public ImmutableTriple<Double, Double, Double> getTargetRenderOffset(CrystalElement e) {
   double ang = Math.toRadians(e.ordinal() * 22.5D);
   double r = 1.5;
   double dx = r * Math.sin(ang);
   double dy = 0.55;
   double dz = r * Math.cos(ang);
   return new ImmutableTriple(dx, dy, dz);
 }
 public void setColor(CrystalElement e) {
   if (worldObj.isRemote) return;
   color = e;
   BlockArray runes = this.getRuneLocations(worldObj, xCoord, yCoord, zCoord);
   for (int i = 0; i < runes.getSize(); i++) {
     Coordinate c = runes.getNthBlock(i);
     if (c.getBlock(worldObj) == ChromaBlocks.RUNE.getBlockInstance())
       worldObj.setBlockMetadataWithNotify(c.xCoord, c.yCoord, c.zCoord, color.ordinal(), 3);
   }
 }
  @Override
  public void writeEntityToNBT(NBTTagCompound nbt) {
    super.writeEntityToNBT(nbt);

    if (color != null) nbt.setInteger("color", color.ordinal());

    nbt.setBoolean("dodrops", doDrops);
    nbt.setBoolean("pylon", isPylonSpawn);

    nbt.setBoolean("isdead", isDead);
  }
  @Override
  protected void entityInit() {
    super.entityInit();
    velocity = new SphericalVector(0.15, rand.nextInt(360), rand.nextInt(360));

    if (color == null) color = CrystalElement.randomElement();

    dataWatcher.addObject(30, 0);

    if (worldObj != null) ; // spawnedEntities++;
  }
 @Override
 protected int doTick(TileEntity te, FluidStack fs) {
   int dye = fs.tag != null ? fs.tag.getInteger("berries") : 0;
   CrystalElement e = dye > 0 ? CrystalElement.elements[fs.tag.getInteger("element")] : null;
   AxisAlignedBB box = ReikaAABBHelper.getBlockAABB(te.xCoord, te.yCoord, te.zCoord);
   List<EntityItem> li = te.worldObj.getEntitiesWithinAABB(EntityItem.class, box);
   boolean flag = false;
   for (EntityItem ei : li) {
     ItemStack is = ei.getEntityItem();
     if (!te.worldObj.isRemote
         && rand.nextInt(5) == 0
         && dye < TileEntityChroma.BERRY_SATURATION
         && ChromaItems.BERRY.matchWith(is)
         && (e == null || is.getItemDamage() == e.ordinal())) {
       e = CrystalElement.elements[is.getItemDamage()];
       if (fs.tag == null) fs.tag = new NBTTagCompound();
       fs.tag.setInteger("element", e.ordinal());
       while (dye < TileEntityChroma.BERRY_SATURATION && is.stackSize > 0) {
         dye = fs.tag.getInteger("berries") + 1;
         fs.tag.setInteger("berries", dye);
         is.stackSize--;
       }
       if (is.stackSize <= 0) ei.setDead();
       flag = true;
     } else if (e != null
         && is.getItemDamage() == e.ordinal()
         && ChromaItems.SHARD.matchWith(is)
         && dye == TileEntityChroma.BERRY_SATURATION) {
       boolean done = false;
       for (int i = 0; i < ACCEL_FACTOR && !done; i++) {
         done = ItemCrystalShard.tickShardCharging(ei, e, te.xCoord, te.yCoord, te.zCoord);
       }
       if (!te.worldObj.isRemote && done) {
         fs.tag = null;
         return 200;
       }
     }
   }
   if (flag && e != null) fs.tag.setInteger("renderColor", BlockActiveChroma.getColor(e, dye));
   return 0;
 }
  @Override
  public void readEntityFromNBT(NBTTagCompound nbt) {
    super.readEntityFromNBT(nbt);

    int c = nbt.getInteger("color");
    color = c >= 0 ? CrystalElement.elements[c] : CrystalElement.randomElement();

    isPylonSpawn = nbt.getBoolean("pylon");
    doDrops = nbt.getBoolean("dodrops");

    if (nbt.getBoolean("isdead")) this.setDead();
  }
 @SideOnly(Side.CLIENT)
 private void idleParticles() {
   double px = ReikaRandomHelper.getRandomPlusMinus(xCoord + 0.5, 1.5);
   double pz = ReikaRandomHelper.getRandomPlusMinus(zCoord + 0.5, 1.5);
   float g = -(float) ReikaRandomHelper.getRandomPlusMinus(0.125, 0.0625);
   int color = CrystalElement.getBlendedColor(ticks, 40);
   int l = ReikaRandomHelper.getRandomPlusMinus(80, 40);
   EntityBlurFX fx =
       new EntityBlurFX(worldObj, px, yCoord + 1.25, pz, 0, 0, 0)
           .setGravity(g)
           .setLife(l)
           .setColor(color);
   fx.noClip = true;
   Minecraft.getMinecraft().effectRenderer.addEffect(fx);
 }
  @Override
  public void onDeath(DamageSource src) {
    ChromaSounds.DISCHARGE.playSound(this, 1F, 2F);
    if (!worldObj.isRemote) {
      Entity e = src.getEntity();
      if (e instanceof EntityPlayer) {
        EntityPlayer ep = (EntityPlayer) e;
        if (doDrops && !ReikaPlayerAPI.isFakeOrNotInteractable(ep, posX, posY, posZ, 8)) {
          int looting = EnchantmentHelper.getLootingModifier((EntityPlayer) src.getEntity());
          ReikaItemHelper.dropItem(
              this,
              ReikaItemHelper.getSizedItemStack(
                  ChromaStacks.beaconDust, rand.nextInt(1 + looting * 2)));
          if (looting > 1) {
            if (color.isPrimary()) ReikaItemHelper.dropItem(this, ChromaStacks.purityDust);
            else ReikaItemHelper.dropItem(this, ChromaStacks.auraDust);
          }
        }
        ProgressStage.BALLLIGHTNING.stepPlayerTo(ep);
      }

      this.sendDeathParticles();
    }
  }
 public int getRenderColor() {
   return ReikaColorAPI.mixColors(color.getColor(), 0x888888, (float) energy / this.getCapacity());
 }
 @Override
 public void writeSpawnData(ByteBuf buf) {
   buf.writeInt(color != null ? color.ordinal() : -1);
 }
  private void renderPylon(int posX, int posY) {
    float mod = 2000F;
    int tick = (int) ((System.currentTimeMillis() / (double) mod) % 16);
    CrystalElement e1 = CrystalElement.elements[tick];
    CrystalElement e2 = CrystalElement.elements[(tick + 1) % 16];
    float mix = (float) (System.currentTimeMillis() % (double) mod) / mod;
    mix = Math.min(mix * 2, 1);
    int c1 = e1.getColor();
    int c2 = e2.getColor();
    int color = ReikaColorAPI.mixColors(c2, c1, mix);
    ReikaTextureHelper.bindTerrainTexture();
    Tessellator v5 = Tessellator.instance;
    v5.setBrightness(240);
    v5.startDrawingQuads();
    v5.setColorOpaque_I(color);
    IIcon ico = ChromaIcons.ROUNDFLARE.getIcon();
    GL11.glEnable(GL11.GL_BLEND);
    BlendMode.ADDITIVEDARK.apply();
    float u = ico.getMinU();
    float v = ico.getMinV();
    float du = ico.getMaxU();
    float dv = ico.getMaxV();
    int w = 96;
    int x = posX + 115;
    int y = posY - 4;
    v5.addVertexWithUV(x, y + w, 0, u, dv);
    v5.addVertexWithUV(x + w, y + w, 0, du, dv);
    v5.addVertexWithUV(x + w, y, 0, du, v);
    v5.addVertexWithUV(x, y, 0, u, v);

    ico = ChromaIcons.BIGFLARE.getIcon();
    u = ico.getMinU();
    v = ico.getMinV();
    du = ico.getMaxU();
    dv = ico.getMaxV();
    w = 8;

    Iterator<PylonParticle> it = particles.iterator();
    while (it.hasNext()) {
      PylonParticle p = it.next();
      v5.addVertexWithUV(p.posX, p.posY + w, 0, u, dv);
      v5.addVertexWithUV(p.posX + w, p.posY + w, 0, du, dv);
      v5.addVertexWithUV(p.posX + w, p.posY, 0, du, v);
      v5.addVertexWithUV(p.posX, p.posY, 0, u, v);

      p.move(180D / ReikaRenderHelper.getFPS());

      p.age++;
      if (!ReikaMathLibrary.isValueInsideBounds(posX, posX + xSize - 8, p.posX)
          || !ReikaMathLibrary.isValueInsideBounds(posY, posY + 80, p.posY)) {
        it.remove();
      }
    }

    v5.draw();

    if (rand.nextInt(50) == 0) {
      particles.add(new PylonParticle(245, 40, rand.nextInt(360)));
    }

    BlendMode.DEFAULT.apply();
  }
  @SideOnly(Side.CLIENT)
  private void spawnParticles(World world, int x, int y, int z) {
    double px = x + particleX;
    double py = y + particleY;
    double pz = z;

    int color = CrystalElement.getBlendedColor(this.getTicksExisted(), 40);

    EntityBlurFX fx =
        new EntityBlurFX(world, px, py, pz).setScale(0.5F).setLife(40).setColor(color);
    Minecraft.getMinecraft().effectRenderer.addEffect(fx);

    px = x + 1 - particleX;
    py = y + 1 - particleY;
    fx = new EntityBlurFX(world, px, py, pz).setScale(0.5F).setLife(40).setColor(color);
    Minecraft.getMinecraft().effectRenderer.addEffect(fx);

    pz = z + 1;
    px = x + 1 - particleX;
    py = y + particleY;
    fx = new EntityBlurFX(world, px, py, pz).setScale(0.5F).setLife(40).setColor(color);
    Minecraft.getMinecraft().effectRenderer.addEffect(fx);

    px = x + particleX;
    py = y + 1 - particleY;
    fx = new EntityBlurFX(world, px, py, pz).setScale(0.5F).setLife(40).setColor(color);
    Minecraft.getMinecraft().effectRenderer.addEffect(fx);

    px = x;
    pz = z + particleX;
    py = y + particleY;
    fx = new EntityBlurFX(world, px, py, pz).setScale(0.5F).setLife(40).setColor(color);
    Minecraft.getMinecraft().effectRenderer.addEffect(fx);

    pz = z + 1 - particleX;
    py = y + 1 - particleY;
    fx = new EntityBlurFX(world, px, py, pz).setScale(0.5F).setLife(40).setColor(color);
    Minecraft.getMinecraft().effectRenderer.addEffect(fx);

    px = x + 1;
    pz = z + 1 - particleX;
    py = y + particleY;
    fx = new EntityBlurFX(world, px, py, pz).setScale(0.5F).setLife(40).setColor(color);
    Minecraft.getMinecraft().effectRenderer.addEffect(fx);

    pz = z + particleX;
    py = y + 1 - particleY;
    fx = new EntityBlurFX(world, px, py, pz).setScale(0.5F).setLife(40).setColor(color);
    Minecraft.getMinecraft().effectRenderer.addEffect(fx);

    double d = 0.05;
    particleX += particleVX;
    particleY += particleVY;
    particleX = MathHelper.clamp_double(particleX, 0, 1);
    particleY = MathHelper.clamp_double(particleY, 0, 1);

    if (particleX == 1 && particleY == 0) {
      particleVX = 0;
      particleVY = d;
    }
    if (particleY == 1 && particleY == 1) {
      particleVX = -d;
      particleVY = 0;
    }
    if (particleX == 0 && particleY == 1) {
      particleVX = 0;
      particleVY = -d;
    }
    if (particleX == 0 && particleY == 0) {
      particleVX = d;
      particleVY = 0;
    }
  }
 @Override
 public void readSpawnData(ByteBuf buf) {
   int c = buf.readInt();
   color = c >= 0 && c < 16 ? CrystalElement.elements[c] : CrystalElement.randomElement();
 }
 private int calcRenderColor() {
   return targetColor != null
       ? ReikaColorAPI.mixColors(targetColor.getColor(), color.getColor(), colorTransitionFraction)
       : color.getColor();
 }
  @Override
  public boolean renderWorldBlock(
      IBlockAccess world, int x, int y, int z, Block b, int modelId, RenderBlocks rb) {
    Tessellator v5 = Tessellator.instance;
    int meta = world.getBlockMetadata(x, y, z);
    int color = b.colorMultiplier(world, x, y, z);
    float red = ReikaColorAPI.getRed(color) / 255F;
    float grn = ReikaColorAPI.getGreen(color) / 255F;
    float blu = ReikaColorAPI.getBlue(color) / 255F;
    rb.renderStandardBlockWithAmbientOcclusion(b, x, y, z, red, grn, blu);
    TileEntityColorLock te = (TileEntityColorLock) world.getTileEntity(x, y, z);

    if (!te.isHeldOpen()) {
      Collection<CrystalElement> c = te.getClosedColors();
      if (!c.isEmpty()) {
        v5.addTranslation(x, y, z);
        IIcon[] ico = new IIcon[] {ChromaIcons.BASICFADE.getIcon(), ChromaIcons.FRAME.getIcon()};
        int s = c.size();
        double iy = 0.0625;
        double dx = 0.0625;
        // s will never be more than 4
        double spc = 0.03125;
        double w = (1D - (dx * 2D) - spc * (s - 1)) / s;
        double sp = spc + w;
        double o = 0.005;
        for (CrystalElement e : c) {
          // if (!BlockColoredLock.isOpen(e, te.getChannel())) { does not work on servers
          for (int i = 0; i < ico.length; i++) {
            if (i == 0) {
              int clr =
                  ReikaColorAPI.getColorWithBrightnessMultiplier(
                      ReikaColorAPI.getModifiedSat(e.getColor(), 0.85F), 0.85F);
              v5.setColorRGBA_I(clr, 192);
              v5.setBrightness(240);
            } else {
              v5.setColorOpaque_I(0xffffff);
              v5.setBrightness(b.getMixedBrightnessForBlock(world, x, y, z));
            }

            for (int k = 0; k < 4; k++) {

              float u = ico[i].getMinU();
              float v = ico[i].getMinV();
              float du = ico[i].getMaxU();
              float dv = ico[i].getMaxV();

              if (k == 0 || k == 3) {
                float scr = v;
                v = dv;
                dv = scr;
              }

              switch (k) {
                case 0:
                  v5.addVertexWithUV(1 + o, dx, iy, du, v);
                  v5.addVertexWithUV(1 + o, dx + w, iy, u, v);
                  v5.addVertexWithUV(1 + o, dx + w, 1 - iy, u, dv);
                  v5.addVertexWithUV(1 + o, dx, 1 - iy, du, dv);
                  break;
                case 1:
                  v5.addVertexWithUV(1 - iy, dx, 1 + o, du, dv);
                  v5.addVertexWithUV(1 - iy, dx + w, 1 + o, u, dv);
                  v5.addVertexWithUV(iy, dx + w, 1 + o, u, v);
                  v5.addVertexWithUV(iy, dx, 1 + o, du, v);
                  break;
                case 2:
                  v5.addVertexWithUV(-o, dx, 1 - iy, du, dv);
                  v5.addVertexWithUV(-o, dx + w, 1 - iy, u, dv);
                  v5.addVertexWithUV(-o, dx + w, iy, u, v);
                  v5.addVertexWithUV(-o, dx, iy, du, v);
                  break;
                case 3:
                  v5.addVertexWithUV(iy, dx, -o, du, v);
                  v5.addVertexWithUV(iy, dx + w, -o, u, v);
                  v5.addVertexWithUV(1 - iy, dx + w, -o, u, dv);
                  v5.addVertexWithUV(1 - iy, dx, -o, du, dv);
                  break;
              }
            }
          }

          dx += sp;
          // }
        }
        v5.addTranslation(-x, -y, -z);
      }
    }

    return true;
  }
  @Override
  public void updateEntity(World world, int x, int y, int z, int meta) {
    super.updateEntity(world, x, y, z, meta);

    if (DragonAPICore.debugtest) {
      if (!hasMultiblock) {
        CrystalElement e = CrystalElement.randomElement();
        FilledBlockArray b = ChromaStructures.getPylonStructure(world, x, y - 9, z, e);
        b.place();
        // world.setBlock(x, y+9, z, this.getTile().getBlock(), this.getTile().getBlockMetadata(),
        // 3);
        // TileEntityCrystalPylon te = (TileEntityCrystalPylon)world.getTileEntity(x, y+9, z);
        color = e;
        hasMultiblock = true;
        this.syncAllData(true);
      }
    }

    if (hasMultiblock) {
      // ReikaJavaLibrary.pConsole(energy, Side.SERVER, color == CrystalElement.BLUE);

      int max = this.getCapacity();
      if (world.getTotalWorldTime() != lastWorldTick) {
        this.charge(world, x, y, z, max);
        lastWorldTick = world.getTotalWorldTime();
      }
      energy = Math.min(energy, max);

      if (world.isRemote) {
        this.spawnParticle(world, x, y, z);
      }

      if (!world.isRemote && rand.nextInt(80) == 0) {
        int r = 8 + rand.nextInt(8);
        AxisAlignedBB box = ReikaAABBHelper.getBlockAABB(x, y, z).expand(r, r, r);
        List<EntityLivingBase> li = world.getEntitiesWithinAABB(EntityLivingBase.class, box);
        for (EntityLivingBase e : li) {
          boolean attack = !e.isDead && e.getHealth() > 0;
          if (e instanceof EntityPlayer) {
            EntityPlayer ep = (EntityPlayer) e;
            attack =
                attack && !ep.capabilities.isCreativeMode && !Chromabilities.PYLON.enabledOn(ep);
          } else if (e instanceof EntityBallLightning) {
            attack = ((EntityBallLightning) e).getElement() != color;
          }
          if (attack) {
            this.attackEntity(e);
            this.sendClientAttack(this, e);
          }
        }
      }

      float f = this.isEnhanced() ? 1.125F : 1;

      if (TileEntityCrystalPylon.TUNED_PYLONS)
        f *= CrystalMusicManager.instance.getDingPitchScale(color);

      if (this.getTicksExisted() % (int) (72 / f) == 0) {
        ChromaSounds.POWER.playSoundAtBlock(this, 1, f);
      }

      int n = this.isEnhanced() ? 24 : 36;
      if (world.isRemote && rand.nextInt(n) == 0) {
        this.spawnLightning(world, x, y, z);
      }

      if (!world.isRemote
          && ChromaOptions.BALLLIGHTNING.getState()
          && energy >= this.getCapacity() / 2
          && rand.nextInt(24000) == 0
          && this.isChunkLoaded()) {
        world.spawnEntityInWorld(
            new EntityBallLightning(world, color, x + 0.5, y + 0.5, z + 0.5)
                .setPylon()
                .setNoDrops());
      }
    }
  }