diff --git a/common/mekanism/api/GasNetwork.java b/common/mekanism/api/GasNetwork.java index a5aa6d87e..1dae4595a 100644 --- a/common/mekanism/api/GasNetwork.java +++ b/common/mekanism/api/GasNetwork.java @@ -8,6 +8,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Set; import net.minecraft.tileentity.TileEntity; @@ -264,11 +265,14 @@ public class GasNetwork implements ITransmitterNetwork public void register() { - IPressurizedTube aTube = tubes.iterator().next(); - if(aTube instanceof TileEntity && !((TileEntity)aTube).worldObj.isRemote) - { - TransmitterNetworkRegistry.getInstance().registerNetwork(this); - } + try { + IPressurizedTube aTube = tubes.iterator().next(); + + if(aTube instanceof TileEntity && !((TileEntity)aTube).worldObj.isRemote) + { + TransmitterNetworkRegistry.getInstance().registerNetwork(this); + } + } catch(NoSuchElementException e) {} } public void deregister() diff --git a/common/mekanism/api/TransmitterNetworkRegistry.java b/common/mekanism/api/TransmitterNetworkRegistry.java index e31068c7c..d209137ff 100644 --- a/common/mekanism/api/TransmitterNetworkRegistry.java +++ b/common/mekanism/api/TransmitterNetworkRegistry.java @@ -58,7 +58,8 @@ public class TransmitterNetworkRegistry implements ITickHandler @Override public void tickEnd(EnumSet type, Object... tickData) { - Set iterNetworks = (Set) networks.clone(); + Set iterNetworks = (Set)networks.clone(); + for(ITransmitterNetwork net : iterNetworks) { if(networks.contains(net)) @@ -77,7 +78,7 @@ public class TransmitterNetworkRegistry implements ITickHandler @Override public String getLabel() { - return "Mekanism Energy Networks"; + return "Mekanism Transmitter Networks"; } @Override diff --git a/common/mekanism/client/RenderLogisticalTransporter.java b/common/mekanism/client/RenderLogisticalTransporter.java index 746019b93..7a02c5227 100644 --- a/common/mekanism/client/RenderLogisticalTransporter.java +++ b/common/mekanism/client/RenderLogisticalTransporter.java @@ -23,7 +23,7 @@ public class RenderLogisticalTransporter extends TileEntitySpecialRenderer @SuppressWarnings("incomplete-switch") public void renderAModelAt(TileEntityLogisticalTransporter tileEntity, double x, double y, double z, float partialTick) { - func_110628_a(MekanismUtils.getResource(ResourceType.RENDER, "LogisticalTransporter.png")); + func_110628_a(MekanismUtils.getResource(ResourceType.RENDER, "LogisticalTransporter" + (tileEntity.isActive ? "Active" : "") + ".png")); GL11.glPushMatrix(); GL11.glTranslatef((float)x + 0.5F, (float)y + 1.5F, (float)z + 0.5F); GL11.glScalef(1.0F, -1F, -1F); diff --git a/common/mekanism/common/BlockTransmitter.java b/common/mekanism/common/BlockTransmitter.java index e329daae1..ef0c0f9f7 100644 --- a/common/mekanism/common/BlockTransmitter.java +++ b/common/mekanism/common/BlockTransmitter.java @@ -276,6 +276,10 @@ public class BlockTransmitter extends Block { ((IPressurizedTube)tileEntity).refreshNetwork(); } + else if(tileEntity instanceof ILogisticalTransporter) + { + ((ILogisticalTransporter)tileEntity).refreshNetwork(); + } } } @@ -298,6 +302,10 @@ public class BlockTransmitter extends Block { ((IPressurizedTube)tileEntity).refreshNetwork(); } + else if(tileEntity instanceof ILogisticalTransporter) + { + ((ILogisticalTransporter)tileEntity).refreshNetwork(); + } } } diff --git a/common/mekanism/common/EnergyNetwork.java b/common/mekanism/common/EnergyNetwork.java index 22ec14412..650a9f7c4 100644 --- a/common/mekanism/common/EnergyNetwork.java +++ b/common/mekanism/common/EnergyNetwork.java @@ -10,6 +10,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Set; import cpw.mods.fml.common.FMLCommonHandler; @@ -368,11 +369,14 @@ public class EnergyNetwork implements ITransmitterNetwork public void register() { - IUniversalCable aCable = cables.iterator().next(); - if(aCable instanceof TileEntity && !((TileEntity)aCable).worldObj.isRemote) - { - TransmitterNetworkRegistry.getInstance().registerNetwork(this); - } + try { + IUniversalCable aCable = cables.iterator().next(); + + if(aCable instanceof TileEntity && !((TileEntity)aCable).worldObj.isRemote) + { + TransmitterNetworkRegistry.getInstance().registerNetwork(this); + } + } catch(NoSuchElementException e) {} } public void deregister() diff --git a/common/mekanism/common/FluidNetwork.java b/common/mekanism/common/FluidNetwork.java index 983e8945d..57035ba5b 100644 --- a/common/mekanism/common/FluidNetwork.java +++ b/common/mekanism/common/FluidNetwork.java @@ -8,6 +8,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Set; import mekanism.api.ITransmitterNetwork; @@ -268,11 +269,14 @@ public class FluidNetwork implements ITransmitterNetwork public void register() { - IMechanicalPipe aPipe = pipes.iterator().next(); - if(aPipe instanceof TileEntity && !((TileEntity)aPipe).worldObj.isRemote) - { - TransmitterNetworkRegistry.getInstance().registerNetwork(this); - } + try { + IMechanicalPipe aPipe = pipes.iterator().next(); + + if(aPipe instanceof TileEntity && !((TileEntity)aPipe).worldObj.isRemote) + { + TransmitterNetworkRegistry.getInstance().registerNetwork(this); + } + } catch(NoSuchElementException e) {} } public void deregister() diff --git a/common/mekanism/common/ILogisticalTransporter.java b/common/mekanism/common/ILogisticalTransporter.java index b1c29de5c..bb24339d4 100644 --- a/common/mekanism/common/ILogisticalTransporter.java +++ b/common/mekanism/common/ILogisticalTransporter.java @@ -2,5 +2,40 @@ package mekanism.common; public interface ILogisticalTransporter { + /** + * Gets the InventoryNetwork currently in use by this transporter segment. + * @return InventoryNetwork this transporter is using + */ + public InventoryNetwork getNetwork(); + + /** + * Gets the InventoryNetwork currently in use by this transporter segment. + * @param createIfNull - If true, the transporter will try and connect to an + * adjacent network, merging several if necessary, or creating a new one + * if none is available + * @return InventoryNetwork this transporter is using + */ + public InventoryNetwork getNetwork(boolean createIfNull); + + /** + * Sets this transporter segment's InventoryNetwork to a new value. + * @param network - InventoryNetwork to set to + */ + public void setNetwork(InventoryNetwork network); + + /** + * Refreshes the transporter's InventoryNetwork. + */ + public void refreshNetwork(); + + /** + * Remove a transporter from its network. + */ + public void removeFromNetwork(); + /** + * Call this if you're worried a transporter's network is messed up and you want + * it to try and fix itself. + */ + public void fixNetwork(); } diff --git a/common/mekanism/common/InventoryNetwork.java b/common/mekanism/common/InventoryNetwork.java new file mode 100644 index 000000000..02c125044 --- /dev/null +++ b/common/mekanism/common/InventoryNetwork.java @@ -0,0 +1,326 @@ +package mekanism.common; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +import mekanism.api.ITransmitterNetwork; +import mekanism.api.Object3D; +import mekanism.api.TransmitterNetworkRegistry; +import net.minecraft.inventory.IInventory; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import net.minecraftforge.event.ForgeSubscribe; +import net.minecraftforge.event.world.ChunkEvent; + +public class InventoryNetwork implements ITransmitterNetwork +{ + public HashSet transporters = new HashSet(); + + public Set possibleAcceptors = new HashSet(); + public Map acceptorDirections = new HashMap(); + + private int ticksSinceCreate = 0; + private int ticksSinceSecond = 0; + private boolean fixed = false; + + public InventoryNetwork(ILogisticalTransporter... varTransporters) + { + transporters.addAll(Arrays.asList(varTransporters)); + register(); + } + + public InventoryNetwork(Set networks) + { + for(InventoryNetwork net : networks) + { + if(net != null) + { + addAllTransporters(net.transporters); + net.deregister(); + } + } + + refresh(); + register(); + } + + public void refresh() + { + Set iterPipes = (Set)transporters.clone(); + Iterator it = iterPipes.iterator(); + + possibleAcceptors.clear(); + acceptorDirections.clear(); + + while(it.hasNext()) + { + ILogisticalTransporter conductor = (ILogisticalTransporter)it.next(); + + if(conductor == null || ((TileEntity)conductor).isInvalid()) + { + it.remove(); + transporters.remove(conductor); + } + else { + conductor.setNetwork(this); + } + } + + for(ILogisticalTransporter pipe : iterPipes) + { + IInventory[] inventories = TransporterUtils.getConnectedInventories((TileEntity)pipe); + + for(IInventory inventory : inventories) + { + if(inventory != null && !(inventory instanceof ILogisticalTransporter)) + { + possibleAcceptors.add(inventory); + acceptorDirections.put(inventory, ForgeDirection.getOrientation(Arrays.asList(inventories).indexOf(inventory))); + } + } + } + } + + public void merge(InventoryNetwork network) + { + if(network != null && network != this) + { + Set networks = new HashSet(); + networks.add(this); + networks.add(network); + InventoryNetwork newNetwork = new InventoryNetwork(networks); + newNetwork.refresh(); + } + } + + public void addAllTransporters(Set newPipes) + { + transporters.addAll(newPipes); + } + + public void split(ILogisticalTransporter splitPoint) + { + if(splitPoint instanceof TileEntity) + { + removeTransporter(splitPoint); + + TileEntity[] connectedBlocks = new TileEntity[6]; + boolean[] dealtWith = {false, false, false, false, false, false}; + + for(ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) + { + TileEntity sideTile = Object3D.get((TileEntity)splitPoint).getFromSide(direction).getTileEntity(((TileEntity)splitPoint).worldObj); + + if(sideTile != null) + { + connectedBlocks[Arrays.asList(ForgeDirection.values()).indexOf(direction)] = sideTile; + } + } + + for(int countOne = 0; countOne < connectedBlocks.length; countOne++) + { + TileEntity connectedBlockA = connectedBlocks[countOne]; + + if(connectedBlockA instanceof ILogisticalTransporter && !dealtWith[countOne]) + { + NetworkFinder finder = new NetworkFinder(((TileEntity)splitPoint).worldObj, Object3D.get(connectedBlockA), Object3D.get((TileEntity)splitPoint)); + List partNetwork = finder.exploreNetwork(); + + for(int countTwo = countOne + 1; countTwo < connectedBlocks.length; countTwo++) + { + TileEntity connectedBlockB = connectedBlocks[countTwo]; + + if(connectedBlockB instanceof ILogisticalTransporter && !dealtWith[countTwo]) + { + if(partNetwork.contains(Object3D.get(connectedBlockB))) + { + dealtWith[countTwo] = true; + } + } + } + + Set newNetTransporters= new HashSet(); + + for(Object3D node : finder.iterated) + { + TileEntity nodeTile = node.getTileEntity(((TileEntity)splitPoint).worldObj); + + if(nodeTile instanceof ILogisticalTransporter) + { + if(nodeTile != splitPoint) + { + newNetTransporters.add((ILogisticalTransporter)nodeTile); + } + } + } + + InventoryNetwork newNetwork = new InventoryNetwork(newNetTransporters.toArray(new ILogisticalTransporter[0])); + newNetwork.refresh(); + } + } + + deregister(); + } + } + + public void fixMessedUpNetwork(ILogisticalTransporter pipe) + { + if(pipe instanceof TileEntity) + { + NetworkFinder finder = new NetworkFinder(((TileEntity)pipe).getWorldObj(), Object3D.get((TileEntity)pipe), null); + List partNetwork = finder.exploreNetwork(); + Set newTransporters = new HashSet(); + + for(Object3D node : partNetwork) + { + TileEntity nodeTile = node.getTileEntity(((TileEntity)pipe).worldObj); + + if(nodeTile instanceof ILogisticalTransporter) + { + ((ILogisticalTransporter)nodeTile).removeFromNetwork(); + newTransporters.add((ILogisticalTransporter)nodeTile); + } + } + + InventoryNetwork newNetwork = new InventoryNetwork(newTransporters.toArray(new ILogisticalTransporter[0])); + newNetwork.refresh(); + newNetwork.fixed = true; + deregister(); + } + } + + public void removeTransporter(ILogisticalTransporter pipe) + { + transporters.remove(pipe); + if(transporters.size() == 0) + { + deregister(); + } + } + + public void register() + { + try { + ILogisticalTransporter aTransporter = transporters.iterator().next(); + + if(aTransporter instanceof TileEntity && !((TileEntity)aTransporter).worldObj.isRemote) + { + TransmitterNetworkRegistry.getInstance().registerNetwork(this); + } + } catch(NoSuchElementException e) {} + } + + public void deregister() + { + transporters.clear(); + + TransmitterNetworkRegistry.getInstance().removeNetwork(this); + } + + public static class NetworkFinder + { + public World worldObj; + public Object3D start; + + public List iterated = new ArrayList(); + public List toIgnore = new ArrayList(); + + public NetworkFinder(World world, Object3D location, Object3D... ignore) + { + worldObj = world; + start = location; + + if(ignore != null) + { + toIgnore = Arrays.asList(ignore); + } + } + + public void loopAll(Object3D location) + { + if(location.getTileEntity(worldObj) instanceof ILogisticalTransporter) + { + iterated.add(location); + } + + for(ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) + { + Object3D obj = location.getFromSide(direction); + + if(!iterated.contains(obj) && !toIgnore.contains(obj)) + { + TileEntity tileEntity = obj.getTileEntity(worldObj); + + if(tileEntity instanceof ILogisticalTransporter) + { + loopAll(obj); + } + } + } + } + + public List exploreNetwork() + { + loopAll(start); + + return iterated; + } + } + + public static class NetworkLoader + { + @ForgeSubscribe + public void onChunkLoad(ChunkEvent.Load event) + { + if(event.getChunk() != null) + { + for(Object obj : event.getChunk().chunkTileEntityMap.values()) + { + if(obj instanceof TileEntity) + { + TileEntity tileEntity = (TileEntity)obj; + + if(tileEntity instanceof ILogisticalTransporter) + { + ((ILogisticalTransporter)tileEntity).refreshNetwork(); + } + } + } + } + } + } + + public void tick() + { + //Fix weird behaviour periodically. + if(!fixed) + { + ++ticksSinceCreate; + if(ticksSinceCreate > 1200) + { + ticksSinceCreate = 0; + fixMessedUpNetwork(transporters.iterator().next()); + } + } + } + + @Override + public String toString() + { + return "[InventoryNetwork] " + transporters.size() + " pipes, " + possibleAcceptors.size() + " acceptors."; + } + + @Override + public int getSize() + { + return transporters.size(); + } +} diff --git a/common/mekanism/common/ItemConfigurator.java b/common/mekanism/common/ItemConfigurator.java index fc7edc113..92dae7b85 100644 --- a/common/mekanism/common/ItemConfigurator.java +++ b/common/mekanism/common/ItemConfigurator.java @@ -17,7 +17,6 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ChatMessageComponent; import net.minecraft.world.World; import net.minecraftforge.common.ForgeDirection; -import universalelectricity.core.electricity.ElectricityPack; public class ItemConfigurator extends ItemEnergized { @@ -50,6 +49,13 @@ public class ItemConfigurator extends ItemEnergized PacketHandler.sendPacket(Transmission.ALL_CLIENTS, new PacketTileEntity().setParams(Object3D.get(tileEntity), tileEntity.getNetworkedData(new ArrayList()))); return true; } + else if(world.getBlockTileEntity(x, y, z) instanceof TileEntityLogisticalTransporter) + { + TileEntityLogisticalTransporter tileEntity = (TileEntityLogisticalTransporter)world.getBlockTileEntity(x, y, z); + tileEntity.isActive = !tileEntity.isActive; + PacketHandler.sendPacket(Transmission.ALL_CLIENTS, new PacketTileEntity().setParams(Object3D.get(tileEntity), tileEntity.getNetworkedData(new ArrayList()))); + return true; + } else if(world.getBlockTileEntity(x, y, z) instanceof TileEntityElectricPump) { TileEntityElectricPump tileEntity = (TileEntityElectricPump)world.getBlockTileEntity(x, y, z); diff --git a/common/mekanism/common/TileEntityLogisticalTransporter.java b/common/mekanism/common/TileEntityLogisticalTransporter.java index 66ea87a25..ad27a29b4 100644 --- a/common/mekanism/common/TileEntityLogisticalTransporter.java +++ b/common/mekanism/common/TileEntityLogisticalTransporter.java @@ -1,8 +1,186 @@ package mekanism.common; +import java.util.ArrayList; +import java.util.HashSet; + +import mekanism.api.Object3D; +import mekanism.api.TransmitterNetworkRegistry; +import mekanism.common.PacketHandler.Transmission; +import mekanism.common.network.PacketDataRequest; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraftforge.common.ForgeDirection; -public class TileEntityLogisticalTransporter extends TileEntity implements ILogisticalTransporter +import com.google.common.io.ByteArrayDataInput; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class TileEntityLogisticalTransporter extends TileEntity implements ILogisticalTransporter, ITileNetwork { + /** The inventory network currently in use by this transporter segment. */ + public InventoryNetwork inventoryNetwork; + + /** This transporter's active state. */ + public boolean isActive = false; + + @Override + public InventoryNetwork getNetwork() + { + if(inventoryNetwork == null) + { + inventoryNetwork = new InventoryNetwork(this); + } + + return inventoryNetwork; + } + + @Override + public InventoryNetwork getNetwork(boolean createIfNull) + { + if(inventoryNetwork == null && createIfNull) + { + TileEntity[] adjacentTransporters = CableUtils.getConnectedCables(this); + HashSet connectedNets = new HashSet(); + + for(TileEntity transporter : adjacentTransporters) + { + if(transporter instanceof ILogisticalTransporter && ((ILogisticalTransporter)transporter).getNetwork(false) != null) + { + connectedNets.add(((ILogisticalTransporter)transporter).getNetwork()); + } + } + if(connectedNets.size() == 0 || worldObj.isRemote) + { + inventoryNetwork = new InventoryNetwork(this); + } + else if(connectedNets.size() == 1) + { + inventoryNetwork = connectedNets.iterator().next(); + inventoryNetwork.transporters.add(this); + } + else { + inventoryNetwork = new InventoryNetwork(connectedNets); + inventoryNetwork.transporters.add(this); + } + } + + return inventoryNetwork; + } + @Override + public void fixNetwork() + { + getNetwork().fixMessedUpNetwork(this); + } + + @Override + public void invalidate() + { + if(!worldObj.isRemote) + { + getNetwork().split(this); + } + + super.invalidate(); + } + + @Override + public void setNetwork(InventoryNetwork network) + { + if(network != inventoryNetwork) + { + removeFromNetwork(); + inventoryNetwork = network; + } + } + + @Override + public void removeFromNetwork() + { + if(inventoryNetwork != null) + { + inventoryNetwork.removeTransporter(this); + } + } + + @Override + public void refreshNetwork() + { + if(!worldObj.isRemote) + { + for(ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) + { + TileEntity tileEntity = Object3D.get(this).getFromSide(side).getTileEntity(worldObj); + + if(tileEntity instanceof ILogisticalTransporter) + { + getNetwork().merge(((ILogisticalTransporter)tileEntity).getNetwork()); + } + } + + getNetwork().refresh(); + } + } + + @Override + public void onChunkUnload() + { + invalidate(); + TransmitterNetworkRegistry.getInstance().pruneEmptyNetworks(); + } + + @Override + public boolean canUpdate() + { + return true; + } + + @Override + public void validate() + { + super.validate(); + + if(worldObj.isRemote) + { + PacketHandler.sendPacket(Transmission.SERVER, new PacketDataRequest().setParams(Object3D.get(this))); + } + } + + @Override + public void handlePacketData(ByteArrayDataInput dataStream) + { + isActive = dataStream.readBoolean(); + } + + @Override + public ArrayList getNetworkedData(ArrayList data) + { + data.add(isActive); + return data; + } + + @Override + public void readFromNBT(NBTTagCompound nbtTags) + { + super.readFromNBT(nbtTags); + + isActive = nbtTags.getBoolean("isActive"); + } + + @Override + public void writeToNBT(NBTTagCompound nbtTags) + { + super.writeToNBT(nbtTags); + + nbtTags.setBoolean("isActive", isActive); + } + + @Override + @SideOnly(Side.CLIENT) + public AxisAlignedBB getRenderBoundingBox() + { + return INFINITE_EXTENT_AABB; + } } diff --git a/common/mekanism/common/TileEntityMechanicalPipe.java b/common/mekanism/common/TileEntityMechanicalPipe.java index 1b60802d5..70f8ee722 100644 --- a/common/mekanism/common/TileEntityMechanicalPipe.java +++ b/common/mekanism/common/TileEntityMechanicalPipe.java @@ -71,15 +71,17 @@ public class TileEntityMechanicalPipe extends TileEntity implements IMechanicalP { if(fluidNetwork == null && createIfNull) { - TileEntity[] adjacentCables = CableUtils.getConnectedCables(this); + TileEntity[] adjacentPipes = PipeUtils.getConnectedPipes(this); HashSet connectedNets = new HashSet(); - for(TileEntity pipe : adjacentCables) + + for(TileEntity pipe : adjacentPipes) { if(pipe instanceof IMechanicalPipe && ((IMechanicalPipe)pipe).getNetwork(false) != null) { connectedNets.add(((IMechanicalPipe)pipe).getNetwork()); } } + if(connectedNets.size() == 0 || worldObj.isRemote) { fluidNetwork = new FluidNetwork(this); diff --git a/common/mekanism/common/TileEntityPressurizedTube.java b/common/mekanism/common/TileEntityPressurizedTube.java index e298d83b4..3334dca3d 100644 --- a/common/mekanism/common/TileEntityPressurizedTube.java +++ b/common/mekanism/common/TileEntityPressurizedTube.java @@ -4,6 +4,7 @@ import java.util.HashSet; import mekanism.api.EnumGas; import mekanism.api.GasNetwork; +import mekanism.api.GasTransmission; import mekanism.api.IPressurizedTube; import mekanism.api.ITubeConnection; import mekanism.api.Object3D; @@ -35,14 +36,14 @@ public class TileEntityPressurizedTube extends TileEntity implements IPressurize { if(gasNetwork == null && createIfNull) { - TileEntity[] adjacentPipes = PipeUtils.getConnectedPipes(this); + TileEntity[] adjacentTubes = GasTransmission.getConnectedTubes(this); HashSet connectedNets = new HashSet(); - for(TileEntity cable : adjacentPipes) + for(TileEntity tube : adjacentTubes) { - if(cable instanceof IPressurizedTube && ((IPressurizedTube)cable).getNetwork(false) != null) + if(tube instanceof IPressurizedTube && ((IPressurizedTube)tube).getNetwork(false) != null) { - connectedNets.add(((IPressurizedTube)cable).getNetwork()); + connectedNets.add(((IPressurizedTube)tube).getNetwork()); } } diff --git a/resources/assets/mekanism/render/LogisticalTransporterOn.png b/resources/assets/mekanism/render/LogisticalTransporterActive.png similarity index 100% rename from resources/assets/mekanism/render/LogisticalTransporterOn.png rename to resources/assets/mekanism/render/LogisticalTransporterActive.png