Package crazypants.enderio.conduit

Source Code of crazypants.enderio.conduit.BlockConduitBundle

package crazypants.enderio.conduit;

import info.jbcs.minecraft.chisel.api.IFacade;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;

import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EffectRenderer;
import net.minecraft.client.particle.EntityDiggingFX;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.IIcon;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.tools.IToolWrench;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Optional;
import cpw.mods.fml.common.network.IGuiHandler;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import crazypants.enderio.BlockEio;
import crazypants.enderio.EnderIO;
import crazypants.enderio.GuiHandler;
import crazypants.enderio.ModObject;
import crazypants.enderio.conduit.geom.CollidableComponent;
import crazypants.enderio.conduit.geom.ConduitConnectorType;
import crazypants.enderio.conduit.gui.ExternalConnectionContainer;
import crazypants.enderio.conduit.gui.GuiExternalConnection;
import crazypants.enderio.conduit.gui.GuiExternalConnectionSelector;
import crazypants.enderio.conduit.gui.PacketFluidFilter;
import crazypants.enderio.conduit.gui.PacketOpenConduitUI;
import crazypants.enderio.conduit.gui.item.PacketExistingItemFilterSnapshot;
import crazypants.enderio.conduit.gui.item.PacketModItemFilter;
import crazypants.enderio.conduit.liquid.PacketFluidLevel;
import crazypants.enderio.conduit.packet.PacketConnectionMode;
import crazypants.enderio.conduit.packet.PacketExtractMode;
import crazypants.enderio.conduit.packet.PacketItemConduitFilter;
import crazypants.enderio.conduit.packet.PacketRedstoneConduitSignalColor;
import crazypants.enderio.conduit.redstone.IRedstoneConduit;
import crazypants.enderio.item.ItemConduitProbe;
import crazypants.enderio.machine.painter.PainterUtil;
import crazypants.enderio.network.PacketHandler;
import crazypants.render.BoundingBox;
import crazypants.util.Util;
import powercrystals.minefactoryreloaded.api.rednet.IRedNetOmniNode;
import powercrystals.minefactoryreloaded.api.rednet.connectivity.RedNetConnectionType;

@Optional.Interface(iface = "powercrystals.minefactoryreloaded.api.rednet.IRedNetOmniNode", modid = "MineFactoryReloaded")
public class BlockConduitBundle extends BlockEio implements IGuiHandler, IFacade, IRedNetOmniNode {

  private static final String KEY_CONNECTOR_ICON = "enderIO:conduitConnector";

  public static BlockConduitBundle create() {

    MinecraftForge.EVENT_BUS.register(ConduitNetworkTickHandler.instance);
    FMLCommonHandler.instance().bus().register(ConduitNetworkTickHandler.instance);

    PacketHandler.INSTANCE.registerMessage(PacketFluidLevel.class, PacketFluidLevel.class, PacketHandler.nextID(), Side.CLIENT);
    PacketHandler.INSTANCE.registerMessage(PacketExtractMode.class, PacketExtractMode.class, PacketHandler.nextID(), Side.SERVER);
    PacketHandler.INSTANCE.registerMessage(PacketConnectionMode.class, PacketConnectionMode.class, PacketHandler.nextID(), Side.SERVER);
    PacketHandler.INSTANCE.registerMessage(PacketItemConduitFilter.class, PacketItemConduitFilter.class, PacketHandler.nextID(), Side.SERVER);
    PacketHandler.INSTANCE.registerMessage(PacketExistingItemFilterSnapshot.class, PacketExistingItemFilterSnapshot.class, PacketHandler.nextID(), Side.SERVER);
    PacketHandler.INSTANCE.registerMessage(PacketModItemFilter.class, PacketModItemFilter.class, PacketHandler.nextID(), Side.SERVER);
    PacketHandler.INSTANCE.registerMessage(PacketFluidFilter.class, PacketFluidFilter.class, PacketHandler.nextID(), Side.SERVER);
    PacketHandler.INSTANCE.registerMessage(PacketRedstoneConduitSignalColor.class, PacketRedstoneConduitSignalColor.class, PacketHandler.nextID(), Side.SERVER);
    PacketHandler.INSTANCE.registerMessage(PacketOpenConduitUI.class, PacketOpenConduitUI.class, PacketHandler.nextID(), Side.SERVER);

    BlockConduitBundle result = new BlockConduitBundle();
    result.init();
    return result;
  }

  public static int rendererId = -1;

  private IIcon connectorIcon;

  private IIcon lastRemovedComponetIcon = null;

  private Random rand = new Random();

  protected BlockConduitBundle() {
    super(ModObject.blockConduitBundle.unlocalisedName, TileConduitBundle.class);
    setBlockBounds(0.334f, 0.334f, 0.334f, 0.667f, 0.667f, 0.667f);
    setCreativeTab(null);
  }

  @SideOnly(Side.CLIENT)
  @Override
  public boolean addHitEffects(World world, MovingObjectPosition target,
      EffectRenderer effectRenderer) {
    IIcon tex = null;

    TileConduitBundle cb = (TileConduitBundle)
        world.getTileEntity(target.blockX, target.blockY, target.blockZ);
    if(ConduitUtil.isSolidFacadeRendered(cb, Minecraft.getMinecraft().thePlayer)) {
      if(cb.getFacadeId() != null) {
        tex = cb.getFacadeId().getIcon(target.sideHit,
            cb.getFacadeMetadata());
      }
    } else if(target.hitInfo instanceof CollidableComponent) {
      CollidableComponent cc = (CollidableComponent) target.hitInfo;
      IConduit con = cb.getConduit(cc.conduitType);
      if(con != null) {
        tex = con.getTextureForState(cc);
      }
    }
    if(tex == null) {
      tex = blockIcon;
    }
    lastRemovedComponetIcon = tex;
    addBlockHitEffects(world, effectRenderer, target.blockX, target.blockY,
        target.blockZ, target.sideHit, tex);
    return true;
  }

  @Override
  @SideOnly(Side.CLIENT)
  public boolean addDestroyEffects(World world, int x, int y, int z, int
      meta, EffectRenderer effectRenderer) {
    IIcon tex = lastRemovedComponetIcon;
    byte b0 = 4;
    for (int j1 = 0; j1 < b0; ++j1) {
      for (int k1 = 0; k1 < b0; ++k1) {
        for (int l1 = 0; l1 < b0; ++l1) {
          double d0 = x + (j1 + 0.5D) / b0;
          double d1 = y + (k1 + 0.5D) / b0;
          double d2 = z + (l1 + 0.5D) / b0;
          int i2 = this.rand.nextInt(6);
          EntityDiggingFX fx = new EntityDiggingFX(world, d0, d1, d2, d0 - x - 0.5D,
              d1 - y - 0.5D, d2 - z - 0.5D, this, i2, 0).applyColourMultiplier(x, y, z);
          fx.setParticleIcon(tex);
          effectRenderer.addEffect(fx);
        }
      }
    }
    return true;

  }

  @SideOnly(Side.CLIENT)
  private void addBlockHitEffects(World world, EffectRenderer effectRenderer,
      int x, int y, int z, int side, IIcon tex) {
    float f = 0.1F;
    double d0 = x + rand.nextDouble() * (getBlockBoundsMaxX() -
        getBlockBoundsMinX() - f * 2.0F) + f + getBlockBoundsMinX();
    double d1 = y + rand.nextDouble() * (getBlockBoundsMaxY() -
        getBlockBoundsMinY() - f * 2.0F) + f + getBlockBoundsMinY();
    double d2 = z + rand.nextDouble() * (getBlockBoundsMaxZ() -
        getBlockBoundsMinZ() - f * 2.0F) + f + getBlockBoundsMinZ();
    if(side == 0) {
      d1 = y + getBlockBoundsMinY() - f;
    } else if(side == 1) {
      d1 = y + getBlockBoundsMaxY() + f;
    } else if(side == 2) {
      d2 = z + getBlockBoundsMinZ() - f;
    } else if(side == 3) {
      d2 = z + getBlockBoundsMaxZ() + f;
    } else if(side == 4) {
      d0 = x + getBlockBoundsMinX() - f;
    } else if(side == 5) {
      d0 = x + getBlockBoundsMaxX() + f;
    }
    EntityDiggingFX digFX = new EntityDiggingFX(world, d0, d1, d2, 0.0D, 0.0D,
        0.0D, this, side, 0);
    digFX.applyColourMultiplier(x, y,
        z).multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F);
    digFX.setParticleIcon(tex);
    effectRenderer.addEffect(digFX);
  }

  @Override
  protected void init() {
    super.init();
    for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
      EnderIO.guiHandler.registerGuiHandler(GuiHandler.GUI_ID_EXTERNAL_CONNECTION_BASE + dir.ordinal(), this);
    }
    EnderIO.guiHandler.registerGuiHandler(GuiHandler.GUI_ID_EXTERNAL_CONNECTION_SELECTOR, this);
  }

  @Override
  public ItemStack getPickBlock(MovingObjectPosition target, World world, int
      x, int y, int z) {
    if(target != null && target.hitInfo instanceof CollidableComponent) {
      CollidableComponent cc = (CollidableComponent) target.hitInfo;
      TileConduitBundle bundle = (TileConduitBundle) world.getTileEntity(x,
          y, z);
      IConduit conduit = bundle.getConduit(cc.conduitType);
      if(conduit != null) {
        return conduit.createItem();
      } else if(cc.conduitType == null && bundle.getFacadeId() != null) {
        // use the facde
        ItemStack fac = new ItemStack(EnderIO.itemConduitFacade, 1, 0);
        PainterUtil.setSourceBlock(fac, bundle.getFacadeId(),
            bundle.getFacadeMetadata());
        return fac;
      }
    }
    return null;
  }

  @Override
  public int getDamageValue(World world, int x, int y, int z) {
    TileEntity te = world.getTileEntity(x, y, z);
    if(!(te instanceof IConduitBundle)) {
      return 0;
    }
    IConduitBundle bun = (IConduitBundle) te;
    return bun.getFacadeId() != null ? bun.getFacadeMetadata() : 0;
  }

  @Override
  public int quantityDropped(Random r) {
    return 0;
  }

  public IIcon getConnectorIcon() {
    return connectorIcon;
  }

  @Override
  public void registerBlockIcons(IIconRegister IIconRegister) {
    connectorIcon = IIconRegister.registerIcon(KEY_CONNECTOR_ICON);
    blockIcon = connectorIcon;
  }

  @Override
  public boolean isSideSolid(IBlockAccess world, int x, int y, int z,
      ForgeDirection side) {
    TileEntity te = world.getTileEntity(x, y, z);
    if(!(te instanceof IConduitBundle)) {
      return false;
    }
    IConduitBundle con = (IConduitBundle) te;
    if(con.getFacadeId() != null) {
      return true;
    }
    return false;
  }

  @Override
  public boolean isOpaqueCube() {
    return false;
  }

  @Override
  public int getRenderType() {
    return rendererId;
  }

  @Override
  public boolean renderAsNormalBlock() {
    return false;
  }

  @Override
  public int getLightOpacity(IBlockAccess world, int x, int y, int z) {
    TileEntity te = world.getTileEntity(x, y, z);
    if(!(te instanceof IConduitBundle)) {
      return super.getLightOpacity(world, x, y, z);
    }
    IConduitBundle con = (IConduitBundle) te;
    return con.getLightOpacity();
  }

  @Override
  public int getLightValue(IBlockAccess world, int x, int y, int z) {
    TileEntity te = world.getTileEntity(x, y, z);
    if(!(te instanceof IConduitBundle)) {
      return super.getLightValue(world, x, y, z);
    }
    IConduitBundle con = (IConduitBundle) te;
    if(con.getFacadeId() != null) {
      return 0;
    }
    Collection<IConduit> conduits = con.getConduits();
    int result = 0;
    for (IConduit conduit : conduits) {
      result += conduit.getLightValue();
    }
    return result;
  }

  @Override
  public int isProvidingStrongPower(IBlockAccess world, int x, int y, int z,
      int par5) {
    IRedstoneConduit con = getRedstoneConduit(world, x, y, z);
    if(con == null) {
      return 0;
    }
    return con.isProvidingStrongPower(ForgeDirection.getOrientation(par5));
  }

  @Override
  public int isProvidingWeakPower(IBlockAccess world, int x, int y, int z,
      int par5) {
    IRedstoneConduit con = getRedstoneConduit(world, x, y, z);
    if(con == null) {
      return 0;
    }

    return con.isProvidingWeakPower(ForgeDirection.getOrientation(par5));
  }

  @Override
  public boolean canProvidePower() {
    return true;
  }

  @Override
  public boolean removedByPlayer(World world, EntityPlayer player, int x,
      int y, int z) {
    IConduitBundle te = (IConduitBundle) world.getTileEntity(x, y, z);
    if(te == null) {
      return true;
    }

    boolean breakBlock = true;
    List<ItemStack> drop = new ArrayList<ItemStack>();
    if(ConduitUtil.isSolidFacadeRendered(te, player)) {
      breakBlock = false;
      ItemStack fac = new ItemStack(EnderIO.itemConduitFacade, 1, 0);
      PainterUtil.setSourceBlock(fac, te.getFacadeId(), te.getFacadeMetadata());
      drop.add(fac);
      te.setFacadeId(null);
      te.setFacadeMetadata(0);
    }

    if(breakBlock) {
      List<RaytraceResult> results = doRayTraceAll(world, x, y, z, player);
      RaytraceResult.sort(Util.getEyePosition(player), results);
      for (RaytraceResult rt : results) {
        if(breakConduit(te, drop, rt, player)) {
          break;
        }
      }
    }

    breakBlock = te.getConduits().isEmpty() && !te.hasFacade();

    if(!world.isRemote && !player.capabilities.isCreativeMode) {
      for (ItemStack st : drop) {
        Util.dropItems(world, st, x, y, z, false);
      }
    }

    if(!breakBlock) {
      world.markBlockForUpdate(x, y, z);
      return false;
    }
    world.setBlockToAir(x, y, z);
    return true;
  }

  private boolean breakConduit(IConduitBundle te, List<ItemStack> drop, RaytraceResult rt, EntityPlayer player) {
    if(rt == null || rt.component == null) {
      return false;
    }
    Class<? extends IConduit> type = rt.component.conduitType;
    if(!ConduitUtil.renderConduit(player, type)) {
      return false;
    }

    if(type == null) {
      // broke a conector so drop any conduits with no connections as there
      // is no other way to remove these
      List<IConduit> cons = new ArrayList<IConduit>(te.getConduits());
      boolean droppedUnconected = false;
      for (IConduit con : cons) {
        if(con.getConduitConnections().isEmpty() &&
            con.getExternalConnections().isEmpty() && ConduitUtil.renderConduit(player, con)) {
          te.removeConduit(con);
          drop.addAll(con.getDrops());
          droppedUnconected = true;
        }
      }
      // If there isn't, then drop em all
      if(!droppedUnconected) {
        for (IConduit con : cons) {
          if(ConduitUtil.renderConduit(player, con)) {
            te.removeConduit(con);
            drop.addAll(con.getDrops());
          }
        }
      }
    } else {
      IConduit con = te.getConduit(type);
      if(con != null) {
        te.removeConduit(con);
        drop.addAll(con.getDrops());
      }
    }

    return true;
  }

  @Override
  public void breakBlock(World world, int x, int y, int z, Block par5, int par6) {

    TileEntity tile = world.getTileEntity(x, y, z);
    if(!(tile instanceof IConduitBundle)) {
      return;
    }
    IConduitBundle te = (IConduitBundle) tile;
    if(te != null) {
      te.onBlockRemoved();
    }
    world.removeTileEntity(x, y, z);
  }
 
  public void onBlockClicked(World world, int x, int y, int z, EntityPlayer player) {
    ItemStack equipped = player.getCurrentEquippedItem();
    if(!player.isSneaking() || equipped == null || equipped.getItem() != EnderIO.itemYetaWench) {
      return;
    }
    ConduitUtil.openConduitGui(world, x, y, z, player);
  }

  @Override
  public boolean onBlockActivated(World world, int x, int y, int z,
      EntityPlayer player, int par6, float par7, float par8, float par9) {

    IConduitBundle bundle = (IConduitBundle) world.getTileEntity(x, y, z);
    if(bundle == null) {
      return false;
    }

    ItemStack stack = player.getCurrentEquippedItem();
    if(stack != null && stack.getItem() == EnderIO.itemConduitFacade && !bundle.hasFacade()) {
      //add facade
      return handleFacadeClick(world, x, y, z, player, bundle, stack);

    } else if(ConduitUtil.isConduitEquipped(player)) {
     // Add conduit
      if(player.isSneaking()) {
        return false;
      }
      if(handleConduitClick(world, x, y, z, player, bundle, stack)) {
        return true;
      }

    } else if(ConduitUtil.isProbeEquipped(player)) {
      //Handle copy / paste of settings
      if(handleConduitProbeClick(world, x, y, z, player, bundle, stack)) {
        return true;
      }
    } else if(ConduitUtil.isToolEquipped(player) && player.isSneaking()) {
       // Break conduit with tool
      if(handleWrenchClick(world, x, y, z, player)) {
        return true;
      }
    }

    // Check conduit defined actions
    RaytraceResult closest = doRayTrace(world, x, y, z, player);
    List<RaytraceResult> all = null;
    if(closest != null) {
      all = doRayTraceAll(world, x, y, z, player);
    }

    if(closest != null && closest.component != null && closest.component.data instanceof
        ConduitConnectorType) {

      ConduitConnectorType conType = (ConduitConnectorType) closest.component.data;
      if(conType == ConduitConnectorType.INTERNAL) {
        boolean result = false;
        // if its a connector pass the event on to all conduits
        for (IConduit con : bundle.getConduits()) {
          if(ConduitUtil.renderConduit(player, con.getCollidableType())
              && con.onBlockActivated(player, getHitForConduitType(all, con.getCollidableType()), all)) {
            bundle.getEntity().markDirty();
            result = true;
          }

        }
        if(result) {
          return true;
        }
      } else {
        if(!world.isRemote) {
          player.openGui(EnderIO.instance, GuiHandler.GUI_ID_EXTERNAL_CONNECTION_BASE + closest.component.dir.ordinal(), world, x, y, z);
        }
        return true;
      }
    }

    if(closest == null || closest.component == null || closest.component.conduitType ==
        null && all == null) {
      // Nothing of interest hit
      return false;
    }

    // Conduit specific actions
    if(all != null) {
      RaytraceResult.sort(Util.getEyePosition(player), all);
      for (RaytraceResult rr : all) {
        if(ConduitUtil.renderConduit(player, rr.component.conduitType) && !(rr.component.data instanceof
            ConduitConnectorType)) {

          IConduit con = bundle.getConduit(rr.component.conduitType);
          if(con != null && con.onBlockActivated(player,
              rr, all)) {
            bundle.getEntity().markDirty();
            return true;
          }
        }
      }
    } else {
      IConduit closestConduit = bundle.getConduit(closest.component.conduitType);
      if(closestConduit != null && ConduitUtil.renderConduit(player, closestConduit) && closestConduit.onBlockActivated(player,
          closest, all)) {
        bundle.getEntity().markDirty();
        return true;
      }
    }
    return false;

  }

  private boolean handleWrenchClick(World world, int x, int y, int z, EntityPlayer player) {
    if(player.getCurrentEquippedItem().getItem() instanceof IToolWrench) {                       
      IToolWrench wrench = (IToolWrench) player.getCurrentEquippedItem().getItem();
      if(wrench.canWrench(player, x, y, z)) {
        if(!world.isRemote) {
          removedByPlayer(world, player, x, y, z);
          if(player.getCurrentEquippedItem().getItem() instanceof IToolWrench) {
            ((IToolWrench) player.getCurrentEquippedItem().getItem()).wrenchUsed(player, x, y, z);
          }
        }
        return true;
      }
    }
    return false;
  }

  private boolean handleConduitProbeClick(World world, int x, int y, int z, EntityPlayer player, IConduitBundle bundle, ItemStack stack) {  
    if(stack.getItemDamage() != 1) {
      return false; //not in copy paste mode
    }   
    RaytraceResult rr = doRayTrace(world, x, y, z, player);
    if(rr == null || rr.component == null) {
      return false;
    }       
    return ItemConduitProbe.copyPasteSettings(player, stack, bundle, rr.component.dir);
  }

  private boolean handleConduitClick(World world, int x, int y, int z, EntityPlayer player, IConduitBundle bundle, ItemStack stack) {
    IConduitItem equipped = (IConduitItem) stack.getItem();
    if(!bundle.hasType(equipped.getBaseConduitType())) {
      bundle.addConduit(equipped.createConduit(stack));
      if(!player.capabilities.isCreativeMode) {
        world.playSoundEffect(x + 0.5F, y + 0.5F, z + 0.5F, stepSound.getStepResourcePath(),
            (stepSound.getVolume() + 1.0F) / 2.0F, stepSound.getPitch() * 0.8F);
        player.getCurrentEquippedItem().stackSize--;
      }
      return true;
    }
    return false;
  }

  private boolean handleFacadeClick(World world, int x, int y, int z, EntityPlayer player, IConduitBundle bundle, ItemStack stack) {
    // Add facade
    if(player.isSneaking()) {
      return false;
    }

    if(PainterUtil.getSourceBlock(player.getCurrentEquippedItem()) == null) {
      return false;
    }

    bundle.setFacadeId(PainterUtil.getSourceBlock(player.getCurrentEquippedItem()));
    bundle.setFacadeMetadata(PainterUtil.getSourceBlockMetadata(player.getCurrentEquippedItem()));
    if(!player.capabilities.isCreativeMode) {
      stack.stackSize--;
    }
    world.markBlockForUpdate(x, y, z);
    bundle.getEntity().markDirty();
    return true;
  }

  @Override
  public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) {
    if(id == GuiHandler.GUI_ID_EXTERNAL_CONNECTION_SELECTOR) {
      return null;
    }
    // The server needs the container as it manages the adding and removing of
    // items, which are then sent to the client for display
    TileEntity te = world.getTileEntity(x, y, z);
    if(te instanceof IConduitBundle) {
      return new ExternalConnectionContainer(player.inventory, (IConduitBundle) te, ForgeDirection.values()[id - GuiHandler.GUI_ID_EXTERNAL_CONNECTION_BASE]);
    }
    return null;
  }

  @Override
  public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) {
    TileEntity te = world.getTileEntity(x, y, z);
    if(te instanceof IConduitBundle) {
      if(id == GuiHandler.GUI_ID_EXTERNAL_CONNECTION_SELECTOR) {
        return new GuiExternalConnectionSelector((IConduitBundle) te);
      }
      return new GuiExternalConnection(player.inventory, (IConduitBundle) te, ForgeDirection.values()[id - GuiHandler.GUI_ID_EXTERNAL_CONNECTION_BASE]);
    }
    return null;
  }

  private RaytraceResult getHitForConduitType(List<RaytraceResult> all, Class<? extends IConduit> collidableType) {
    for (RaytraceResult rr : all) {
      if(rr.component != null && rr.component.conduitType == collidableType) {
        return rr;
      }
    }
    return null;
  }

  @Override
  public void onNeighborBlockChange(World world, int x, int y, int z, Block
      blockId) {
    TileEntity tile = world.getTileEntity(x, y, z);
    if((tile instanceof IConduitBundle)) {
      ((IConduitBundle) tile).onNeighborBlockChange(blockId);
    }
  }

  @Override
  public void onNeighborChange(IBlockAccess world, int x, int y, int z, int tileX, int tileY, int tileZ) {   
    TileEntity conduit = world.getTileEntity(x, y, z);
    if(conduit instanceof IConduitBundle) {
      ((IConduitBundle) conduit).onNeighborChange(world, x, y, z, tileX, tileY, tileZ);
    }
  }

  @Override
  public void addCollisionBoxesToList(World world, int x, int y, int z,
      AxisAlignedBB axisalignedbb, @SuppressWarnings("rawtypes") List arraylist,
      Entity par7Entity) {

    TileEntity te = world.getTileEntity(x, y, z);
    if(!(te instanceof IConduitBundle)) {
      return;
    }
    IConduitBundle con = (IConduitBundle) te;
    if(con.getFacadeId() != null) {
      setBlockBounds(0, 0, 0, 1, 1, 1);
      super.addCollisionBoxesToList(world, x, y, z, axisalignedbb, arraylist,
          par7Entity);
    } else {

      Collection<CollidableComponent> bounds = con.getCollidableComponents();
      for (CollidableComponent bnd : bounds) {
        setBlockBounds(bnd.bound.minX, bnd.bound.minY, bnd.bound.minZ,
            bnd.bound.maxX, bnd.bound.maxY, bnd.bound.maxZ);
        super.addCollisionBoxesToList(world, x, y, z, axisalignedbb, arraylist,
            par7Entity);
      }

      if(con.getConduits().isEmpty()) { // just in case
        setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
        super.addCollisionBoxesToList(world, x, y, z, axisalignedbb, arraylist,
            par7Entity);
      }
    }

    setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);

  }

  @Override
  public AxisAlignedBB getSelectedBoundingBoxFromPool(World world, int x, int
      y, int z) {

    TileEntity te = world.getTileEntity(x, y, z);
    if(!(te instanceof IConduitBundle)) {
      return null;
    }
    IConduitBundle con = (IConduitBundle) te;

    BoundingBox minBB = new BoundingBox(1, 1, 1, 0, 0, 0);
    if(!ConduitUtil.isSolidFacadeRendered(con, EnderIO.proxy.getClientPlayer())) {

      Collection<CollidableComponent> bounds = con.getCollidableComponents();
      for (CollidableComponent bnd : bounds) {
        minBB = minBB.expandBy(bnd.bound);
      }

    } else {
      minBB = new BoundingBox(0, 0, 0, 1, 1, 1);
    }

    if(!minBB.isValid()) {
      minBB = new BoundingBox(0, 0, 0, 1, 1, 1);
    }

    return AxisAlignedBB.getBoundingBox(x + minBB.minX, y + minBB.minY,
        z + minBB.minZ, x + minBB.maxX, y + minBB.maxY, z +
            minBB.maxZ);
  }

  @Override
  public MovingObjectPosition collisionRayTrace(World world, int x, int y,
      int z, Vec3 origin, Vec3 direction) {
    RaytraceResult raytraceResult = doRayTrace(world, x, y, z, origin,
        direction, null);
    if(raytraceResult == null) {
      return null;
    }

    if(raytraceResult.movingObjectPosition != null) {
      raytraceResult.movingObjectPosition.hitInfo = raytraceResult.component;

    }
    return raytraceResult.movingObjectPosition;
  }

  public RaytraceResult doRayTrace(World world, int x, int y, int z,
      EntityPlayer entityPlayer) {
    List<RaytraceResult> allHits = doRayTraceAll(world, x, y, z, entityPlayer);
    if(allHits == null) {
      return null;
    }
    Vec3 origin = Util.getEyePosition(entityPlayer);
    return RaytraceResult.getClosestHit(origin, allHits);
  }

  public List<RaytraceResult> doRayTraceAll(World world, int x, int y, int z,
      EntityPlayer entityPlayer) {
    double pitch = Math.toRadians(entityPlayer.rotationPitch);
    double yaw = Math.toRadians(entityPlayer.rotationYaw);

    double dirX = -Math.sin(yaw) * Math.cos(pitch);
    double dirY = -Math.sin(pitch);
    double dirZ = Math.cos(yaw) * Math.cos(pitch);

    double reachDistance = EnderIO.proxy.getReachDistanceForPlayer(entityPlayer);

    Vec3 origin = Util.getEyePosition(entityPlayer);
    Vec3 direction = origin.addVector(dirX * reachDistance, dirY *
        reachDistance, dirZ * reachDistance);
    return doRayTraceAll(world, x, y, z, origin, direction,
        entityPlayer);
  }

  private RaytraceResult doRayTrace(World world, int x, int y, int z, Vec3 origin, Vec3 direction, EntityPlayer entityPlayer) {
    List<RaytraceResult> allHits = doRayTraceAll(world, x, y, z, origin, direction, entityPlayer);
    if(allHits == null) {
      return null;
    }
    return RaytraceResult.getClosestHit(origin, allHits);
  }

  protected List<RaytraceResult> doRayTraceAll(World world, int x, int y, int z, Vec3
      origin, Vec3 direction, EntityPlayer player) {

    TileEntity te = world.getTileEntity(x, y, z);
    if(!(te instanceof IConduitBundle)) {
      return null;
    }
    IConduitBundle bundle = (IConduitBundle) te;
    List<RaytraceResult> hits = new ArrayList<RaytraceResult>();

    if(ConduitUtil.isSolidFacadeRendered(bundle, player)) {
      setBlockBounds(0, 0, 0, 1, 1, 1);
      MovingObjectPosition hitPos = super.collisionRayTrace(world, x, y, z,
          origin, direction);
      if(hitPos != null) {
        hits.add(new RaytraceResult(new CollidableComponent(null,
            BoundingBox.UNIT_CUBE, ForgeDirection.UNKNOWN, null), hitPos));
      }
    } else {

      Collection<CollidableComponent> components =
          new ArrayList<CollidableComponent>(bundle.getCollidableComponents());
      for (CollidableComponent component : components) {
        setBlockBounds(component.bound.minX, component.bound.minY,
            component.bound.minZ, component.bound.maxX, component.bound.maxY,
            component.bound.maxZ);
        MovingObjectPosition hitPos = super.collisionRayTrace(world, x, y, z,
            origin, direction);
        if(hitPos != null) {
          hits.add(new RaytraceResult(component, hitPos));
        }
      }

      // safety to prevent unbreakable empty bundles in case of a bug
      if(bundle.getConduits().isEmpty() && !ConduitUtil.isFacadeHidden(bundle,
          player)) {
        setBlockBounds(0, 0, 0, 1, 1, 1);
        MovingObjectPosition hitPos = super.collisionRayTrace(world, x, y, z,
            origin, direction);
        if(hitPos != null) {
          hits.add(new RaytraceResult(null, hitPos));
        }
      }
    }

    setBlockBounds(0, 0, 0, 1, 1, 1);

    return hits;
  }

  @Override
  public int getFacadeMetadata(IBlockAccess world, int x, int y, int z, int side) {
    TileEntity te = world.getTileEntity(x, y, z);
    if(!(te instanceof IConduitBundle)) {
      return 0;
    }
    IConduitBundle cb = (IConduitBundle)te;
    return cb.getFacadeMetadata();
  }

  @Override
  public Block getFacade(IBlockAccess world, int x, int y, int z, int side) {
    TileEntity te = world.getTileEntity(x, y, z);
    if(!(te instanceof IConduitBundle)) {
      return this;
    }
    IConduitBundle cb = (IConduitBundle)te;
    Block res = cb.getFacadeId();
    if(res == null) {
      return this;
    }
    return res;
  }

  @Override
  public void onInputsChanged(World world, int x, int y, int z, ForgeDirection side, int[] inputValues) {
    IRedstoneConduit conduit = getRedstoneConduit(world, x, y, z);
    if(conduit == null) {
      return;
    }

    conduit.onInputsChanged(world, x, y, z, side, inputValues);
  }

  @Override
  public void onInputChanged(World world, int x, int y, int z, ForgeDirection side, int inputValue) {
    // Unused because only called in "Single" mode.
  }

  @Override
  public int[] getOutputValues(World world, int x, int y, int z, ForgeDirection side) {
    IRedstoneConduit conduit = getRedstoneConduit(world, x, y, z);
    if(conduit == null) {
      return null;
    }

    return conduit.getOutputValues(world, x, y, z, side);
  }

  @Override
  public int getOutputValue(World world, int x, int y, int z, ForgeDirection side, int subnet) {
    IRedstoneConduit conduit = getRedstoneConduit(world, x, y, z);
    if(conduit == null) {
      return 0;
    }

    return conduit.getOutputValue(world, x, y, z, side, subnet);
  }

  @Override
  @Optional.Method(modid = "MineFactoryReloaded")
  public RedNetConnectionType getConnectionType(World world, int x, int y, int z, ForgeDirection side) {
    IRedstoneConduit conduit = getRedstoneConduit(world, x, y, z);
    if(conduit == null) {
      return RedNetConnectionType.None;
    }
    return conduit.canConnectToExternal(side, false) ? RedNetConnectionType.CableAll : RedNetConnectionType.None;
  }

  private static IRedstoneConduit getRedstoneConduit(IBlockAccess world, int x, int y, int z) {
    TileEntity te = world.getTileEntity(x, y, z);
    if(!(te instanceof IConduitBundle)) {
      return null;
    }
    IConduitBundle bundle = (IConduitBundle) te;
    return bundle.getConduit(IRedstoneConduit.class);
  }
}
TOP

Related Classes of crazypants.enderio.conduit.BlockConduitBundle

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.