CVE-2023-38689: Deserialization of Untrusted Data (CWE-502)
value: Logistics Pipes is a modification (a.k.a. mod) for the computer game Minecraft Java Edition. The mod used Java's `ObjectInputStream#readObject` on untrusted data coming from clients or servers over the network resulting in possible remote code execution when sending specifically crafted network packets after connecting. The affected versions were released between 2013 and 2016 and the issue (back then unknown) was fixed in 2016 by a refactoring of the network IO code.  
The issue is present in all Logistics Pipes versions ranged from 0.7.0.91 prior to 0.10.0.71, which were downloaded from different platforms summing up to multi-million downloads. For Minecraft version 1.7.10 the issue was fixed in build 0.10.0.71. Everybody on Minecraft 1.7.10 should check their version number of Logistics Pipes in their modlist and update, if the version number is smaller than 0.10.0.71. Any newer supported Minecraft version (like 1.12.2) never had a Logistics Pipes version with vulnerable code. The best available workaround for vulnerable versions is to play in singleplayer only or update to newer Minecraft versions and modpacks.
CWE description: The product deserializes untrusted data without sufficiently verifying that the resulting data will be valid.
CVSS v3 base score: 9.8
Published: 2023-08-04T17:15Z
Repository: https://github.com/RS485/LogisticsPipes
Language: Java
Files changed: common/logisticspipes/gui/GuiCraftingPipe.java, common/logisticspipes/items/ItemUpgrade.java, common/logisticspipes/logic/BaseLogicCrafting.java, common/logisticspipes/logistics/LogisticsLiquidManager.java, common/logisticspipes/nei/DebugHelper.java, common/logisticspipes/network/ClientPacketHandler.java, common/logisticspipes/network/GuiHandler.java, common/logisticspipes/network/NetworkConstants.java, common/logisticspipes/network/ServerPacketHandler.java, common/logisticspipes/network/packets/GuiArgumentPacket.java, common/logisticspipes/pipes/PipeItemsCraftingLogistics.java, common/logisticspipes/pipes/PipeLiquidProvider.java, common/logisticspipes/pipes/upgrades/AdvancedSatelliteUpgrade.java, common/logisticspipes/pipes/upgrades/ConnectionUpgrade.java, common/logisticspipes/pipes/upgrades/IPipeUpgrade.java, common/logisticspipes/pipes/upgrades/SneakyUpgrade.java, common/logisticspipes/pipes/upgrades/SpeedUpgrade.java, common/logisticspipes/pipes/upgrades/SplitCraftingCrafterUpgrade.java, common/logisticspipes/pipes/upgrades/SplitCraftingSatelliteUpgrade.java, common/logisticspipes/pipes/upgrades/UpgradeManager.java, common/logisticspipes/utils/gui/BasicGuiHelper.java
Commit date: 2013-02-24 16:44:08 +0100
Commit message: Added AdvancedSatellite Upgrade.

Diff: diff --git a/common/logisticspipes/gui/GuiCraftingPipe.java b/common/logisticspipes/gui/GuiCraftingPipe.java
index 9b01fca2..876558e7 100644
--- a/common/logisticspipes/gui/GuiCraftingPipe.java
+++ b/common/logisticspipes/gui/GuiCraftingPipe.java
@@ -9,81 +9,120 @@
 package logisticspipes.gui;
 
 import logisticspipes.interfaces.IGuiIDHandlerProvider;
 import logisticspipes.logic.BaseLogicCrafting;
 import logisticspipes.network.GuiIDs;
+import logisticspipes.utils.gui.BasicGuiHelper;
 import logisticspipes.utils.gui.DummyContainer;
 import logisticspipes.utils.gui.SmallGuiButton;
 import net.minecraft.client.gui.GuiButton;
 import net.minecraft.client.gui.inventory.GuiContainer;
 import net.minecraft.entity.player.EntityPlayer;
 import net.minecraft.inventory.IInventory;
 import net.minecraft.inventory.Slot;
 
-import org.lwjgl.opengl.GL11;
-
 public class GuiCraftingPipe extends GuiContainer implements IGuiIDHandlerProvider {
 
 	private final BaseLogicCrafting _logic;
 	private final EntityPlayer _player;
 	private final GuiButton[] buttonarray;
+	private final GuiButton[] normalButtonArray;
+	private final GuiButton[][] advancedSatButtonArray;
+	private final boolean isAdvancedSat;
+	private final boolean isSplitedCrafting;
 	
-	public GuiCraftingPipe(EntityPlayer player, IInventory dummyInventory, BaseLogicCrafting logic) {
+	public GuiCraftingPipe(EntityPlayer player, IInventory dummyInventory, BaseLogicCrafting logic, boolean isAdvancedSat, boolean isSplitedCrafting) {
 		super(null);
 		_player = player;
+		this.isAdvancedSat = isAdvancedSat;
+		this.isSplitedCrafting = isSplitedCrafting;
+		
+		if(!isAdvancedSat && !isSplitedCrafting) {
+			xSize = 177;
+			ySize = 187;
+		} else {
+			xSize = 177;
+			ySize = 187 + 30;
+		}
+		
 		DummyContainer dummy = new DummyContainer(player.inventory, dummyInventory);
-		dummy.addNormalSlotsForPlayerInventory(18, 97);
+		dummy.addNormalSlotsForPlayerInventory(8, ySize - 82);
 
 		//Input slots
         for(int l = 0; l < 9; l++) {
-        	dummy.addDummySlot(l, 18 + l * 18, 18);
+        	dummy.addDummySlot(l, 8 + l * 18, 18);
+        }
+
+		//Output slot
+        if(!isAdvancedSat) {
+        	dummy.addDummySlot(9, 85, 55);
+        } else {
+        	dummy.addDummySlot(9, 85, 105);
         }
-        
-        //Output slot
-        dummy.addDummySlot(9, 90, 64);
 		
         this.inventorySlots = dummy;
 		_logic = logic;
-		xSize = 195;
-		ySize = 187;
 		buttonarray = new GuiButton[6];
+		normalButtonArray = new GuiButton[6];
+		advancedSatButtonArray = new GuiButton[9][2];
+		for(int i=0;i<9;i++) {
+			advancedSatButtonArray[i] = new GuiButton[2];
+		}
 	}
 
 	@SuppressWarnings("unchecked")
 	@Override
 	public void initGui() {
 		super.initGui();
 		
-		controlList.add(new SmallGuiButton(0, (width-xSize) / 2 + 164, (height - ySize) / 2 + 50, 10,10, ">"));
-		controlList.add(new SmallGuiButton(1, (width-xSize) / 2 + 129, (height - ySize) / 2 + 50, 10,10, "<"));
-		//controlList.add(new SmallGuiButton(2, (width-xSize) / 2 + 138, (height - ySize) / 2 + 75, 30,10, "Paint"));
-		controlList.add(new SmallGuiButton(3, (width-xSize) / 2 + 47, (height - ySize) / 2 + 50, 37,10, "Import"));
-		controlList.add(new SmallGuiButton(4, (width-xSize) / 2 + 15, (height - ySize) / 2 + 50, 28,10, "Open"));
-		for(int i = 0; i < 6; i++) {
-			controlList.add(buttonarray[i] = new SmallGuiButton(5 + i, (width-xSize) / 2 + 20 + 18 * i, (height - ySize) / 2 + 37, 10,10, ">"));
-			buttonarray[i].drawButton = false;
+		if(!isAdvancedSat) {
+			controlList.add(normalButtonArray[0] = new SmallGuiButton(0, (width-xSize) / 2 + 155, (height - ySize) / 2 + 50, 10,10, ">"));
+			controlList.add(normalButtonArray[1] = new SmallGuiButton(1, (width-xSize) / 2 + 120, (height - ySize) / 2 + 50, 10,10, "<"));
+		}
+		if(!isAdvancedSat) {
+			controlList.add(normalButtonArray[2] = new SmallGuiButton(3, (width-xSize) / 2 + 39, (height - ySize) / 2 + 50, 37,10, "Import"));
+			controlList.add(normalButtonArray[3] = new SmallGuiButton(4, (width-xSize) / 2 + 6, (height - ySize) / 2 + 50, 28,10, "Open"));
+			for(int i = 0; i < 6; i++) {
+				controlList.add(buttonarray[i] = new SmallGuiButton(5 + i, (width-xSize) / 2 + 12 + 18 * i, (height - ySize) / 2 + 30, 10,10, ">"));
+				buttonarray[i].drawButton = false;
+			}
+			controlList.add(normalButtonArray[4] = new SmallGuiButton(20, (width-xSize) / 2 + 155, (height - ySize) / 2 + 85, 10,10, ">"));
+			controlList.add(normalButtonArray[5] = new SmallGuiButton(21, (width-xSize) / 2 + 120, (height - ySize) / 2 + 85, 10,10, "<"));
+		} else {
+			for(int i=0;i<9;i++) {
+				controlList.add(advancedSatButtonArray[i][0] = new SmallGuiButton(30 + i, (width-xSize) / 2 + 10 + 18 * i, (height - ySize) / 2 + 40, 15,10, "/\\"));
+				controlList.add(advancedSatButtonArray[i][1] = new SmallGuiButton(40 + i, (width-xSize) / 2 + 10 + 18 * i, (height - ySize) / 2 + 70, 15,10, "\\/"));
+			}
+			controlList.add(normalButtonArray[2] = new SmallGuiButton(3, (width-xSize) / 2 + 39, (height - ySize) / 2 + 100, 37,10, "Import"));
+			controlList.add(normalButtonArray[3] = new SmallGuiButton(4, (width-xSize) / 2 + 6, (height - ySize) / 2 + 100, 28,10, "Open"));
+			controlList.add(normalButtonArray[4] = new SmallGuiButton(20, (width-xSize) / 2 + 155, (height - ySize) / 2 + 105, 10,10, ">"));
+			controlList.add(normalButtonArray[5] = new SmallGuiButton(21, (width-xSize) / 2 + 120, (height - ySize) / 2 + 105, 10,10, "<"));
 		}
-		controlList.add(new SmallGuiButton(20, (width-xSize) / 2 + 164, (height - ySize) / 2 + 85, 10,10, ">"));
-		controlList.add(new SmallGuiButton(21, (width-xSize) / 2 + 129, (height - ySize) / 2 + 85, 10,10, "<"));
 	}
 	
 	
 	@Override
 	protected void actionPerformed(GuiButton guibutton) {
 		if(5 <= guibutton.id && guibutton.id < 11) {
 			_logic.handleStackMove(guibutton.id - 5);
 		}
+		if(30 <= guibutton.id && guibutton.id < 40) {
+			_logic.setNextSatellite(_player, guibutton.id - 30);
+		}
+		if(40 <= guibutton.id && guibutton.id < 50) {
+			_logic.setPrevSatellite(_player, guibutton.id - 40);
+		}
 		switch(guibutton.id){
 		case 0:
 			_logic.setNextSatellite(_player);
 			return;
 		case 1: 
 			_logic.setPrevSatellite(_player);
 			return;
-		case 2:
+		/*case 2:
 			_logic.paintPathToSatellite();
-			return;
+			return;*/
 		case 3:
 			_logic.importFromCraftingTable(_player);
 			return;
 		case 4:
 			_logic.openAttachedGui(_player);
@@ -107,60 +146,68 @@ public class GuiCraftingPipe extends GuiContainer implements IGuiIDHandlerProvid
 	}
 
 	@Override
 	protected void drawGuiContainerForegroundLayer(int par1, int par2) {
 		fontRenderer.drawString("Inputs", 18, 7, 0x404040);
-		fontRenderer.drawString("Output", 48, 67, 0x404040);
-		fontRenderer.drawString("Inventory", 18, 86, 0x404040);
-		fontRenderer.drawString("Satellite", 132, 7, 0x404040);
+		fontRenderer.drawString("Inventory", 10, ySize - 93, 0x404040);
 		
-		
-		if (_logic.satelliteId == 0){
-			fontRenderer.drawString("Off", 144, 52, 0x404040);
+		if(!isAdvancedSat) {
+			fontRenderer.drawString("Output", 77, 40, 0x404040);
+			fontRenderer.drawString("Satellite", 123, 7, 0x404040);
+			if (_logic.satelliteId == 0) {
+				fontRenderer.drawString("Off", 135, 52, 0x404040);
+			} else {
+				fontRenderer.drawString(""+_logic.satelliteId , 146 - fontRenderer.getStringWidth(""+_logic.satelliteId) , 52, 0x404040);
+			}
+			fontRenderer.drawString("Priority:" , 123 , 75, 0x404040);
+			fontRenderer.drawString(""+_logic.priority , 143 - (fontRenderer.getStringWidth(""+_logic.priority) / 2) , 87, 0x404040);
 		} else {
-			fontRenderer.drawString(""+_logic.satelliteId , 155 - fontRenderer.getStringWidth(""+_logic.satelliteId) , 52, 0x404040);
-			/*
-			if (_logic.isSatelliteConnected()){
-				MinecraftForgeClient.bindTexture(mod_LogisticsPipes.LOGISTICSPIPE_ROUTED_TEXTURE_FILE);
-			}else{
-				MinecraftForgeClient.bindTexture(mod_LogisticsPipes.LOGISTICSPIPE_NOTROUTED_TEXTURE_FILE);
-			}*/
-			//TODO /\ /\ ???
-	
-			//GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-			//drawRect(0,1000,0,10000, 0xFFFF0000);
-			//drawTexturedModalRect(155, 50, 10 * (xSize / 16) , 0, 10, 10);
-			//MinecraftForgeClient.unbindTexture();
+			for(int i=0; i<9;i++) {
+				if (_logic.advancedSatelliteIdArray[i] == 0) {
+					fontRenderer.drawString("Off", 10 + (i * 18), 57, 0x404040);
+				} else {
+					fontRenderer.drawString(""+_logic.advancedSatelliteIdArray[i] , 20 - fontRenderer.getStringWidth(""+_logic.advancedSatelliteIdArray[i]) + (i * 18), 57, 0x404040);
+				}
+			}
+			fontRenderer.drawString("Output", 77, 90, 0x404040);
+			fontRenderer.drawString("Priority:" , 123 , 95, 0x404040);
+			fontRenderer.drawString(""+_logic.priority , 143 - (fontRenderer.getStringWidth(""+_logic.priority) / 2) , 107, 0x404040);
 		}
-		fontRenderer.drawString("Priority:" , 132 , 75, 0x404040);
-		fontRenderer.drawString(""+_logic.priority , 152 - (fontRenderer.getStringWidth(""+_logic.priority) / 2) , 87, 0x404040);
 	}
 	
 	@Override
 	public void drawScreen(int par1, int par2, float par3) {
 		super.drawScreen(par1, par2, par3);
 	}
     
 	@Override
 	protected void drawGuiContainerBackgroundLayer(float f, int x, int y) {
-		int i = mc.renderEngine.getTexture("/logisticspipes/gui/crafting.png");
-		GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-		mc.renderEngine.bindTexture(i);
-		int j = guiLeft;
-		int k = guiTop;
-
-		drawTexturedModalRect(j, k, 0, 0, xSize, ySize);
-
-		drawRect(400, 400, 0, 0, 0x404040);
+		BasicGuiHelper.drawGuiBackGround(mc, guiLeft, guiTop, guiLeft + xSize, guiTop + ySize, zLevel, true, true, true, true, true);
 
-		for(int count=36; count<42;count++) {
-			Slot slot = inventorySlots.getSlot(count);
-			if(slot != null && slot.getStack() != null && slot.getStack().getMaxStackSize() < 2) {
-				drawRect(guiLeft + 18 + (18 * (count-36)), guiTop + 18, guiLeft + 18 + (18 * (count-36)) + 16, guiTop + 18 + 16, 0xFFFF0000);
-				buttonarray[count - 36].drawButton = true;
-			} else {
-				buttonarray[count - 36].drawButton = false;
+		if(!isAdvancedSat) {
+			drawRect(guiLeft + 116, guiTop + 4, guiLeft + 170, guiTop + 70, 0xff8B8B8B);
+		}
+		
+		for(int i=0; i<9;i++) {
+			BasicGuiHelper.drawSlotBackground(mc, guiLeft + 7 + (18*i), guiTop + 17);
+		}
+		if(!isAdvancedSat) {
+			BasicGuiHelper.drawBigSlotBackground(mc, guiLeft + 80, guiTop + 50);
+		} else {
+			BasicGuiHelper.drawBigSlotBackground(mc, guiLeft + 80, guiTop + 100);
+		}
+		BasicGuiHelper.drawPlayerInventoryBackground(mc, guiLeft + 8, guiTop + ySize - 82);
+		
+		if(!isAdvancedSat) {
+			for(int count=36; count<42;count++) {
+				Slot slot = inventorySlots.getSlot(count);
+				if(slot != null && slot.getStack() != null && slot.getStack().getMaxStackSize() < 2) {
+					drawRect(guiLeft + 18 + (18 * (count-36)), guiTop + 18, guiLeft + 18 + (18 * (count-36)) + 16, guiTop + 18 + 16, 0xFFFF0000);
+					buttonarray[count - 36].drawButton = true;
+				} else {
+					buttonarray[count - 36].drawButton = false;
+				}
 			}
 		}
 	}
 
 	@Override
diff --git a/common/logisticspipes/items/ItemUpgrade.java b/common/logisticspipes/items/ItemUpgrade.java
index 7d6a08df..577287b7 100644
--- a/common/logisticspipes/items/ItemUpgrade.java
+++ b/common/logisticspipes/items/ItemUpgrade.java
@@ -2,12 +2,15 @@ package logisticspipes.items;
 
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.List;
 
+import logisticspipes.pipes.upgrades.AdvancedSatelliteUpgrade;
 import logisticspipes.pipes.upgrades.IPipeUpgrade;
 import logisticspipes.pipes.upgrades.SpeedUpgrade;
+import logisticspipes.pipes.upgrades.SplitCraftingCrafterUpgrade;
+import logisticspipes.pipes.upgrades.SplitCraftingSatelliteUpgrade;
 import logisticspipes.pipes.upgrades.connection.ConnectionUpgradeDOWN;
 import logisticspipes.pipes.upgrades.connection.ConnectionUpgradeEAST;
 import logisticspipes.pipes.upgrades.connection.ConnectionUpgradeNORTH;
 import logisticspipes.pipes.upgrades.connection.ConnectionUpgradeSOUTH;
 import logisticspipes.pipes.upgrades.connection.ConnectionUpgradeUP;
@@ -39,10 +42,15 @@ public class ItemUpgrade extends LogisticsItem {
 	public static final int CONNECTION_EAST = 14;
 	public static final int CONNECTION_WEST = 15;
 	
 	//Speed Upgrade
 	public static final int SPEED = 20;
+	
+	//Crafting Upgrades
+	public static final int ADVANCED_SAT_CRAFTINGPIPE = 21;
+	public static final int SAT_DISTRIBUTING_CRAFTER = 22;
+	public static final int SAT_DISTRIBUTING_SATELITE = 23;
 
 	List<Upgrade> upgrades = new ArrayList<Upgrade>();
 	
 	private class Upgrade {
 		private String name;
@@ -117,10 +125,13 @@ public class ItemUpgrade extends LogisticsItem {
 		registerUpgrade(CONNECTION_NORTH, "Disconnection Upgrade (NORTH)", ConnectionUpgradeNORTH.class, 9 * 16 + 9);
 		registerUpgrade(CONNECTION_SOUTH, "Disconnection Upgrade (SOUTH)", ConnectionUpgradeSOUTH.class, 9 * 16 + 10);
 		registerUpgrade(CONNECTION_EAST, "Disconnection Upgrade (EAST)", ConnectionUpgradeEAST.class, 9 * 16 + 11);
 		registerUpgrade(CONNECTION_WEST, "Disconnection Upgrade (WEST)", ConnectionUpgradeWEST.class, 9 * 16 + 12);
 		registerUpgrade(SPEED, "Item Speed Upgrade", SpeedUpgrade.class, 9 * 16 + 6);
+		registerUpgrade(ADVANCED_SAT_CRAFTINGPIPE, "Advanced Satellite Upgrade", AdvancedSatelliteUpgrade.class, 9 * 16 + 13);
+		registerUpgrade(SAT_DISTRIBUTING_CRAFTER, "Split Crafting Upgrade (Crafter)", SplitCraftingCrafterUpgrade.class, 9 * 16 + 14);
+		registerUpgrade(SAT_DISTRIBUTING_SATELITE, "Split Crafting Upgrade (Satellite)", SplitCraftingSatelliteUpgrade.class, 9 * 16 + 15);
 	}
 	
 	public void registerUpgrade(int id, String name, Class<? extends IPipeUpgrade> moduleClass) {
 		boolean flag = true;
 		for(Upgrade upgrade:upgrades) {
diff --git a/common/logisticspipes/logic/BaseLogicCrafting.java b/common/logisticspipes/logic/BaseLogicCrafting.java
index 91be5102..9525ead9 100644
--- a/common/logisticspipes/logic/BaseLogicCrafting.java
+++ b/common/logisticspipes/logic/BaseLogicCrafting.java
@@ -6,12 +6,14 @@ import java.util.List;
 
 import logisticspipes.LogisticsPipes;
 import logisticspipes.interfaces.routing.IRequireReliableTransport;
 import logisticspipes.network.GuiIDs;
 import logisticspipes.network.NetworkConstants;
+import logisticspipes.network.packets.GuiArgumentPacket;
 import logisticspipes.network.packets.PacketCoordinates;
 import logisticspipes.network.packets.PacketInventoryChange;
+import logisticspipes.network.packets.PacketModuleInteger;
 import logisticspipes.network.packets.PacketPipeInteger;
 import logisticspipes.pipes.basic.CoreRoutedPipe;
 import logisticspipes.proxy.MainProxy;
 import logisticspipes.proxy.SimpleServiceLocator;
 import logisticspipes.proxy.interfaces.ICraftingRecipeProvider;
@@ -49,39 +51,58 @@ public class BaseLogicCrafting extends BaseRoutingLogic implements IRequireRelia
 	protected final LinkedList<ItemIdentifierStack> _lostItems = new LinkedList<ItemIdentifierStack>();
 
 	@TileNetworkData
 	public int satelliteId = 0;
 
+	@TileNetworkData(staticSize=9)
+	public int advancedSatelliteIdArray[] = new int[9];
+
 	@TileNetworkData
 	public int priority = 0;
 
 	public BaseLogicCrafting() {
 		throttleTime = 40;
 	}
 
 	/* ** SATELLITE CODE ** */
 
-	protected int getNextConnectSatelliteId(boolean prev) {
+	protected int getNextConnectSatelliteId(boolean prev, int x, int y) {
 		final List<ExitRoute> routes = getRoutedPipe().getRouter().getIRoutersByCost();
 		int closestIdFound = prev ? 0 : Integer.MAX_VALUE;
 		for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
 			CoreRoutedPipe satPipe = satellite.getRoutedPipe();
 			if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
 				continue;
 			IRouter satRouter = satPipe.getRouter();
 			for (ExitRoute route:routes){
 				if (route.destination == satRouter) {
-					if (!prev && satellite.satelliteId > satelliteId && satellite.satelliteId < closestIdFound) {
-						closestIdFound = satellite.satelliteId;
-					} else if (prev && satellite.satelliteId < satelliteId && satellite.satelliteId > closestIdFound) {
-						closestIdFound = satellite.satelliteId;
+					if(x == -1 && y == -1) {
+						if (!prev && satellite.satelliteId > satelliteId && satellite.satelliteId < closestIdFound) {
+							closestIdFound = satellite.satelliteId;
+						} else if (prev && satellite.satelliteId < satelliteId && satellite.satelliteId > closestIdFound) {
+							closestIdFound = satellite.satelliteId;
+						}
+					} else if(y == -1) {
+						if (!prev && satellite.satelliteId > advancedSatelliteIdArray[x] && satellite.satelliteId < closestIdFound) {
+							closestIdFound = satellite.satelliteId;
+						} else if (prev && satellite.satelliteId < advancedSatelliteIdArray[x] && satellite.satelliteId > closestIdFound) {
+							closestIdFound = satellite.satelliteId;
+						}
+					} else {
+						//TODO
 					}
 				}
 			}
 		}
 		if (closestIdFound == Integer.MAX_VALUE) {
-			return satelliteId;
+			if(x == -1 && y == -1) {
+				return satelliteId;
+			} else if(y == -1) {
+				return advancedSatelliteIdArray[x];
+			} else {
+				//TODO
+			}
 		}
 
 		return closestIdFound;
 
 	}
@@ -89,59 +110,105 @@ public class BaseLogicCrafting extends BaseRoutingLogic implements IRequireRelia
 	public void setNextSatellite(EntityPlayer player) {
 		if (MainProxy.isClient(player.worldObj)) {
 			final PacketCoordinates packet = new PacketCoordinates(NetworkConstants.CRAFTING_PIPE_NEXT_SATELLITE, xCoord, yCoord, zCoord);
 			MainProxy.sendPacketToServer(packet.getPacket());
 		} else {
-			satelliteId = getNextConnectSatelliteId(false);
+			satelliteId = getNextConnectSatelliteId(false, -1, -1);
 			final PacketPipeInteger packet = new PacketPipeInteger(NetworkConstants.CRAFTING_PIPE_SATELLITE_ID, xCoord, yCoord, zCoord, satelliteId);
 			MainProxy.sendPacketToPlayer(packet.getPacket(), (Player)player);
 		}
 
 	}
 	
 	// This is called by the packet PacketCraftingPipeSatelliteId
-	public void setSatelliteId(int satelliteId) {
-		this.satelliteId = satelliteId;
+	public void setSatelliteId(int satelliteId, int x, int y) {
+		if(x == -1 && y == -1) {
+			this.satelliteId = satelliteId;
+		} else if(y == -1) {
+			advancedSatelliteIdArray[x] = satelliteId;
+		} else {
+			//TODO
+		}
 	}
 
 	public void setPrevSatellite(EntityPlayer player) {
 		if (MainProxy.isClient(player.worldObj)) {
 			final PacketCoordinates packet = new PacketCoordinates(NetworkConstants.CRAFTING_PIPE_PREV_SATELLITE, xCoord, yCoord, zCoord);
 			MainProxy.sendPacketToServer(packet.getPacket());
 		} else {
-			satelliteId = getNextConnectSatelliteId(true);
+			satelliteId = getNextConnectSatelliteId(true, -1, -1);
 			final PacketPipeInteger packet = new PacketPipeInteger(NetworkConstants.CRAFTING_PIPE_SATELLITE_ID, xCoord, yCoord, zCoord, satelliteId);
 			MainProxy.sendPacketToPlayer(packet.getPacket(), (Player)player);
 		}
 	}
 
 	public boolean isSatelliteConnected() {
 		final List<ExitRoute> routes = getRoutedPipe().getRouter().getIRoutersByCost();
-		for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
-			if (satellite.satelliteId == satelliteId) {
-				CoreRoutedPipe satPipe = satellite.getRoutedPipe();
-				if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
+		if(!((CoreRoutedPipe)this.container.pipe).getUpgradeManager().isAdvancedSatelliteCrafter()) {
+			if(satelliteId == 0) return true;
+			for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
+				if (satellite.satelliteId == satelliteId) {
+					CoreRoutedPipe satPipe = satellite.getRoutedPipe();
+					if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
+						continue;
+					IRouter satRouter = satPipe.getRouter();
+					for (ExitRoute route:routes) {
+						if (route.destination == satRouter) {
+							return true;
+						}
+					}
+				}
+			}
+		} else {
+			boolean foundAll = true;
+			for(int i=0;i<9;i++) {
+				boolean foundOne = false;
+				if(advancedSatelliteIdArray[i] == 0) {
 					continue;
-				IRouter satRouter = satPipe.getRouter();
-				for (ExitRoute route:routes) {
-					if (route.destination == satRouter) {
-						return true;
+				}
+				for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
+					if (satellite.satelliteId == advancedSatelliteIdArray[i]) {
+						CoreRoutedPipe satPipe = satellite.getRoutedPipe();
+						if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
+							continue;
+						IRouter satRouter = satPipe.getRouter();
+						for (ExitRoute route:routes) {
+							if (route.destination == satRouter) {
+								foundOne = true;
+								break;
+							}
+						}
 					}
 				}
+				foundAll &= foundOne;
 			}
+			return foundAll;
 		}
 		return false;
 	}
 
-	public IRouter getSatelliteRouter() {
-		for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
-			if (satellite.satelliteId == satelliteId) {
-				CoreRoutedPipe satPipe = satellite.getRoutedPipe();
-				if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
-					continue;
-				return satPipe.getRouter();
+	public IRouter getSatelliteRouter(int x, int y) {
+		if(x == -1 && y == -1) {
+			for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
+				if (satellite.satelliteId == satelliteId) {
+					CoreRoutedPipe satPipe = satellite.getRoutedPipe();
+					if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
+						continue;
+					return satPipe.getRouter();
+				}
+			}
+		} else if(y == -1) {
+			for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
+				if (satellite.satelliteId == advancedSatelliteIdArray[x]) {
+					CoreRoutedPipe satPipe = satellite.getRoutedPipe();
+					if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
+						continue;
+					return satPipe.getRouter();
+				}
 			}
+		} else {
+			//TODO
 		}
 		return null;
 	}
 
 	@Override
@@ -180,10 +247,11 @@ public class BaseLogicCrafting extends BaseRoutingLogic implements IRequireRelia
 	}
 
 	@Override
 	public void onWrenchClicked(EntityPlayer entityplayer) {
 		if (MainProxy.isServer(entityplayer.worldObj)) {
+			MainProxy.sendPacketToPlayer(new GuiArgumentPacket(GuiIDs.GUI_CRAFTINGPIPE_ID, new Object[]{((CoreRoutedPipe)this.container.pipe).getUpgradeManager().isAdvancedSatelliteCrafter(), ((CoreRoutedPipe)this.container.pipe).getUpgradeManager().isSatelliteCraftingCrafter()}).getPacket(),  (Player) entityplayer);
 			entityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_CRAFTINGPIPE_ID, worldObj, xCoord, yCoord, zCoord);
 		}
 	}
 
 	@Override
@@ -361,18 +429,27 @@ public class BaseLogicCrafting extends BaseRoutingLogic implements IRequireRelia
 	
 	public void setDummyInventorySlot(int slot, ItemStack itemstack) {
 		_dummyInventory.setInventorySlotContents(slot, itemstack);
 	}
 
-	/* ** NON NETWORKING ** */
-	@SuppressWarnings("deprecation")
-	public void paintPathToSatellite() {
-		final IRouter satelliteRouter = getSatelliteRouter();
-		if (satelliteRouter == null) {
-			return;
+	public void setNextSatellite(EntityPlayer player, int i) {
+		if (MainProxy.isClient(player.worldObj)) {
+			final PacketCoordinates packet = new PacketPipeInteger(NetworkConstants.CRAFTING_PIPE_NEXT_SATELLITE_ADVANCED, xCoord, yCoord, zCoord, i);
+			MainProxy.sendPacketToServer(packet.getPacket());
+		} else {
+			advancedSatelliteIdArray[i] = getNextConnectSatelliteId(false, i, -1);
+			final PacketModuleInteger packet = new PacketModuleInteger(NetworkConstants.CRAFTING_PIPE_SATELLITE_ID_ADVANCED, xCoord, yCoord, zCoord, i, advancedSatelliteIdArray[i]);
+			MainProxy.sendPacketToPlayer(packet.getPacket(), (Player)player);
 		}
-
-		getRoutedPipe().getRouter().displayRouteTo(satelliteRouter.getSimpleID());
 	}
 
-
+	public void setPrevSatellite(EntityPlayer player, int i) {
+		if (MainProxy.isClient(player.worldObj)) {
+			final PacketCoordinates packet = new PacketPipeInteger(NetworkConstants.CRAFTING_PIPE_PREV_SATELLITE_ADVANCED, xCoord, yCoord, zCoord, i);
+			MainProxy.sendPacketToServer(packet.getPacket());
+		} else {
+			advancedSatelliteIdArray[i] = getNextConnectSatelliteId(true, i, -1);
+			final PacketModuleInteger packet = new PacketModuleInteger(NetworkConstants.CRAFTING_PIPE_SATELLITE_ID_ADVANCED, xCoord, yCoord, zCoord, i, advancedSatelliteIdArray[i]);
+			MainProxy.sendPacketToPlayer(packet.getPacket(), (Player)player);
+		}
+	}
 }
diff --git a/common/logisticspipes/logistics/LogisticsLiquidManager.java b/common/logisticspipes/logistics/LogisticsLiquidManager.java
index 080a4ac4..a3423627 100644
--- a/common/logisticspipes/logistics/LogisticsLiquidManager.java
+++ b/common/logisticspipes/logistics/LogisticsLiquidManager.java
@@ -39,11 +39,11 @@ public class LogisticsLiquidManager implements ILogisticsLiquidManager {
 			if(amount > 0) {
 				Pair<Integer, Integer> result = new Pair<Integer, Integer>(candidateRouter.destination.getSimpleID(), amount);
 				return result;
 			}
 		}
-		Pair<Integer, Integer> result = new Pair<Integer, Integer>(null, 0);
+		Pair<Integer, Integer> result = new Pair<Integer, Integer>(0, 0);
 		return result;
 	}
 
 	@Override
 	public ItemStack getLiquidContainer(LiquidStack stack) {
diff --git a/common/logisticspipes/nei/DebugHelper.java b/common/logisticspipes/nei/DebugHelper.java
index 4190856b..c07f9bfc 100644
--- a/common/logisticspipes/nei/DebugHelper.java
+++ b/common/logisticspipes/nei/DebugHelper.java
@@ -101,10 +101,11 @@ public class DebugHelper implements IContainerTooltipHandler {
 			int i = 0;
 			for(byte byt:((NBTTagByteArray)nbt).byteArray) {
 				content.add(new DefaultMutableTreeNode("[" + i + "]: " + Byte.toString(byt)));
 				i++;
 			}
+			node.add(content);
 			node.add(type);
 		} else if(nbt instanceof NBTTagDouble) {
 			DefaultMutableTreeNode type = new DefaultMutableTreeNode("NBTTagDouble");
 			type.add(new DefaultMutableTreeNode("Name: " + nbt.getName()));
 			type.add(new DefaultMutableTreeNode("Data: " + ((NBTTagDouble)nbt).data));
diff --git a/common/logisticspipes/network/ClientPacketHandler.java b/common/logisticspipes/network/ClientPacketHandler.java
index d15d25bd..1da52f3d 100755
--- a/common/logisticspipes/network/ClientPacketHandler.java
+++ b/common/logisticspipes/network/ClientPacketHandler.java
@@ -39,10 +39,11 @@ import logisticspipes.modules.ModuleApiaristSink;
 import logisticspipes.modules.ModuleElectricManager;
 import logisticspipes.modules.ModuleItemSink;
 import logisticspipes.modules.ModuleModBasedItemSink;
 import logisticspipes.modules.ModuleThaumicAspectSink;
 import logisticspipes.nei.LoadingHelper;
+import logisticspipes.network.packets.GuiArgumentPacket;
 import logisticspipes.network.packets.PacketBufferTransfer;
 import logisticspipes.network.packets.PacketCoordinatesUUID;
 import logisticspipes.network.packets.PacketCraftingLoop;
 import logisticspipes.network.packets.PacketInventoryChange;
 import logisticspipes.network.packets.PacketItem;
@@ -336,10 +337,21 @@ public class ClientPacketHandler {
 				case NetworkConstants.SET_SECURITY_CC:
 					final PacketPipeInteger packetBb = new PacketPipeInteger();
 					packetBb.readData(data);
 					onSetSecurityCC(packetBb);
 					break;
+				case NetworkConstants.GUI_ARGUMENT_PACKET:
+					final GuiArgumentPacket packetBc = new GuiArgumentPacket();
+					packetBc.readData(data);
+					GuiHandler.argumentQueue.put(packetBc.guiID, packetBc.args);
+					break;
+				case NetworkConstants.CRAFTING_PIPE_SATELLITE_ID_ADVANCED:
+					final PacketModuleInteger packetBd = new PacketModuleInteger();
+					packetBd.readData(data);
+					onCraftingPipeSetSatelliteAdvanced(packetBd);
+					break;
+					
 			}
 		} catch (final Exception ex) {
 			ex.printStackTrace();
 		}
 	}
@@ -352,11 +364,11 @@ public class ClientPacketHandler {
 
 		if (!(pipe.pipe.logic instanceof BaseLogicCrafting)) {
 			return;
 		}
 
-		((BaseLogicCrafting) pipe.pipe.logic).setSatelliteId(packet.integer);
+		((BaseLogicCrafting) pipe.pipe.logic).setSatelliteId(packet.integer, -1, -1);
 	}
 
 	private static void onCraftingPipeSetImport(PacketInventoryChange packet) {
 		final TileGenericPipe pipe = getPipe(FMLClientHandler.instance().getClient().theWorld, packet.posX, packet.posY, packet.posZ);
 		if (pipe == null) {
@@ -923,10 +935,23 @@ public class ClientPacketHandler {
 			if (FMLClientHandler.instance().getClient().currentScreen instanceof GuiSecurityStation) {
 				((GuiSecurityStation)FMLClientHandler.instance().getClient().currentScreen).refreshCheckBoxes();
 			}
 		}
 	}
+
+	private static void onCraftingPipeSetSatelliteAdvanced(PacketModuleInteger packet) {
+		final TileGenericPipe pipe = getPipe(FMLClientHandler.instance().getClient().theWorld, packet.posX, packet.posY, packet.posZ);
+		if (pipe == null) {
+			return;
+		}
+
+		if (!(pipe.pipe.logic instanceof BaseLogicCrafting)) {
+			return;
+		}
+
+		((BaseLogicCrafting) pipe.pipe.logic).setSatelliteId(packet.integer, packet.slot, -1);
+	}
 	
 	// BuildCraft method
 	/**
 	 * Retrieves pipe at specified coordinates if any.
 	 * 
diff --git a/common/logisticspipes/network/GuiHandler.java b/common/logisticspipes/network/GuiHandler.java
index f9cad4cb..b926b7da 100644
--- a/common/logisticspipes/network/GuiHandler.java
+++ b/common/logisticspipes/network/GuiHandler.java
@@ -1,7 +1,10 @@
 package logisticspipes.network;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import logisticspipes.LogisticsPipes;
 import logisticspipes.blocks.LogisticsSecurityTileEntity;
 import logisticspipes.blocks.LogisticsSolderingTileEntity;
 import logisticspipes.blocks.powertile.LogisticsPowerJuntionTileEntity_BuildCraft;
 import logisticspipes.gui.GuiChassiPipe;
@@ -85,10 +88,12 @@ import buildcraft.core.utils.SimpleInventory;
 import buildcraft.transport.TileGenericPipe;
 import cpw.mods.fml.common.network.IGuiHandler;
 import cpw.mods.fml.common.network.Player;
 
 public class GuiHandler implements IGuiHandler {
+	
+	public final static Map<Integer, Object[]> argumentQueue = new HashMap<Integer, Object[]>();
 
 	@Override
 	public Object getServerGuiElement(int ID, EntityPlayer player, World world, final int x, final int y, final int z) {
 		
 		TileEntity tile = null;
@@ -632,16 +637,22 @@ public class GuiHandler implements IGuiHandler {
 					}
 				}
 			}
 		}
 		
+		Object[] args = argumentQueue.get(GuiIDs.GUI_CRAFTINGPIPE_ID);
+		
 		if(ID < 120) {
 			switch(ID) {
 			
 			case GuiIDs.GUI_CRAFTINGPIPE_ID:
 				if(pipe == null || pipe.pipe == null || !(pipe.pipe.logic instanceof BaseLogicCrafting)) return null;
-				return new GuiCraftingPipe(player, ((BaseLogicCrafting)pipe.pipe.logic).getDummyInventory(), (BaseLogicCrafting)pipe.pipe.logic);
+				if(args == null) {
+					new UnsupportedOperationException("Arguments missing").printStackTrace();
+					return null;
+				}
+				return new GuiCraftingPipe(player, ((BaseLogicCrafting)pipe.pipe.logic).getDummyInventory(), (BaseLogicCrafting)pipe.pipe.logic, (Boolean) args[0], (Boolean) args[1]);
 			
 			case GuiIDs.GUI_LiquidSupplier_ID:
 				if(pipe == null || pipe.pipe == null || !(pipe.pipe.logic instanceof LogicLiquidSupplier)) return null;
 				return new GuiLiquidSupplierPipe(player.inventory, ((LogicLiquidSupplier)pipe.pipe.logic).getDummyInventory(), (LogicLiquidSupplier)pipe.pipe.logic);
 				
diff --git a/common/logisticspipes/network/NetworkConstants.java b/common/logisticspipes/network/NetworkConstants.java
index 9b9bc534..187528da 100755
--- a/common/logisticspipes/network/NetworkConstants.java
+++ b/common/logisticspipes/network/NetworkConstants.java
@@ -97,6 +97,10 @@ public class NetworkConstants {
 	public static final int PLAYER_LIST = 92;
 	public static final int SECURITY_STATION_ID = 93;
 	public static final int OPEN_SECURITY_PLAYER = 94;
 	public static final int SAVE_SECURITY_PLAYER = 95;
 	public static final int SET_SECURITY_CC = 96;
+	public static final int GUI_ARGUMENT_PACKET = 97;
+	public static final int CRAFTING_PIPE_NEXT_SATELLITE_ADVANCED = 98;
+	public static final int CRAFTING_PIPE_PREV_SATELLITE_ADVANCED = 99;
+	public static final int CRAFTING_PIPE_SATELLITE_ID_ADVANCED = 100;
 }
diff --git a/common/logisticspipes/network/ServerPacketHandler.java b/common/logisticspipes/network/ServerPacketHandler.java
index 14a2eb0e..e4415e16 100644
--- a/common/logisticspipes/network/ServerPacketHandler.java
+++ b/common/logisticspipes/network/ServerPacketHandler.java
@@ -368,11 +368,20 @@ public class ServerPacketHandler {
 				case NetworkConstants.SET_SECURITY_CC:
 					final PacketPipeInteger packetBc = new PacketPipeInteger();
 					packetBc.readData(data);
 					onSetSecurityCC(player, packetBc);
 					break;
-					
+				case NetworkConstants.CRAFTING_PIPE_NEXT_SATELLITE_ADVANCED:
+					final PacketPipeInteger packetBd = new PacketPipeInteger();
+					packetBd.readData(data);
+					onCraftingPipeNextSatelliteAdvanced(player, packetBd);
+					break;
+				case NetworkConstants.CRAFTING_PIPE_PREV_SATELLITE_ADVANCED:
+					final PacketPipeInteger packetBe = new PacketPipeInteger();
+					packetBe.readData(data);
+					onCraftingPipePrevSatelliteAdvanced(player, packetBe);
+					break;
 			}
 		} catch (final Exception ex) {
 			ex.printStackTrace();
 		}
 	}
@@ -1436,10 +1445,36 @@ public class ServerPacketHandler {
 		TileEntity tile = player.worldObj.getBlockTileEntity(packet.posX, packet.posY, packet.posZ);
 		if(tile instanceof LogisticsSecurityTileEntity) {
 			((LogisticsSecurityTileEntity)tile).changeCC();
 		}
 	}
+
+	private static void onCraftingPipeNextSatelliteAdvanced(EntityPlayerMP player, PacketPipeInteger packet) {
+		final TileGenericPipe pipe = getPipe(player.worldObj, packet.posX, packet.posY, packet.posZ);
+		if (pipe == null) {
+			return;
+		}
+
+		if (!(pipe.pipe.logic instanceof BaseLogicCrafting)) {
+			return;
+		}
+
+		((BaseLogicCrafting) pipe.pipe.logic).setNextSatellite(player, packet.integer);
+	}
+
+	private static void onCraftingPipePrevSatelliteAdvanced(EntityPlayerMP player, PacketPipeInteger packet) {
+		final TileGenericPipe pipe = getPipe(player.worldObj, packet.posX, packet.posY, packet.posZ);
+		if (pipe == null) {
+			return;
+		}
+
+		if (!(pipe.pipe.logic instanceof BaseLogicCrafting)) {
+			return;
+		}
+
+		((BaseLogicCrafting) pipe.pipe.logic).setPrevSatellite(player, packet.integer);
+	}
 	
 	// BuildCraft method
 	/**
 	 * Retrieves pipe at specified coordinates if any.
 	 * 
diff --git a/common/logisticspipes/network/packets/GuiArgumentPacket.java b/common/logisticspipes/network/packets/GuiArgumentPacket.java
new file mode 100644
index 00000000..eb2f37e4
--- /dev/null
+++ b/common/logisticspipes/network/packets/GuiArgumentPacket.java
@@ -0,0 +1,70 @@
+package logisticspipes.network.packets;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+
+import logisticspipes.network.NetworkConstants;
+
+public class GuiArgumentPacket extends LogisticsPipesPacket {
+	
+	public Object[] args;
+	public int guiID = 0;
+	
+	public GuiArgumentPacket() {
+		super();
+	}
+	
+	public GuiArgumentPacket(int Id, Object... arg) {
+		super();
+		args = arg;
+		guiID = Id;
+	}
+	
+	@Override
+	public int getID() {
+		return NetworkConstants.GUI_ARGUMENT_PACKET;
+	}
+
+	@Override
+	public void readData(DataInputStream data) throws IOException {
+		guiID = data.readInt();
+		int size = data.readInt();
+		args = new Object[size];
+		for(int i=0; i < size;i++) {
+			int arraySize = data.readInt();
+			byte[] bytes = new byte[arraySize];
+			data.read(bytes);
+			ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
+			ObjectInput in = null;
+			in = new ObjectInputStream(bis);
+			try {
+				Object o = in.readObject();
+				args[i] = o;
+			} catch (ClassNotFoundException e) {
+				throw new UnsupportedOperationException(e);
+			} 
+		}
+	}
+
+	@Override
+	public void writeData(DataOutputStream data) throws IOException {
+		data.writeInt(guiID);
+		data.writeInt(args.length);
+		for(int i=0; i<args.length;i++) {
+			ByteArrayOutputStream bos = new ByteArrayOutputStream();
+			ObjectOutput out = null;
+			out = new ObjectOutputStream(bos); 
+			out.writeObject(args[i]);
+			byte[] bytes = bos.toByteArray();
+			data.writeInt(bytes.length);
+			data.write(bytes);
+		}
+	}
+}
diff --git a/common/logisticspipes/pipes/PipeItemsCraftingLogistics.java b/common/logisticspipes/pipes/PipeItemsCraftingLogistics.java
index 6b41aefb..7e1a7aa7 100644
--- a/common/logisticspipes/pipes/PipeItemsCraftingLogistics.java
+++ b/common/logisticspipes/pipes/PipeItemsCraftingLogistics.java
@@ -346,26 +346,41 @@ public class PipeItemsCraftingLogistics extends CoreRoutedPipe implements ICraft
 			return null;
 		}
 		
 		BaseLogicCrafting craftingLogic = (BaseLogicCrafting) this.logic;
 		ItemStack stack = craftingLogic.getCraftedItem(); 
-		if ( stack == null) return null;
+		if (stack == null) return null;
+		
+		IRequestItems[] target = new IRequestItems[9];
+		for(int i=0;i<9;i++) {
+			target[i] = this;
+		}
 
 		boolean hasSatellite = craftingLogic.isSatelliteConnected();
-		if(craftingLogic.satelliteId != 0 && !hasSatellite) return null;
+		if(!hasSatellite) return null;
+		if(!getUpgradeManager().isAdvancedSatelliteCrafter()) {
+			if(craftingLogic.satelliteId != 0) {
+				IRequestItems sat = (IRequestItems)craftingLogic.getSatelliteRouter(-1, -1).getPipe();
+				for(int i=6;i<9;i++) {
+					target[i] = sat;
+				}
+			}
+		} else {
+			for(int i=0;i<9;i++) {
+				if(craftingLogic.advancedSatelliteIdArray[i] != 0) {
+					target[i] = (IRequestItems)craftingLogic.getSatelliteRouter(i, -1).getPipe();
+				}
+			}
+		}
 
 		CraftingTemplate template = new CraftingTemplate(ItemIdentifierStack.GetFromStack(stack), this, craftingLogic.priority);
 
 		//Check all materials
 		for (int i = 0; i < 9; i++){
 			ItemStack resourceStack = craftingLogic.getMaterials(i);
 			if (resourceStack == null || resourceStack.stackSize == 0) continue;
-			if (i < 6 || !hasSatellite) {
-				template.addRequirement(ItemIdentifierStack.GetFromStack(resourceStack), this);
-			} else {
-				template.addRequirement(ItemIdentifierStack.GetFromStack(resourceStack), (IRequestItems)craftingLogic.getSatelliteRouter().getPipe());
-			}
+			template.addRequirement(ItemIdentifierStack.GetFromStack(resourceStack), target[i]);
 				
 		}
 		return template;
 	}
 
diff --git a/common/logisticspipes/pipes/PipeLiquidProvider.java b/common/logisticspipes/pipes/PipeLiquidProvider.java
index 4c1c19d7..c23c6cff 100644
--- a/common/logisticspipes/pipes/PipeLiquidProvider.java
+++ b/common/logisticspipes/pipes/PipeLiquidProvider.java
@@ -1,9 +1,11 @@
 package logisticspipes.pipes;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
 
 import logisticspipes.interfaces.routing.ILiquidProvider;
 import logisticspipes.interfaces.routing.IRequestLiquid;
 import logisticspipes.logisticspipes.IRoutedItem;
 import logisticspipes.logisticspipes.IRoutedItem.TransportMode;
@@ -12,10 +14,11 @@ import logisticspipes.proxy.SimpleServiceLocator;
 import logisticspipes.request.LiquidRequest;
 import logisticspipes.routing.LiquidLogisticsPromise;
 import logisticspipes.routing.LogisticsLiquidOrderManager;
 import logisticspipes.textures.Textures;
 import logisticspipes.textures.Textures.TextureType;
+import logisticspipes.utils.ItemIdentifier;
 import logisticspipes.utils.LiquidIdentifier;
 import logisticspipes.utils.Pair;
 import logisticspipes.utils.Pair3;
 import net.minecraft.item.ItemStack;
 import net.minecraft.tileentity.TileEntity;
@@ -142,6 +145,23 @@ public class PipeLiquidProvider extends LiquidRoutedPipe implements ILiquidProvi
 
 	@Override
 	public boolean canInsertFromSideToTanks() {
 		return true;
 	}
+
+
+	@Override //work in progress, currently not active code.
+	public Set<ItemIdentifier> getSpecificInterests() {
+		Set<ItemIdentifier> l1 = new TreeSet<ItemIdentifier>();;
+		for(Pair<TileEntity, ForgeDirection> pair:getAdjacentTanks(false)) {
+			ILiquidTank[] tanks = ((ITankContainer)pair.getValue1()).getTanks(pair.getValue2().getOpposite());
+			for(ILiquidTank tank:tanks) {
+				LiquidStack liquid;
+				if((liquid = tank.getLiquid()) != null && liquid.itemID != 0) {
+					LiquidIdentifier ident = LiquidIdentifier.get(liquid);
+					l1.add(ident.getItemIdentifier());
+				}
+			}
+		}
+		return l1;
+	}
 }
diff --git a/common/logisticspipes/pipes/upgrades/AdvancedSatelliteUpgrade.java b/common/logisticspipes/pipes/upgrades/AdvancedSatelliteUpgrade.java
new file mode 100644
index 00000000..fc16ac03
--- /dev/null
+++ b/common/logisticspipes/pipes/upgrades/AdvancedSatelliteUpgrade.java
@@ -0,0 +1,17 @@
+package logisticspipes.pipes.upgrades;
+
+import logisticspipes.pipes.PipeItemsCraftingLogistics;
+import logisticspipes.pipes.basic.CoreRoutedPipe;
+
+public class AdvancedSatelliteUpgrade implements IPipeUpgrade {
+
+	@Override
+	public boolean needsUpdate() {
+		return false;
+	}
+
+	@Override
+	public boolean isAllowed(CoreRoutedPipe pipe) {
+		return pipe instanceof PipeItemsCraftingLogistics;
+	}
+}
diff --git a/common/logisticspipes/pipes/upgrades/ConnectionUpgrade.java b/common/logisticspipes/pipes/upgrades/ConnectionUpgrade.java
index 87c30c1d..1a020e12 100644
--- a/common/logisticspipes/pipes/upgrades/ConnectionUpgrade.java
+++ b/common/logisticspipes/pipes/upgrades/ConnectionUpgrade.java
@@ -1,12 +1,18 @@
 package logisticspipes.pipes.upgrades;
 
+import logisticspipes.pipes.basic.CoreRoutedPipe;
 import net.minecraftforge.common.ForgeDirection;
 
 public abstract class ConnectionUpgrade implements IPipeUpgrade {
 	public abstract ForgeDirection getSide();
 
 	@Override
 	public boolean needsUpdate() {
 		return true;
 	}
+
+	@Override
+	public boolean isAllowed(CoreRoutedPipe pipe) {
+		return true;
+	}
 }
diff --git a/common/logisticspipes/pipes/upgrades/IPipeUpgrade.java b/common/logisticspipes/pipes/upgrades/IPipeUpgrade.java
index 393587e0..ab835cf9 100644
--- a/common/logisticspipes/pipes/upgrades/IPipeUpgrade.java
+++ b/common/logisticspipes/pipes/upgrades/IPipeUpgrade.java
@@ -1,6 +1,8 @@
 package logisticspipes.pipes.upgrades;
 
+import logisticspipes.pipes.basic.CoreRoutedPipe;
 
 public interface IPipeUpgrade {
 	boolean needsUpdate();
+	boolean isAllowed(CoreRoutedPipe pipe);
 }
diff --git a/common/logisticspipes/pipes/upgrades/SneakyUpgrade.java b/common/logisticspipes/pipes/upgrades/SneakyUpgrade.java
index 802dad65..d7c83ed0 100644
--- a/common/logisticspipes/pipes/upgrades/SneakyUpgrade.java
+++ b/common/logisticspipes/pipes/upgrades/SneakyUpgrade.java
@@ -1,12 +1,18 @@
 package logisticspipes.pipes.upgrades;
 
+import logisticspipes.pipes.basic.CoreRoutedPipe;
 import net.minecraftforge.common.ForgeDirection;
 
 public abstract class SneakyUpgrade implements IPipeUpgrade {
 	public abstract ForgeDirection getSneakyOrientation();
 
 	@Override
 	public boolean needsUpdate() {
 		return false;
 	}
+
+	@Override
+	public boolean isAllowed(CoreRoutedPipe pipe) {
+		return true;
+	}
 }
diff --git a/common/logisticspipes/pipes/upgrades/SpeedUpgrade.java b/common/logisticspipes/pipes/upgrades/SpeedUpgrade.java
index 88c6f13e..1c116969 100644
--- a/common/logisticspipes/pipes/upgrades/SpeedUpgrade.java
+++ b/common/logisticspipes/pipes/upgrades/SpeedUpgrade.java
@@ -1,10 +1,16 @@
 package logisticspipes.pipes.upgrades;
 
+import logisticspipes.pipes.basic.CoreRoutedPipe;
+
 public class SpeedUpgrade implements IPipeUpgrade {
 
 	@Override
 	public boolean needsUpdate() {
 		return false;
 	}
-
+	
+	@Override
+	public boolean isAllowed(CoreRoutedPipe pipe) {
+		return true;
+	}
 }
diff --git a/common/logisticspipes/pipes/upgrades/SplitCraftingCrafterUpgrade.java b/common/logisticspipes/pipes/upgrades/SplitCraftingCrafterUpgrade.java
new file mode 100644
index 00000000..fb4fabd6
--- /dev/null
+++ b/common/logisticspipes/pipes/upgrades/SplitCraftingCrafterUpgrade.java
@@ -0,0 +1,17 @@
+package logisticspipes.pipes.upgrades;
+
+import logisticspipes.pipes.PipeItemsCraftingLogistics;
+import logisticspipes.pipes.basic.CoreRoutedPipe;
+
+public class SplitCraftingCrafterUpgrade implements IPipeUpgrade {
+
+	@Override
+	public boolean needsUpdate() {
+		return false;
+	}
+	
+	@Override
+	public boolean isAllowed(CoreRoutedPipe pipe) {
+		return pipe instanceof PipeItemsCraftingLogistics;
+	}
+}
diff --git a/common/logisticspipes/pipes/upgrades/SplitCraftingSatelliteUpgrade.java b/common/logisticspipes/pipes/upgrades/SplitCraftingSatelliteUpgrade.java
new file mode 100644
index 00000000..130ad47d
--- /dev/null
+++ b/common/logisticspipes/pipes/upgrades/SplitCraftingSatelliteUpgrade.java
@@ -0,0 +1,17 @@
+package logisticspipes.pipes.upgrades;
+
+import logisticspipes.pipes.PipeItemsSatelliteLogistics;
+import logisticspipes.pipes.basic.CoreRoutedPipe;
+
+public class SplitCraftingSatelliteUpgrade implements IPipeUpgrade {
+
+	@Override
+	public boolean needsUpdate() {
+		return false;
+	}
+	
+	@Override
+	public boolean isAllowed(CoreRoutedPipe pipe) {
+		return pipe instanceof PipeItemsSatelliteLogistics;
+	}
+}
diff --git a/common/logisticspipes/pipes/upgrades/UpgradeManager.java b/common/logisticspipes/pipes/upgrades/UpgradeManager.java
index 6c492e26..faba095d 100644
--- a/common/logisticspipes/pipes/upgrades/UpgradeManager.java
+++ b/common/logisticspipes/pipes/upgrades/UpgradeManager.java
@@ -29,10 +29,13 @@ public class UpgradeManager implements ISimpleInventoryEventHandler {
 
 	/* cached attributes */
 	private ForgeDirection sneakyOrientation = ForgeDirection.UNKNOWN;
 	private int speedUpgradeCount = 0;
 	private final EnumSet<ForgeDirection> disconnectedSides = EnumSet.noneOf(ForgeDirection.class);
+	private boolean isAdvancedCrafter = false;
+	private boolean isSatelliteCraftingSatellite = false;
+	private boolean isSatelliteCraftingCrafter = false;
 	
 	public UpgradeManager(CoreRoutedPipe pipe) {
 		this.pipe = pipe;
 		inv.addListener(this);
 	}
@@ -70,19 +73,28 @@ public class UpgradeManager implements ISimpleInventoryEventHandler {
 			}
 		}
 		//update sneaky direction, speed upgrade count and disconnection
 		sneakyOrientation = ForgeDirection.UNKNOWN;
 		speedUpgradeCount = 0;
+		isAdvancedCrafter = false;
+		isSatelliteCraftingSatellite = false;
+		isSatelliteCraftingCrafter = false;
 		disconnectedSides.clear();
 		for(int i=0;i<upgrades.length;i++) {
 			IPipeUpgrade upgrade = upgrades[i];
 			if(upgrade instanceof SneakyUpgrade && sneakyOrientation == ForgeDirection.UNKNOWN) {
 				sneakyOrientation = ((SneakyUpgrade) upgrade).getSneakyOrientation();
 			} else if(upgrade instanceof SpeedUpgrade) {
 				speedUpgradeCount += inv.getStackInSlot(i).stackSize;
 			} else if(upgrade instanceof ConnectionUpgrade) {
 				disconnectedSides.add(((ConnectionUpgrade)upgrade).getSide());
+			} else if(upgrade instanceof SplitCraftingCrafterUpgrade) {
+				isSatelliteCraftingCrafter = true;
+			} else if(upgrade instanceof SplitCraftingSatelliteUpgrade) {
+				isSatelliteCraftingSatellite = true;
+			} else if(upgrade instanceof AdvancedSatelliteUpgrade) {
+				isAdvancedCrafter = true;
 			}
 		}
 		if(needUpdate) {
 			pipe.connectionUpdate();
 		}
@@ -110,11 +122,22 @@ public class UpgradeManager implements ISimpleInventoryEventHandler {
 		DummyContainer dummy = new DummyContainer(player.inventory, inv);
 		dummy.addNormalSlotsForPlayerInventory(8, 60);
 
 		//Pipe slots
 	    for(int pipeSlot = 0; pipeSlot < 8; pipeSlot++){
-	    	dummy.addRestrictedSlot(pipeSlot, inv, 8 + pipeSlot * 18, 18, LogisticsPipes.UpgradeItem.itemID);
+	    	dummy.addRestrictedSlot(pipeSlot, inv, 8 + pipeSlot * 18, 18, new ISlotCheck() {
+				@Override
+				public boolean isStackAllowed(ItemStack itemStack) {
+					if(itemStack == null) return false;
+					if(itemStack.itemID == LogisticsPipes.UpgradeItem.itemID) {
+						if(!LogisticsPipes.UpgradeItem.getUpgradeForItem(itemStack, null).isAllowed(pipe)) return false;
+					} else {
+						return false;
+					}
+					return true;
+				}
+	    	});
 	    }
     	dummy.addRestrictedSlot(8, inv, 8 + 8 * 18, 18, new ISlotCheck() {
 			@Override
 			public boolean isStackAllowed(ItemStack itemStack) {
 				if(itemStack == null) return false;
@@ -133,11 +156,11 @@ public class UpgradeManager implements ISimpleInventoryEventHandler {
 	public boolean isSideDisconnected(ForgeDirection side) {
 		return disconnectedSides.contains(side);
 	}
 
 	public boolean tryIserting(World world, EntityPlayer entityplayer) {
-		if(entityplayer.getCurrentEquippedItem() != null && entityplayer.getCurrentEquippedItem().itemID == LogisticsPipes.UpgradeItem.itemID) {
+		if(entityplayer.getCurrentEquippedItem() != null && entityplayer.getCurrentEquippedItem().itemID == LogisticsPipes.UpgradeItem.itemID && LogisticsPipes.UpgradeItem.getUpgradeForItem(entityplayer.getCurrentEquippedItem(), null).isAllowed(pipe)) {
 			if(MainProxy.isClient(world)) return true;
 			for(int i=0;i<inv.getSizeInventory() - 1;i++) {
 				ItemStack item = inv.getStackInSlot(i);
 				if(item == null) {
 					inv.setInventorySlotContents(i, entityplayer.getCurrentEquippedItem().splitStack(1));
@@ -192,6 +215,18 @@ public class UpgradeManager implements ISimpleInventoryEventHandler {
 			if(securityDelay > 20) {
 				inv.setInventorySlotContents(8, null);
 			}
 		}
 	}
+	
+	public boolean isAdvancedSatelliteCrafter() {
+		return isAdvancedCrafter;
+	}
+	
+	public boolean isSatelliteCraftingSatellite() {
+		return isSatelliteCraftingSatellite;
+	}
+	
+	public boolean isSatelliteCraftingCrafter() {
+		return isSatelliteCraftingCrafter;
+	}
 }
diff --git a/common/logisticspipes/utils/gui/BasicGuiHelper.java b/common/logisticspipes/utils/gui/BasicGuiHelper.java
index 777d7260..9a6a944f 100644
--- a/common/logisticspipes/utils/gui/BasicGuiHelper.java
+++ b/common/logisticspipes/utils/gui/BasicGuiHelper.java
@@ -431,10 +431,24 @@ public class BasicGuiHelper {
         var9.addVertexWithUV(x + 18	, y			, (double)zLevel, 1	, 0);
         var9.addVertexWithUV(x		, y			, (double)zLevel, 0	, 0);
         var9.draw();
     }
     
+    public static void drawBigSlotBackground(Minecraft mc, int x, int y) {
+		int i = mc.renderEngine.getTexture("/logisticspipes/gui/slot-big.png");
+		GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+		mc.renderEngine.bindTexture(i);
+		
+		Tessellator var9 = Tessellator.instance;
+        var9.startDrawingQuads();
+        var9.addVertexWithUV(x		, y + 26	, (double)zLevel, 0	, 1);
+        var9.addVertexWithUV(x + 26	, y + 26	, (double)zLevel, 1	, 1);
+        var9.addVertexWithUV(x + 26	, y			, (double)zLevel, 1	, 0);
+        var9.addVertexWithUV(x		, y			, (double)zLevel, 0	, 0);
+        var9.draw();
+    }
+    
 
     public static void drawSmallSlotBackground(Minecraft mc, int x, int y) {
 		int i = mc.renderEngine.getTexture("/logisticspipes/gui/slot-small.png");
 		GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
 		mc.renderEngine.bindTexture(i);
diff --git a/resources/logisticspipes/gui/slot-big.png b/resources/logisticspipes/gui/slot-big.png
new file mode 100644
index 00000000..63719902
Binary files /dev/null and b/resources/logisticspipes/gui/slot-big.png differ
diff --git a/resources/logisticspipes/item_textures.png b/resources/logisticspipes/item_textures.png
index 5ee7cda0..5b7164f9 100644
Binary files a/resources/logisticspipes/item_textures.png and b/resources/logisticspipes/item_textures.png differ

Vulnerable code: import org.lwjgl.opengl.GL11;

	public GuiCraftingPipe(EntityPlayer player, IInventory dummyInventory, BaseLogicCrafting logic) {
		dummy.addNormalSlotsForPlayerInventory(18, 97);
        	dummy.addDummySlot(l, 18 + l * 18, 18);
        
        //Output slot
        dummy.addDummySlot(9, 90, 64);
		xSize = 195;
		ySize = 187;
		controlList.add(new SmallGuiButton(0, (width-xSize) / 2 + 164, (height - ySize) / 2 + 50, 10,10, ">"));
		controlList.add(new SmallGuiButton(1, (width-xSize) / 2 + 129, (height - ySize) / 2 + 50, 10,10, "<"));
		//controlList.add(new SmallGuiButton(2, (width-xSize) / 2 + 138, (height - ySize) / 2 + 75, 30,10, "Paint"));
		controlList.add(new SmallGuiButton(3, (width-xSize) / 2 + 47, (height - ySize) / 2 + 50, 37,10, "Import"));
		controlList.add(new SmallGuiButton(4, (width-xSize) / 2 + 15, (height - ySize) / 2 + 50, 28,10, "Open"));
		for(int i = 0; i < 6; i++) {
			controlList.add(buttonarray[i] = new SmallGuiButton(5 + i, (width-xSize) / 2 + 20 + 18 * i, (height - ySize) / 2 + 37, 10,10, ">"));
			buttonarray[i].drawButton = false;
		controlList.add(new SmallGuiButton(20, (width-xSize) / 2 + 164, (height - ySize) / 2 + 85, 10,10, ">"));
		controlList.add(new SmallGuiButton(21, (width-xSize) / 2 + 129, (height - ySize) / 2 + 85, 10,10, "<"));
		case 2:
			return;
		fontRenderer.drawString("Output", 48, 67, 0x404040);
		fontRenderer.drawString("Inventory", 18, 86, 0x404040);
		fontRenderer.drawString("Satellite", 132, 7, 0x404040);
		
		if (_logic.satelliteId == 0){
			fontRenderer.drawString("Off", 144, 52, 0x404040);
			fontRenderer.drawString(""+_logic.satelliteId , 155 - fontRenderer.getStringWidth(""+_logic.satelliteId) , 52, 0x404040);
			/*
			if (_logic.isSatelliteConnected()){
				MinecraftForgeClient.bindTexture(mod_LogisticsPipes.LOGISTICSPIPE_ROUTED_TEXTURE_FILE);
			}else{
				MinecraftForgeClient.bindTexture(mod_LogisticsPipes.LOGISTICSPIPE_NOTROUTED_TEXTURE_FILE);
			}*/
			//TODO /\ /\ ???
	
			//GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
			//drawRect(0,1000,0,10000, 0xFFFF0000);
			//drawTexturedModalRect(155, 50, 10 * (xSize / 16) , 0, 10, 10);
			//MinecraftForgeClient.unbindTexture();
		fontRenderer.drawString("Priority:" , 132 , 75, 0x404040);
		fontRenderer.drawString(""+_logic.priority , 152 - (fontRenderer.getStringWidth(""+_logic.priority) / 2) , 87, 0x404040);
		int i = mc.renderEngine.getTexture("/logisticspipes/gui/crafting.png");
		GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
		mc.renderEngine.bindTexture(i);
		int j = guiLeft;
		int k = guiTop;

		drawTexturedModalRect(j, k, 0, 0, xSize, ySize);

		drawRect(400, 400, 0, 0, 0x404040);
		for(int count=36; count<42;count++) {
			Slot slot = inventorySlots.getSlot(count);
			if(slot != null && slot.getStack() != null && slot.getStack().getMaxStackSize() < 2) {
				drawRect(guiLeft + 18 + (18 * (count-36)), guiTop + 18, guiLeft + 18 + (18 * (count-36)) + 16, guiTop + 18 + 16, 0xFFFF0000);
				buttonarray[count - 36].drawButton = true;
			} else {
				buttonarray[count - 36].drawButton = false;
	protected int getNextConnectSatelliteId(boolean prev) {
					if (!prev && satellite.satelliteId > satelliteId && satellite.satelliteId < closestIdFound) {
						closestIdFound = satellite.satelliteId;
					} else if (prev && satellite.satelliteId < satelliteId && satellite.satelliteId > closestIdFound) {
						closestIdFound = satellite.satelliteId;
			return satelliteId;
			satelliteId = getNextConnectSatelliteId(false);
	public void setSatelliteId(int satelliteId) {
		this.satelliteId = satelliteId;
			satelliteId = getNextConnectSatelliteId(true);
		for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
			if (satellite.satelliteId == satelliteId) {
				CoreRoutedPipe satPipe = satellite.getRoutedPipe();
				if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
				IRouter satRouter = satPipe.getRouter();
				for (ExitRoute route:routes) {
					if (route.destination == satRouter) {
						return true;
	public IRouter getSatelliteRouter() {
		for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
			if (satellite.satelliteId == satelliteId) {
				CoreRoutedPipe satPipe = satellite.getRoutedPipe();
				if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
					continue;
				return satPipe.getRouter();
	/* ** NON NETWORKING ** */
	@SuppressWarnings("deprecation")
	public void paintPathToSatellite() {
		final IRouter satelliteRouter = getSatelliteRouter();
		if (satelliteRouter == null) {
			return;

		getRoutedPipe().getRouter().displayRouteTo(satelliteRouter.getSimpleID());

		Pair<Integer, Integer> result = new Pair<Integer, Integer>(null, 0);
		((BaseLogicCrafting) pipe.pipe.logic).setSatelliteId(packet.integer);
				return new GuiCraftingPipe(player, ((BaseLogicCrafting)pipe.pipe.logic).getDummyInventory(), (BaseLogicCrafting)pipe.pipe.logic);
					
		if ( stack == null) return null;
		if(craftingLogic.satelliteId != 0 && !hasSatellite) return null;
			if (i < 6 || !hasSatellite) {
				template.addRequirement(ItemIdentifierStack.GetFromStack(resourceStack), this);
			} else {
				template.addRequirement(ItemIdentifierStack.GetFromStack(resourceStack), (IRequestItems)craftingLogic.getSatelliteRouter().getPipe());
			}

	    	dummy.addRestrictedSlot(pipeSlot, inv, 8 + pipeSlot * 18, 18, LogisticsPipes.UpgradeItem.itemID);
		if(entityplayer.getCurrentEquippedItem() != null && entityplayer.getCurrentEquippedItem().itemID == LogisticsPipes.UpgradeItem.itemID) {
Fixed code: import logisticspipes.utils.gui.BasicGuiHelper;
	private final GuiButton[] normalButtonArray;
	private final GuiButton[][] advancedSatButtonArray;
	private final boolean isAdvancedSat;
	private final boolean isSplitedCrafting;
	public GuiCraftingPipe(EntityPlayer player, IInventory dummyInventory, BaseLogicCrafting logic, boolean isAdvancedSat, boolean isSplitedCrafting) {
		this.isAdvancedSat = isAdvancedSat;
		this.isSplitedCrafting = isSplitedCrafting;
		
		if(!isAdvancedSat && !isSplitedCrafting) {
			xSize = 177;
			ySize = 187;
		} else {
			xSize = 177;
			ySize = 187 + 30;
		}
		
		dummy.addNormalSlotsForPlayerInventory(8, ySize - 82);
        	dummy.addDummySlot(l, 8 + l * 18, 18);
        }

		//Output slot
        if(!isAdvancedSat) {
        	dummy.addDummySlot(9, 85, 55);
        } else {
        	dummy.addDummySlot(9, 85, 105);
		normalButtonArray = new GuiButton[6];
		advancedSatButtonArray = new GuiButton[9][2];
		for(int i=0;i<9;i++) {
			advancedSatButtonArray[i] = new GuiButton[2];
		}
		if(!isAdvancedSat) {
			controlList.add(normalButtonArray[0] = new SmallGuiButton(0, (width-xSize) / 2 + 155, (height - ySize) / 2 + 50, 10,10, ">"));
			controlList.add(normalButtonArray[1] = new SmallGuiButton(1, (width-xSize) / 2 + 120, (height - ySize) / 2 + 50, 10,10, "<"));
		}
		if(!isAdvancedSat) {
			controlList.add(normalButtonArray[2] = new SmallGuiButton(3, (width-xSize) / 2 + 39, (height - ySize) / 2 + 50, 37,10, "Import"));
			controlList.add(normalButtonArray[3] = new SmallGuiButton(4, (width-xSize) / 2 + 6, (height - ySize) / 2 + 50, 28,10, "Open"));
			for(int i = 0; i < 6; i++) {
				controlList.add(buttonarray[i] = new SmallGuiButton(5 + i, (width-xSize) / 2 + 12 + 18 * i, (height - ySize) / 2 + 30, 10,10, ">"));
				buttonarray[i].drawButton = false;
			}
			controlList.add(normalButtonArray[4] = new SmallGuiButton(20, (width-xSize) / 2 + 155, (height - ySize) / 2 + 85, 10,10, ">"));
			controlList.add(normalButtonArray[5] = new SmallGuiButton(21, (width-xSize) / 2 + 120, (height - ySize) / 2 + 85, 10,10, "<"));
		} else {
			for(int i=0;i<9;i++) {
				controlList.add(advancedSatButtonArray[i][0] = new SmallGuiButton(30 + i, (width-xSize) / 2 + 10 + 18 * i, (height - ySize) / 2 + 40, 15,10, "/\\"));
				controlList.add(advancedSatButtonArray[i][1] = new SmallGuiButton(40 + i, (width-xSize) / 2 + 10 + 18 * i, (height - ySize) / 2 + 70, 15,10, "\\/"));
			}
			controlList.add(normalButtonArray[2] = new SmallGuiButton(3, (width-xSize) / 2 + 39, (height - ySize) / 2 + 100, 37,10, "Import"));
			controlList.add(normalButtonArray[3] = new SmallGuiButton(4, (width-xSize) / 2 + 6, (height - ySize) / 2 + 100, 28,10, "Open"));
			controlList.add(normalButtonArray[4] = new SmallGuiButton(20, (width-xSize) / 2 + 155, (height - ySize) / 2 + 105, 10,10, ">"));
			controlList.add(normalButtonArray[5] = new SmallGuiButton(21, (width-xSize) / 2 + 120, (height - ySize) / 2 + 105, 10,10, "<"));
		if(30 <= guibutton.id && guibutton.id < 40) {
			_logic.setNextSatellite(_player, guibutton.id - 30);
		}
		if(40 <= guibutton.id && guibutton.id < 50) {
			_logic.setPrevSatellite(_player, guibutton.id - 40);
		}
		/*case 2:
			return;*/
		fontRenderer.drawString("Inventory", 10, ySize - 93, 0x404040);
		if(!isAdvancedSat) {
			fontRenderer.drawString("Output", 77, 40, 0x404040);
			fontRenderer.drawString("Satellite", 123, 7, 0x404040);
			if (_logic.satelliteId == 0) {
				fontRenderer.drawString("Off", 135, 52, 0x404040);
			} else {
				fontRenderer.drawString(""+_logic.satelliteId , 146 - fontRenderer.getStringWidth(""+_logic.satelliteId) , 52, 0x404040);
			}
			fontRenderer.drawString("Priority:" , 123 , 75, 0x404040);
			fontRenderer.drawString(""+_logic.priority , 143 - (fontRenderer.getStringWidth(""+_logic.priority) / 2) , 87, 0x404040);
			for(int i=0; i<9;i++) {
				if (_logic.advancedSatelliteIdArray[i] == 0) {
					fontRenderer.drawString("Off", 10 + (i * 18), 57, 0x404040);
				} else {
					fontRenderer.drawString(""+_logic.advancedSatelliteIdArray[i] , 20 - fontRenderer.getStringWidth(""+_logic.advancedSatelliteIdArray[i]) + (i * 18), 57, 0x404040);
				}
			}
			fontRenderer.drawString("Output", 77, 90, 0x404040);
			fontRenderer.drawString("Priority:" , 123 , 95, 0x404040);
			fontRenderer.drawString(""+_logic.priority , 143 - (fontRenderer.getStringWidth(""+_logic.priority) / 2) , 107, 0x404040);
		BasicGuiHelper.drawGuiBackGround(mc, guiLeft, guiTop, guiLeft + xSize, guiTop + ySize, zLevel, true, true, true, true, true);
		if(!isAdvancedSat) {
			drawRect(guiLeft + 116, guiTop + 4, guiLeft + 170, guiTop + 70, 0xff8B8B8B);
		}
		
		for(int i=0; i<9;i++) {
			BasicGuiHelper.drawSlotBackground(mc, guiLeft + 7 + (18*i), guiTop + 17);
		}
		if(!isAdvancedSat) {
			BasicGuiHelper.drawBigSlotBackground(mc, guiLeft + 80, guiTop + 50);
		} else {
			BasicGuiHelper.drawBigSlotBackground(mc, guiLeft + 80, guiTop + 100);
		}
		BasicGuiHelper.drawPlayerInventoryBackground(mc, guiLeft + 8, guiTop + ySize - 82);
		
		if(!isAdvancedSat) {
			for(int count=36; count<42;count++) {
				Slot slot = inventorySlots.getSlot(count);
				if(slot != null && slot.getStack() != null && slot.getStack().getMaxStackSize() < 2) {
					drawRect(guiLeft + 18 + (18 * (count-36)), guiTop + 18, guiLeft + 18 + (18 * (count-36)) + 16, guiTop + 18 + 16, 0xFFFF0000);
					buttonarray[count - 36].drawButton = true;
				} else {
					buttonarray[count - 36].drawButton = false;
				}
import logisticspipes.pipes.upgrades.AdvancedSatelliteUpgrade;
import logisticspipes.pipes.upgrades.SplitCraftingCrafterUpgrade;
import logisticspipes.pipes.upgrades.SplitCraftingSatelliteUpgrade;
	
	//Crafting Upgrades
	public static final int ADVANCED_SAT_CRAFTINGPIPE = 21;
	public static final int SAT_DISTRIBUTING_CRAFTER = 22;
	public static final int SAT_DISTRIBUTING_SATELITE = 23;
		registerUpgrade(ADVANCED_SAT_CRAFTINGPIPE, "Advanced Satellite Upgrade", AdvancedSatelliteUpgrade.class, 9 * 16 + 13);
		registerUpgrade(SAT_DISTRIBUTING_CRAFTER, "Split Crafting Upgrade (Crafter)", SplitCraftingCrafterUpgrade.class, 9 * 16 + 14);
		registerUpgrade(SAT_DISTRIBUTING_SATELITE, "Split Crafting Upgrade (Satellite)", SplitCraftingSatelliteUpgrade.class, 9 * 16 + 15);
import logisticspipes.network.packets.GuiArgumentPacket;
import logisticspipes.network.packets.PacketModuleInteger;
	@TileNetworkData(staticSize=9)
	public int advancedSatelliteIdArray[] = new int[9];

	protected int getNextConnectSatelliteId(boolean prev, int x, int y) {
					if(x == -1 && y == -1) {
						if (!prev && satellite.satelliteId > satelliteId && satellite.satelliteId < closestIdFound) {
							closestIdFound = satellite.satelliteId;
						} else if (prev && satellite.satelliteId < satelliteId && satellite.satelliteId > closestIdFound) {
							closestIdFound = satellite.satelliteId;
						}
					} else if(y == -1) {
						if (!prev && satellite.satelliteId > advancedSatelliteIdArray[x] && satellite.satelliteId < closestIdFound) {
							closestIdFound = satellite.satelliteId;
						} else if (prev && satellite.satelliteId < advancedSatelliteIdArray[x] && satellite.satelliteId > closestIdFound) {
							closestIdFound = satellite.satelliteId;
						}
					} else {
						//TODO
			if(x == -1 && y == -1) {
				return satelliteId;
			} else if(y == -1) {
				return advancedSatelliteIdArray[x];
			} else {
				//TODO
			}
			satelliteId = getNextConnectSatelliteId(false, -1, -1);
	public void setSatelliteId(int satelliteId, int x, int y) {
		if(x == -1 && y == -1) {
			this.satelliteId = satelliteId;
		} else if(y == -1) {
			advancedSatelliteIdArray[x] = satelliteId;
		} else {
			//TODO
		}
			satelliteId = getNextConnectSatelliteId(true, -1, -1);
		if(!((CoreRoutedPipe)this.container.pipe).getUpgradeManager().isAdvancedSatelliteCrafter()) {
			if(satelliteId == 0) return true;
			for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
				if (satellite.satelliteId == satelliteId) {
					CoreRoutedPipe satPipe = satellite.getRoutedPipe();
					if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
						continue;
					IRouter satRouter = satPipe.getRouter();
					for (ExitRoute route:routes) {
						if (route.destination == satRouter) {
							return true;
						}
					}
				}
			}
		} else {
			boolean foundAll = true;
			for(int i=0;i<9;i++) {
				boolean foundOne = false;
				if(advancedSatelliteIdArray[i] == 0) {
				}
				for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
					if (satellite.satelliteId == advancedSatelliteIdArray[i]) {
						CoreRoutedPipe satPipe = satellite.getRoutedPipe();
						if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
							continue;
						IRouter satRouter = satPipe.getRouter();
						for (ExitRoute route:routes) {
							if (route.destination == satRouter) {
								foundOne = true;
								break;
							}
						}
				foundAll &= foundOne;
			return foundAll;
	public IRouter getSatelliteRouter(int x, int y) {
		if(x == -1 && y == -1) {
			for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
				if (satellite.satelliteId == satelliteId) {
					CoreRoutedPipe satPipe = satellite.getRoutedPipe();
					if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
						continue;
					return satPipe.getRouter();
				}
			}
		} else if(y == -1) {
			for (final BaseLogicSatellite satellite : BaseLogicSatellite.AllSatellites) {
				if (satellite.satelliteId == advancedSatelliteIdArray[x]) {
					CoreRoutedPipe satPipe = satellite.getRoutedPipe();
					if(satPipe == null || satPipe.stillNeedReplace() || satPipe.getRouter() == null)
						continue;
					return satPipe.getRouter();
				}
		} else {
			//TODO
			MainProxy.sendPacketToPlayer(new GuiArgumentPacket(GuiIDs.GUI_CRAFTINGPIPE_ID, new Object[]{((CoreRoutedPipe)this.container.pipe).getUpgradeManager().isAdvancedSatelliteCrafter(), ((CoreRoutedPipe)this.container.pipe).getUpgradeManager().isSatelliteCraftingCrafter()}).getPacket(),  (Player) entityplayer);
	public void setNextSatellite(EntityPlayer player, int i) {
		if (MainProxy.isClient(player.worldObj)) {
			final PacketCoordinates packet = new PacketPipeInteger(NetworkConstants.CRAFTING_PIPE_NEXT_SATELLITE_ADVANCED, xCoord, yCoord, zCoord, i);
			MainProxy.sendPacketToServer(packet.getPacket());
		} else {
			advancedSatelliteIdArray[i] = getNextConnectSatelliteId(false, i, -1);
			final PacketModuleInteger packet = new PacketModuleInteger(NetworkConstants.CRAFTING_PIPE_SATELLITE_ID_ADVANCED, xCoord, yCoord, zCoord, i, advancedSatelliteIdArray[i]);
			MainProxy.sendPacketToPlayer(packet.getPacket(), (Player)player);
	public void setPrevSatellite(EntityPlayer player, int i) {
		if (MainProxy.isClient(player.worldObj)) {
			final PacketCoordinates packet = new PacketPipeInteger(NetworkConstants.CRAFTING_PIPE_PREV_SATELLITE_ADVANCED, xCoord, yCoord, zCoord, i);
			MainProxy.sendPacketToServer(packet.getPacket());
		} else {
			advancedSatelliteIdArray[i] = getNextConnectSatelliteId(true, i, -1);
			final PacketModuleInteger packet = new PacketModuleInteger(NetworkConstants.CRAFTING_PIPE_SATELLITE_ID_ADVANCED, xCoord, yCoord, zCoord, i, advancedSatelliteIdArray[i]);
			MainProxy.sendPacketToPlayer(packet.getPacket(), (Player)player);
		}
	}
		Pair<Integer, Integer> result = new Pair<Integer, Integer>(0, 0);
			node.add(content);
import logisticspipes.network.packets.GuiArgumentPacket;
				case NetworkConstants.GUI_ARGUMENT_PACKET:
					final GuiArgumentPacket packetBc = new GuiArgumentPacket();
					packetBc.readData(data);
					GuiHandler.argumentQueue.put(packetBc.guiID, packetBc.args);
					break;
				case NetworkConstants.CRAFTING_PIPE_SATELLITE_ID_ADVANCED:
					final PacketModuleInteger packetBd = new PacketModuleInteger();
					packetBd.readData(data);
					onCraftingPipeSetSatelliteAdvanced(packetBd);
					break;
					
		((BaseLogicCrafting) pipe.pipe.logic).setSatelliteId(packet.integer, -1, -1);

	private static void onCraftingPipeSetSatelliteAdvanced(PacketModuleInteger packet) {
		final TileGenericPipe pipe = getPipe(FMLClientHandler.instance().getClient().theWorld, packet.posX, packet.posY, packet.posZ);
		if (pipe == null) {
			return;
		}

		if (!(pipe.pipe.logic instanceof BaseLogicCrafting)) {
			return;
		}

		((BaseLogicCrafting) pipe.pipe.logic).setSatelliteId(packet.integer, packet.slot, -1);
	}
import java.util.HashMap;
import java.util.Map;

	
	public final static Map<Integer, Object[]> argumentQueue = new HashMap<Integer, Object[]>();
		Object[] args = argumentQueue.get(GuiIDs.GUI_CRAFTINGPIPE_ID);
		
				if(args == null) {
					new UnsupportedOperationException("Arguments missing").printStackTrace();
					return null;
				}
				return new GuiCraftingPipe(player, ((BaseLogicCrafting)pipe.pipe.logic).getDummyInventory(), (BaseLogicCrafting)pipe.pipe.logic, (Boolean) args[0], (Boolean) args[1]);
	public static final int GUI_ARGUMENT_PACKET = 97;
	public static final int CRAFTING_PIPE_NEXT_SATELLITE_ADVANCED = 98;
	public static final int CRAFTING_PIPE_PREV_SATELLITE_ADVANCED = 99;
	public static final int CRAFTING_PIPE_SATELLITE_ID_ADVANCED = 100;
				case NetworkConstants.CRAFTING_PIPE_NEXT_SATELLITE_ADVANCED:
					final PacketPipeInteger packetBd = new PacketPipeInteger();
					packetBd.readData(data);
					onCraftingPipeNextSatelliteAdvanced(player, packetBd);
					break;
				case NetworkConstants.CRAFTING_PIPE_PREV_SATELLITE_ADVANCED:
					final PacketPipeInteger packetBe = new PacketPipeInteger();
					packetBe.readData(data);
					onCraftingPipePrevSatelliteAdvanced(player, packetBe);
					break;

	private static void onCraftingPipeNextSatelliteAdvanced(EntityPlayerMP player, PacketPipeInteger packet) {
		final TileGenericPipe pipe = getPipe(player.worldObj, packet.posX, packet.posY, packet.posZ);
		if (pipe == null) {
			return;
		}

		if (!(pipe.pipe.logic instanceof BaseLogicCrafting)) {
			return;
		}

		((BaseLogicCrafting) pipe.pipe.logic).setNextSatellite(player, packet.integer);
	}

	private static void onCraftingPipePrevSatelliteAdvanced(EntityPlayerMP player, PacketPipeInteger packet) {
		final TileGenericPipe pipe = getPipe(player.worldObj, packet.posX, packet.posY, packet.posZ);
		if (pipe == null) {
			return;
		}

		if (!(pipe.pipe.logic instanceof BaseLogicCrafting)) {
			return;
		}

		((BaseLogicCrafting) pipe.pipe.logic).setPrevSatellite(player, packet.integer);
	}
package logisticspipes.network.packets;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

import logisticspipes.network.NetworkConstants;

public class GuiArgumentPacket extends LogisticsPipesPacket {
	
	public Object[] args;
	public int guiID = 0;
	
	public GuiArgumentPacket() {
		super();
	}
	
	public GuiArgumentPacket(int Id, Object... arg) {
		super();
		args = arg;
		guiID = Id;
	}
	
	@Override
	public int getID() {
		return NetworkConstants.GUI_ARGUMENT_PACKET;
	}

	@Override
	public void readData(DataInputStream data) throws IOException {
		guiID = data.readInt();
		int size = data.readInt();
		args = new Object[size];
		for(int i=0; i < size;i++) {
			int arraySize = data.readInt();
			byte[] bytes = new byte[arraySize];
			data.read(bytes);
			ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
			ObjectInput in = null;
			in = new ObjectInputStream(bis);
			try {
				Object o = in.readObject();
				args[i] = o;
			} catch (ClassNotFoundException e) {
				throw new UnsupportedOperationException(e);
			} 
		}
	}

	@Override
	public void writeData(DataOutputStream data) throws IOException {
		data.writeInt(guiID);
		data.writeInt(args.length);
		for(int i=0; i<args.length;i++) {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutput out = null;
			out = new ObjectOutputStream(bos); 
			out.writeObject(args[i]);
			byte[] bytes = bos.toByteArray();
			data.writeInt(bytes.length);
			data.write(bytes);
		}
	}
}
		if (stack == null) return null;
		
		IRequestItems[] target = new IRequestItems[9];
		for(int i=0;i<9;i++) {
			target[i] = this;
		}
		if(!hasSatellite) return null;
		if(!getUpgradeManager().isAdvancedSatelliteCrafter()) {
			if(craftingLogic.satelliteId != 0) {
				IRequestItems sat = (IRequestItems)craftingLogic.getSatelliteRouter(-1, -1).getPipe();
				for(int i=6;i<9;i++) {
					target[i] = sat;
				}
			}
		} else {
			for(int i=0;i<9;i++) {
				if(craftingLogic.advancedSatelliteIdArray[i] != 0) {
					target[i] = (IRequestItems)craftingLogic.getSatelliteRouter(i, -1).getPipe();
				}
			}
		}
			template.addRequirement(ItemIdentifierStack.GetFromStack(resourceStack), target[i]);
import java.util.Set;
import java.util.TreeSet;
import logisticspipes.utils.ItemIdentifier;


	@Override //work in progress, currently not active code.
	public Set<ItemIdentifier> getSpecificInterests() {
		Set<ItemIdentifier> l1 = new TreeSet<ItemIdentifier>();;
		for(Pair<TileEntity, ForgeDirection> pair:getAdjacentTanks(false)) {
			ILiquidTank[] tanks = ((ITankContainer)pair.getValue1()).getTanks(pair.getValue2().getOpposite());
			for(ILiquidTank tank:tanks) {
				LiquidStack liquid;
				if((liquid = tank.getLiquid()) != null && liquid.itemID != 0) {
					LiquidIdentifier ident = LiquidIdentifier.get(liquid);
					l1.add(ident.getItemIdentifier());
				}
			}
		}
		return l1;
	}
package logisticspipes.pipes.upgrades;

import logisticspipes.pipes.PipeItemsCraftingLogistics;
import logisticspipes.pipes.basic.CoreRoutedPipe;

public class AdvancedSatelliteUpgrade implements IPipeUpgrade {

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

	@Override
	public boolean isAllowed(CoreRoutedPipe pipe) {
		return pipe instanceof PipeItemsCraftingLogistics;
	}
}
import logisticspipes.pipes.basic.CoreRoutedPipe;

	@Override
	public boolean isAllowed(CoreRoutedPipe pipe) {
		return true;
	}
import logisticspipes.pipes.basic.CoreRoutedPipe;
	boolean isAllowed(CoreRoutedPipe pipe);
import logisticspipes.pipes.basic.CoreRoutedPipe;

	@Override
	public boolean isAllowed(CoreRoutedPipe pipe) {
		return true;
	}
import logisticspipes.pipes.basic.CoreRoutedPipe;

	
	@Override
	public boolean isAllowed(CoreRoutedPipe pipe) {
		return true;
	}
package logisticspipes.pipes.upgrades;

import logisticspipes.pipes.PipeItemsCraftingLogistics;
import logisticspipes.pipes.basic.CoreRoutedPipe;

public class SplitCraftingCrafterUpgrade implements IPipeUpgrade {

	@Override
	public boolean needsUpdate() {
		return false;
	}
	
	@Override
	public boolean isAllowed(CoreRoutedPipe pipe) {
		return pipe instanceof PipeItemsCraftingLogistics;
	}
}
package logisticspipes.pipes.upgrades;

import logisticspipes.pipes.PipeItemsSatelliteLogistics;
import logisticspipes.pipes.basic.CoreRoutedPipe;

public class SplitCraftingSatelliteUpgrade implements IPipeUpgrade {

	@Override
	public boolean needsUpdate() {
		return false;
	}
	
	@Override
	public boolean isAllowed(CoreRoutedPipe pipe) {
		return pipe instanceof PipeItemsSatelliteLogistics;
	}
}
	private boolean isAdvancedCrafter = false;
	private boolean isSatelliteCraftingSatellite = false;
	private boolean isSatelliteCraftingCrafter = false;
		isAdvancedCrafter = false;
		isSatelliteCraftingSatellite = false;
		isSatelliteCraftingCrafter = false;
			} else if(upgrade instanceof SplitCraftingCrafterUpgrade) {
				isSatelliteCraftingCrafter = true;
			} else if(upgrade instanceof SplitCraftingSatelliteUpgrade) {
				isSatelliteCraftingSatellite = true;
			} else if(upgrade instanceof AdvancedSatelliteUpgrade) {
				isAdvancedCrafter = true;
	    	dummy.addRestrictedSlot(pipeSlot, inv, 8 + pipeSlot * 18, 18, new ISlotCheck() {
				@Override
				public boolean isStackAllowed(ItemStack itemStack) {
					if(itemStack == null) return false;
					if(itemStack.itemID == LogisticsPipes.UpgradeItem.itemID) {
						if(!LogisticsPipes.UpgradeItem.getUpgradeForItem(itemStack, null).isAllowed(pipe)) return false;
					} else {
						return false;
					}
					return true;
				}
	    	});
		if(entityplayer.getCurrentEquippedItem() != null && entityplayer.getCurrentEquippedItem().itemID == LogisticsPipes.UpgradeItem.itemID && LogisticsPipes.UpgradeItem.getUpgradeForItem(entityplayer.getCurrentEquippedItem(), null).isAllowed(pipe)) {
	
	public boolean isAdvancedSatelliteCrafter() {
		return isAdvancedCrafter;
	}
	
	public boolean isSatelliteCraftingSatellite() {
		return isSatelliteCraftingSatellite;
	}
	
	public boolean isSatelliteCraftingCrafter() {
		return isSatelliteCraftingCrafter;
	}
    public static void drawBigSlotBackground(Minecraft mc, int x, int y) {
		int i = mc.renderEngine.getTexture("/logisticspipes/gui/slot-big.png");
		GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
		mc.renderEngine.bindTexture(i);
		
		Tessellator var9 = Tessellator.instance;
        var9.startDrawingQuads();
        var9.addVertexWithUV(x		, y + 26	, (double)zLevel, 0	, 1);
        var9.addVertexWithUV(x + 26	, y + 26	, (double)zLevel, 1	, 1);
        var9.addVertexWithUV(x + 26	, y			, (double)zLevel, 1	, 0);
        var9.addVertexWithUV(x		, y			, (double)zLevel, 0	, 0);
        var9.draw();
    }