@Override
  public void validate() {
    super.validate();

    if (worldObj.isRemote) {
      initSounds();
    }
  }
  @Override
  public void handlePacketData(ByteBuf dataStream) {
    if (!worldObj.isRemote) {
      int type = dataStream.readInt();

      switch (type) {
        case 0:
          if (getReactor() != null) getReactor().setInjectionRate(dataStream.readInt());
          break;
      }

      return;
    }

    super.handlePacketData(dataStream);

    if (worldObj.isRemote) {
      boolean formed = dataStream.readBoolean();

      if (formed) {
        if (getReactor() == null || !((FusionReactor) getReactor()).formed) {
          Mekanism.proxy.doGenericSparkle(
              this,
              new INodeChecker() {
                @Override
                public boolean isNode(TileEntity tile) {
                  return tile instanceof TileEntityReactorBlock;
                }
              });
        }

        if (getReactor() == null) {
          setReactor(new FusionReactor(this));
          MekanismUtils.updateBlock(worldObj, xCoord, yCoord, zCoord);
        }

        ((FusionReactor) getReactor()).formed = true;
        getReactor().setPlasmaTemp(dataStream.readDouble());
        getReactor().setCaseTemp(dataStream.readDouble());
        getReactor().setInjectionRate(dataStream.readInt());
        getReactor().setBurning(dataStream.readBoolean());
        fuelTank.setGas(new GasStack(GasRegistry.getGas("fusionFuelDT"), dataStream.readInt()));
        deuteriumTank.setGas(new GasStack(GasRegistry.getGas("deuterium"), dataStream.readInt()));
        tritiumTank.setGas(new GasStack(GasRegistry.getGas("tritium"), dataStream.readInt()));
        waterTank.setCapacity(dataStream.readInt());
        waterTank.setFluid(new FluidStack(FluidRegistry.getFluid("water"), dataStream.readInt()));
        steamTank.setCapacity(dataStream.readInt());
        steamTank.setFluid(new FluidStack(FluidRegistry.getFluid("steam"), dataStream.readInt()));
      } else if (getReactor() != null) {
        setReactor(null);
        MekanismUtils.updateBlock(worldObj, xCoord, yCoord, zCoord);
      }
    }
  }
  @Override
  public void readFromNBT(NBTTagCompound tag) {
    super.readFromNBT(tag);

    boolean formed = tag.getBoolean("formed");

    if (formed) {
      setReactor(new FusionReactor(this));
      getReactor().setPlasmaTemp(tag.getDouble("plasmaTemp"));
      getReactor().setCaseTemp(tag.getDouble("caseTemp"));
      getReactor().setInjectionRate(tag.getInteger("injectionRate"));
      getReactor().setBurning(tag.getBoolean("burning"));
      getReactor().updateTemperatures();
    }

    fuelTank.read(tag.getCompoundTag("fuelTank"));
    deuteriumTank.read(tag.getCompoundTag("deuteriumTank"));
    tritiumTank.read(tag.getCompoundTag("tritiumTank"));
    waterTank.readFromNBT(tag.getCompoundTag("waterTank"));
    steamTank.readFromNBT(tag.getCompoundTag("steamTank"));
  }
  @Override
  public void onUpdate() {
    super.onUpdate();

    if (worldObj.isRemote) {
      updateSound();
    }

    if (isFormed()) {
      getReactor().simulate();

      if (!worldObj.isRemote
          && (getReactor().isBurning() != clientBurning
              || Math.abs(getReactor().getPlasmaTemp() - clientTemp) > 1000000)) {
        Mekanism.packetHandler.sendToAllAround(
            new TileEntityMessage(Coord4D.get(this), getNetworkedData(new ArrayList())),
            Coord4D.get(this).getTargetPoint(50D));
        clientBurning = getReactor().isBurning();
        clientTemp = getReactor().getPlasmaTemp();
      }
    }
  }
  @Override
  public ArrayList getNetworkedData(ArrayList data) {
    super.getNetworkedData(data);

    data.add(getReactor() != null && getReactor().isFormed());

    if (getReactor() != null) {
      data.add(getReactor().getPlasmaTemp());
      data.add(getReactor().getCaseTemp());
      data.add(getReactor().getInjectionRate());
      data.add(getReactor().isBurning());
      data.add(fuelTank.getStored());
      data.add(deuteriumTank.getStored());
      data.add(tritiumTank.getStored());
      data.add(waterTank.getCapacity());
      data.add(waterTank.getFluidAmount());
      data.add(steamTank.getCapacity());
      data.add(steamTank.getFluidAmount());
    }

    return data;
  }
  @Override
  public void writeToNBT(NBTTagCompound tag) {
    super.writeToNBT(tag);

    tag.setBoolean("formed", isFormed());

    if (isFormed()) {
      tag.setDouble("plasmaTemp", getReactor().getPlasmaTemp());
      tag.setDouble("caseTemp", getReactor().getCaseTemp());
      tag.setInteger("injectionRate", getReactor().getInjectionRate());
      tag.setBoolean("burning", getReactor().isBurning());
    } else {
      tag.setDouble("plasmaTemp", 0);
      tag.setDouble("caseTemp", 0);
      tag.setInteger("injectionRate", 0);
      tag.setBoolean("burning", false);
    }

    tag.setTag("fuelTank", fuelTank.write(new NBTTagCompound()));
    tag.setTag("deuteriumTank", deuteriumTank.write(new NBTTagCompound()));
    tag.setTag("tritiumTank", tritiumTank.write(new NBTTagCompound()));
    tag.setTag("waterTank", waterTank.writeToNBT(new NBTTagCompound()));
    tag.setTag("steamTank", steamTank.writeToNBT(new NBTTagCompound()));
  }
  @Override
  public void onAdded() {
    super.onAdded();

    formMultiblock(false);
  }
  @Override
  public void onChunkUnload() {
    super.onChunkUnload();

    formMultiblock(true);
  }