package buildcraft.transport.stripes; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import net.minecraft.block.Block; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; import net.minecraftforge.common.util.ForgeDirection; import buildcraft.BuildCraftTransport; import buildcraft.api.core.Position; import buildcraft.api.transport.IStripesActivator; import buildcraft.core.proxy.CoreProxy; import buildcraft.transport.Pipe; import buildcraft.transport.PipeTransportItems; import buildcraft.transport.TileGenericPipe; import buildcraft.transport.TravelingItem; import buildcraft.transport.utils.TransportUtils; public class PipeExtensionListener { private class PipeExtensionRequest { public ItemStack stack; public int x, y, z; public ForgeDirection o; public IStripesActivator h; } private final Map<World, HashSet<PipeExtensionRequest>> requests = new HashMap<World, HashSet<PipeExtensionRequest>>(); public void requestPipeExtension(ItemStack stack, World world, int x, int y, int z, ForgeDirection o, IStripesActivator h) { if (world.isRemote) { return; } if (!requests.containsKey(world)) { requests.put(world, new HashSet<PipeExtensionRequest>()); } PipeExtensionRequest r = new PipeExtensionRequest(); r.stack = stack; r.x = x; r.y = y; r.z = z; r.o = o; r.h = h; requests.get(world).add(r); } @SubscribeEvent public void tick(TickEvent.WorldTickEvent event) { if (event.phase == TickEvent.Phase.END && requests.containsKey(event.world)) { HashSet<PipeExtensionRequest> rSet = requests.get(event.world); World w = event.world; for (PipeExtensionRequest r : rSet) { Position target = new Position(r.x, r.y, r.z); target.orientation = r.o; boolean retract = r.stack.getItem() == BuildCraftTransport.pipeItemsVoid; ArrayList<ItemStack> removedPipeStacks = null; if (retract) { target.moveBackwards(1.0D); if (w.getBlock((int) target.x, (int) target.y, (int) target.z) != BuildCraftTransport.genericPipeBlock) { r.h.sendItem(r.stack, r.o.getOpposite()); continue; } target.moveBackwards(1.0D); if (w.getBlock((int) target.x, (int) target.y, (int) target.z) != BuildCraftTransport.genericPipeBlock) { r.h.sendItem(r.stack, r.o.getOpposite()); continue; } target.moveForwards(1.0D); } else { target.moveForwards(1.0D); if (!w.isAirBlock((int) target.x, (int) target.y, (int) target.z)) { r.h.sendItem(r.stack, r.o.getOpposite()); continue; } } // Step 1: Copy over and remove existing pipe Block oldBlock = w.getBlock(r.x, r.y, r.z); int oldMeta = w.getBlockMetadata(r.x, r.y, r.z); NBTTagCompound nbt = new NBTTagCompound(); w.getTileEntity(r.x, r.y, r.z).writeToNBT(nbt); w.setBlockToAir(r.x, r.y, r.z); boolean failedPlacement = false; // Step 2: If retracting, remove previous pipe; if extending, add new pipe if (retract) { removedPipeStacks = w.getBlock((int) target.x, (int) target.y, (int) target.z).getDrops(w, (int) target.x, (int) target.y, (int) target.z, w.getBlockMetadata((int) target.x, (int) target.y, (int) target.z), 0); w.setBlockToAir((int) target.x, (int) target.y, (int) target.z); } else { if (!r.stack.getItem().onItemUse(r.stack, CoreProxy.proxy.getBuildCraftPlayer((WorldServer) w, r.x, r.y, r.z).get(), w, r.x, r.y, r.z, 1, 0, 0, 0)) { failedPlacement = true; target.moveBackwards(1.0D); } } // Step 3: Place stripes pipe back // - Correct NBT coordinates nbt.setInteger("x", (int) target.x); nbt.setInteger("y", (int) target.y); nbt.setInteger("z", (int) target.z); // - Create block and tile TileGenericPipe pipeTile = (TileGenericPipe) TileEntity.createAndLoadEntity(nbt); w.setBlock((int) target.x, (int) target.y, (int) target.z, oldBlock, oldMeta, 3); w.setTileEntity((int) target.x, (int) target.y, (int) target.z, pipeTile); pipeTile.setWorldObj(w); pipeTile.validate(); pipeTile.updateEntity(); // Step 4: Hope for the best, clean up. PipeTransportItems items = (PipeTransportItems) pipeTile.pipe.transport; if (!retract && !failedPlacement) { r.stack.stackSize--; } if (r.stack.stackSize > 0) { sendItem(items, r.stack, r.o.getOpposite()); } if (removedPipeStacks != null) { for (ItemStack s : removedPipeStacks) { sendItem(items, s, r.o.getOpposite()); } } if (!retract && !failedPlacement) { TileGenericPipe newPipeTile = (TileGenericPipe) w.getTileEntity(r.x, r.y, r.z); newPipeTile.updateEntity(); pipeTile.scheduleNeighborChange(); if (pipeTile.getPipe() != null) { ((Pipe) pipeTile.getPipe()).scheduleWireUpdate(); } } } rSet.clear(); } } private void sendItem(PipeTransportItems transport, ItemStack itemStack, ForgeDirection direction) { TravelingItem newItem = TravelingItem.make( transport.container.xCoord + 0.5, transport.container.yCoord + TransportUtils.getPipeFloorOf(itemStack), transport.container.zCoord + 0.5, itemStack); transport.injectItem(newItem, direction); } }