CVE-2023-38689 (Java, published 2023-08-04T17:15Z)
Description: 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.
Severity: nan (CVSS v3 base score: 9.8)
Weakness: CWE-502 \u2014 Deserialization of Untrusted Data
The product deserializes untrusted data without sufficiently verifying that the resulting data will be valid.
Repository: https://github.com/RS485/LogisticsPipes
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 message: Added AdvancedSatellite Upgrade.


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();
    }