///// Multiblock Connection Base Logic
  @Override
  public Set<MultiblockControllerBase> attachToNeighbors() {
    Set<MultiblockControllerBase> controllers = null;
    MultiblockControllerBase bestController = null;

    // Look for a compatible controller in our neighboring parts.
    IMultiblockPart[] partsToCheck = getNeighboringParts();
    for (IMultiblockPart neighborPart : partsToCheck) {
      if (neighborPart.isConnected()) {
        MultiblockControllerBase candidate = neighborPart.getMultiblockController();
        if (!candidate.getClass().equals(this.getMultiblockControllerType())) {
          // Skip multiblocks with incompatible types
          continue;
        }

        if (controllers == null) {
          controllers = new HashSet<MultiblockControllerBase>();
          bestController = candidate;
        } else if (!controllers.contains(candidate) && candidate.shouldConsume(bestController)) {
          bestController = candidate;
        }

        controllers.add(candidate);
      }
    }

    // If we've located a valid neighboring controller, attach to it.
    if (bestController != null) {
      // attachBlock will call onAttached, which will set the controller.
      this.controller = bestController;
      bestController.attachBlock(this);
    }

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

    if (isMultiblockSaveDelegate() && isConnected()) {
      NBTTagCompound multiblockData = new NBTTagCompound();
      this.controller.writeToNBT(multiblockData);
      data.setTag("multiblockData", multiblockData);
    }
  }
  @Override
  public void readFromNBT(NBTTagCompound data) {
    super.readFromNBT(data);

    // We can't directly initialize a multiblock controller yet, so we cache the data here until
    // we receive a validate() call, which creates the controller and hands off the cached data.
    if (data.hasKey("multiblockData")) {
      this.cachedMultiblockData = data.getCompoundTag("multiblockData");
    }
  }
 /**
  * This is called when a block is being marked as valid by the chunk, but has not yet fully been
  * placed into the world's TileEntity cache. this.worldObj, xCoord, yCoord and zCoord have been
  * initialized, but any attempts to read data about the world can cause infinite loops - if you
  * call getTileEntity on this TileEntity's coordinate from within validate(), you will blow your
  * call stack.
  *
  * <p>TL;DR: Here there be dragons.
  *
  * @see net.minecraft.tileentity.TileEntity#validate()
  */
 @Override
 public void validate() {
   super.validate();
   MultiblockRegistry.onPartAdded(this.worldObj, this);
 }
 /**
  * Called from Minecraft's tile entity loop, after all tile entities have been ticked, as the
  * chunk in which this tile entity is contained is unloading. Happens before the Forge TickEnd
  * event.
  *
  * @see net.minecraft.tileentity.TileEntity#onChunkUnload()
  */
 @Override
 public void onChunkUnload() {
   super.onChunkUnload();
   detachSelf(true);
 }
 /**
  * Called when a block is removed by game actions, such as a player breaking the block or the
  * block being changed into another block.
  *
  * @see net.minecraft.tileentity.TileEntity#invalidate()
  */
 @Override
 public void invalidate() {
   super.invalidate();
   detachSelf(false);
 }