diff --git a/gradle.properties b/gradle.properties index 6f17a7f56..74ce20c29 100644 --- a/gradle.properties +++ b/gradle.properties @@ -34,6 +34,7 @@ code_chicken_lib_version=1.1.3.127 code_chicken_core_version=1.0.4.35 nei_version=1.0.4.90 bc_version=6.4.6 +opencomputers_version=1.5.9.21 ######################################################### # Self Compiled APIs # diff --git a/gradle/scripts/dependencies.gradle b/gradle/scripts/dependencies.gradle index 6b49341dc..974276ad4 100644 --- a/gradle/scripts/dependencies.gradle +++ b/gradle/scripts/dependencies.gradle @@ -49,6 +49,12 @@ repositories { name = "RX14 Proxy" url = "http://mvn.rx14.co.uk/repo/" } + + maven { + name "OpenComputers Repo" + url = "http://maven.cil.li/" + } + // CurseForge DNS for TE is not available or I am just being unlucky, code part can stay since this is applicable to any other curseforge mod though // ivy { // name = "CoFHLib" @@ -85,6 +91,8 @@ dependencies { mods "com.enderio:EnderIO:${minecraft_version}-${enderio_version}:dev" mods "net.mcft.copy.betterstorage:BetterStorage:${minecraft_version}-${betterstorage_version}:deobf" mods "inventorytweaks:InventoryTweaks:${invtweaks_version}:deobf" + mods "li.cil.oc:OpenComputers:MC${minecraft_version}-${opencomputers_version}:dev" + // mods name: 'CoFHLib', version: "[${minecraft_version}]${cofhlib_version}-dev", ext: 'jar' // mods name: 'CoFHCore', version: "[${minecraft_version}]${cofhcore_version}-dev", ext: 'jar' // mods name: 'ThermalExpansion', version: "[${minecraft_version}]${texpansion_version}-dev", ext: 'jar' @@ -97,6 +105,7 @@ dependencies { compile "com.mod-buildcraft:buildcraft:${bc_version}:dev" // provided APIs + compile "li.cil.oc:OpenComputers:MC${minecraft_version}-${opencomputers_version}:api" compile "net.industrial-craft:industrialcraft-2:${ic2_version}-experimental:api" compile "net.mcft.copy.betterstorage:BetterStorage:${minecraft_version}-${betterstorage_version}:api" diff --git a/gradle/scripts/optional.gradle b/gradle/scripts/optional.gradle index 452232289..ce1029ba6 100644 --- a/gradle/scripts/optional.gradle +++ b/gradle/scripts/optional.gradle @@ -103,4 +103,14 @@ task installBetterStorage(type: Copy, dependsOn: "deinstallBetterStorage") { task deinstallBetterStorage(type: Delete) { delete fileTree(dir: minecraft.runDir + "/mods", include: "*BetterStorage*.jar") -} \ No newline at end of file +} + +task installOpenComputers(type: Copy, dependsOn: "deinstallOpenComputers") { + from { configurations.mods } + include "**/*OpenComputer*dev*.jar" + into file(minecraft.runDir + "/mods") +} + +task deinstallOpenComputers(type: Delete) { + delete fileTree(dir: minecraft.runDir + "/mods", include: "*OpenComputers*.jar") +} diff --git a/src/api/java/appeng/api/definitions/IParts.java b/src/api/java/appeng/api/definitions/IParts.java index f79cf3e09..220d83ca0 100644 --- a/src/api/java/appeng/api/definitions/IParts.java +++ b/src/api/java/appeng/api/definitions/IParts.java @@ -82,6 +82,8 @@ public interface IParts IItemDefinition p2PTunnelLight(); + IItemDefinition p2PTunnelOpenComputers(); + IItemDefinition cableAnchor(); IItemDefinition monitor(); diff --git a/src/main/java/appeng/core/Registration.java b/src/main/java/appeng/core/Registration.java index 4e5b58c5b..fb0db8df4 100644 --- a/src/main/java/appeng/core/Registration.java +++ b/src/main/java/appeng/core/Registration.java @@ -539,6 +539,11 @@ public final class Registration partHelper.registerNewLayer( "appeng.parts.layers.LayerIEnergyHandler", "cofh.api.energy.IEnergyReceiver" ); } + if ( AppEng.instance.isIntegrationEnabled( IntegrationType.OpenComputers ) ) + { + partHelper.registerNewLayer( "appeng.parts.layers.LayerSidedEnvironment", "li.cil.oc.api.network.SidedEnvironment" ); + } + FMLCommonHandler.instance().bus().register( TickHandler.INSTANCE ); MinecraftForge.EVENT_BUS.register( TickHandler.INSTANCE ); diff --git a/src/main/java/appeng/core/api/definitions/ApiParts.java b/src/main/java/appeng/core/api/definitions/ApiParts.java index 3539ac954..0bcf61756 100644 --- a/src/main/java/appeng/core/api/definitions/ApiParts.java +++ b/src/main/java/appeng/core/api/definitions/ApiParts.java @@ -59,6 +59,7 @@ public final class ApiParts implements IParts private final IItemDefinition p2PTunnelEU; private final IItemDefinition p2PTunnelRF; private final IItemDefinition p2PTunnelLight; + private final IItemDefinition p2PTunnelOpenComputers; private final IItemDefinition cableAnchor; private final IItemDefinition monitor; private final IItemDefinition semiDarkMonitor; @@ -100,6 +101,7 @@ public final class ApiParts implements IParts this.p2PTunnelEU = new DamagedItemDefinition( itemMultiPart.createPart( PartType.P2PTunnelEU ) ); this.p2PTunnelRF = new DamagedItemDefinition( itemMultiPart.createPart( PartType.P2PTunnelRF ) ); this.p2PTunnelLight = new DamagedItemDefinition( itemMultiPart.createPart( PartType.P2PTunnelLight ) ); + this.p2PTunnelOpenComputers = new DamagedItemDefinition( itemMultiPart.createPart( PartType.P2PTunnelOpenComputers ) ); this.cableAnchor = new DamagedItemDefinition( itemMultiPart.createPart( PartType.CableAnchor ) ); this.monitor = new DamagedItemDefinition( itemMultiPart.createPart( PartType.Monitor ) ); this.semiDarkMonitor = new DamagedItemDefinition( itemMultiPart.createPart( PartType.SemiDarkMonitor ) ); @@ -266,6 +268,12 @@ public final class ApiParts implements IParts return this.p2PTunnelLight; } + @Override + public IItemDefinition p2PTunnelOpenComputers() + { + return this.p2PTunnelOpenComputers; + } + @Override public IItemDefinition cableAnchor() { diff --git a/src/main/java/appeng/core/features/AEFeature.java b/src/main/java/appeng/core/features/AEFeature.java index 8a75e99fd..cebe6e135 100644 --- a/src/main/java/appeng/core/features/AEFeature.java +++ b/src/main/java/appeng/core/features/AEFeature.java @@ -57,7 +57,7 @@ public enum AEFeature DenseEnergyCells( "HigherCapacity" ), DenseCables( "HigherCapacity" ), - P2PTunnelRF( "P2PTunnels" ), P2PTunnelME( "P2PTunnels" ), P2PTunnelItems( "P2PTunnels" ), P2PTunnelRedstone( "P2PTunnels" ), P2PTunnelEU( "P2PTunnels" ), P2PTunnelLiquids( "P2PTunnels" ), P2PTunnelLight( "P2PTunnels" ), + P2PTunnelRF( "P2PTunnels" ), P2PTunnelME( "P2PTunnels" ), P2PTunnelItems( "P2PTunnels" ), P2PTunnelRedstone( "P2PTunnels" ), P2PTunnelEU( "P2PTunnels" ), P2PTunnelLiquids( "P2PTunnels" ), P2PTunnelLight( "P2PTunnels" ), P2PTunnelOpenComputers( "P2PTunnels" ), MassCannonBlockDamage( "BlockFeatures" ), TinyTNTBlockDamage( "BlockFeatures" ), Facades( "Facades" ), diff --git a/src/main/java/appeng/core/localization/GuiText.java b/src/main/java/appeng/core/localization/GuiText.java index c1851067c..c8884e4fe 100644 --- a/src/main/java/appeng/core/localization/GuiText.java +++ b/src/main/java/appeng/core/localization/GuiText.java @@ -44,7 +44,8 @@ public enum GuiText CraftingTerminal, FormationPlane, Inscriber, QuartzCuttingKnife, - METunnel, ItemTunnel, RedstoneTunnel, EUTunnel, FluidTunnel, + // tunnel names + METunnel, ItemTunnel, RedstoneTunnel, EUTunnel, FluidTunnel, OCTunnel, LightTunnel, RFTunnel, StoredSize, CopyMode, CopyModeDesc, PatternTerminal, CraftingPattern, @@ -56,7 +57,7 @@ public enum GuiText inWorldPurificationFluix, inWorldSingularity, ChargedQuartz, OfSecondOutput, - NoSecondOutput, RFTunnel, Stores, Next, SelectAmount, Lumen, Empty, + NoSecondOutput, Stores, Next, SelectAmount, Lumen, Empty, ConfirmCrafting, Stored, Crafting, Scheduled, CraftingStatus, Cancel, @@ -64,7 +65,7 @@ public enum GuiText CraftingCPU, Automatic, CoProcessors, Simulation, Missing, - InterfaceTerminal, NoCraftingCPUs, LightTunnel, Clean, InvalidPattern, + InterfaceTerminal, NoCraftingCPUs, Clean, InvalidPattern, InterfaceTerminalHint, Range, TransparentFacades, TransparentFacadesHint, diff --git a/src/main/java/appeng/core/settings/TickRates.java b/src/main/java/appeng/core/settings/TickRates.java index ac2ac7d0c..3bb3a9e5a 100644 --- a/src/main/java/appeng/core/settings/TickRates.java +++ b/src/main/java/appeng/core/settings/TickRates.java @@ -45,7 +45,9 @@ public enum TickRates ItemTunnel( 5, 60 ), - LightTunnel( 5, 120 ); + LightTunnel( 5, 120 ), + + OpenComputersTunnel( 1, 5 ); public int min; public int max; diff --git a/src/main/java/appeng/integration/IntegrationType.java b/src/main/java/appeng/integration/IntegrationType.java index 5a81d8596..7651f6ee5 100644 --- a/src/main/java/appeng/integration/IntegrationType.java +++ b/src/main/java/appeng/integration/IntegrationType.java @@ -57,7 +57,9 @@ public enum IntegrationType ImmibisMicroblocks( IntegrationSide.BOTH, "ImmibisMicroblocks", "ImmibisMicroblocks" ), - BetterStorage( IntegrationSide.BOTH, "BetterStorage", "betterstorage" ); + BetterStorage( IntegrationSide.BOTH, "BetterStorage", "betterstorage" ), + + OpenComputers( IntegrationSide.BOTH, "OpenComputers", "OpenComputers" ); public final IntegrationSide side; public final String dspName; diff --git a/src/main/java/appeng/integration/modules/OpenComputers.java b/src/main/java/appeng/integration/modules/OpenComputers.java new file mode 100644 index 000000000..607dd874d --- /dev/null +++ b/src/main/java/appeng/integration/modules/OpenComputers.java @@ -0,0 +1,61 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Applied Energistics 2. If not, see . + */ + +package appeng.integration.modules; + +import li.cil.oc.api.Items; + +import appeng.api.AEApi; +import appeng.api.config.TunnelType; +import appeng.api.features.IP2PTunnelRegistry; +import appeng.integration.BaseModule; + +public class OpenComputers extends BaseModule +{ + public static OpenComputers instance; + + public OpenComputers() + { + this.testClassExistence( li.cil.oc.api.Items.class ); + this.testClassExistence( li.cil.oc.api.Network.class ); + this.testClassExistence( li.cil.oc.api.network.Environment.class ); + this.testClassExistence( li.cil.oc.api.network.SidedEnvironment.class ); + this.testClassExistence( li.cil.oc.api.network.Node.class ); + this.testClassExistence( li.cil.oc.api.network.Message.class ); + } + + @Override + public void init() + { + } + + @Override + public void postInit() + { + final IP2PTunnelRegistry registry = AEApi.instance().registries().p2pTunnel(); + + registry.addNewAttunement( Items.get( "cable" ).createItemStack( 1 ), TunnelType.COMPUTER_MESSAGE ); + registry.addNewAttunement( Items.get( "adapter" ).createItemStack( 1 ), TunnelType.COMPUTER_MESSAGE ); + registry.addNewAttunement( Items.get( "switch" ).createItemStack( 1 ), TunnelType.COMPUTER_MESSAGE ); + registry.addNewAttunement( Items.get( "accessPoint" ).createItemStack( 1 ), TunnelType.COMPUTER_MESSAGE ); + registry.addNewAttunement( Items.get( "lanCard" ).createItemStack( 1 ), TunnelType.COMPUTER_MESSAGE ); + registry.addNewAttunement( Items.get( "linkedCard" ).createItemStack( 1 ), TunnelType.COMPUTER_MESSAGE ); + registry.addNewAttunement( Items.get( "wlanCard" ).createItemStack( 1 ), TunnelType.COMPUTER_MESSAGE ); + registry.addNewAttunement( Items.get( "analyzer" ).createItemStack( 1 ), TunnelType.COMPUTER_MESSAGE ); + } +} diff --git a/src/main/java/appeng/items/parts/PartType.java b/src/main/java/appeng/items/parts/PartType.java index cc1774a03..2aed2ef2a 100644 --- a/src/main/java/appeng/items/parts/PartType.java +++ b/src/main/java/appeng/items/parts/PartType.java @@ -47,6 +47,7 @@ import appeng.parts.p2p.PartP2PIC2Power; import appeng.parts.p2p.PartP2PItems; import appeng.parts.p2p.PartP2PLight; import appeng.parts.p2p.PartP2PLiquids; +import appeng.parts.p2p.PartP2POpenComputers; import appeng.parts.p2p.PartP2PRFPower; import appeng.parts.p2p.PartP2PRedstone; import appeng.parts.p2p.PartP2PTunnelME; @@ -153,6 +154,8 @@ public enum PartType P2PTunnelLight( 467, EnumSet.of( AEFeature.P2PTunnel, AEFeature.P2PTunnelLight ), EnumSet.noneOf( IntegrationType.class ), PartP2PLight.class, GuiText.LightTunnel ), + P2PTunnelOpenComputers(468, EnumSet.of( AEFeature.P2PTunnel, AEFeature.P2PTunnelOpenComputers ), EnumSet.of( IntegrationType.OpenComputers ), PartP2POpenComputers.class, GuiText.OCTunnel ), + InterfaceTerminal( 480, EnumSet.of( AEFeature.InterfaceTerminal ), EnumSet.noneOf( IntegrationType.class ), PartInterfaceTerminal.class ); public final int baseDamage; diff --git a/src/main/java/appeng/parts/layers/LayerSidedEnvironment.java b/src/main/java/appeng/parts/layers/LayerSidedEnvironment.java new file mode 100644 index 000000000..a6e279eb3 --- /dev/null +++ b/src/main/java/appeng/parts/layers/LayerSidedEnvironment.java @@ -0,0 +1,64 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Applied Energistics 2. If not, see . + */ + +package appeng.parts.layers; + +import javax.annotation.Nullable; + +import net.minecraftforge.common.util.ForgeDirection; + +import cpw.mods.fml.common.event.FMLInitializationEvent; + +import li.cil.oc.api.network.Node; +import li.cil.oc.api.network.SidedEnvironment; + +import appeng.api.parts.IPart; +import appeng.api.parts.LayerBase; +import appeng.core.Registration; +import appeng.helpers.Reflected; + + +/** + * Reflected in {@link Registration#initialize(FMLInitializationEvent)} + */ +@Reflected +public class LayerSidedEnvironment extends LayerBase implements SidedEnvironment +{ + @Nullable + @Override + public Node sidedNode(ForgeDirection side) + { + final IPart part = this.getPart( side ); + if ( part instanceof SidedEnvironment ) + { + return ( (SidedEnvironment) part ).sidedNode( side ); + } + return null; + } + + @Override + public boolean canConnect(ForgeDirection side) + { + final IPart part = this.getPart( side ); + if ( part instanceof SidedEnvironment ) + { + return ( (SidedEnvironment) part ).canConnect( side ); + } + return false; + } +} diff --git a/src/main/java/appeng/parts/p2p/PartP2POpenComputers.java b/src/main/java/appeng/parts/p2p/PartP2POpenComputers.java new file mode 100644 index 000000000..7786b733c --- /dev/null +++ b/src/main/java/appeng/parts/p2p/PartP2POpenComputers.java @@ -0,0 +1,250 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Applied Energistics 2. If not, see . + */ + +package appeng.parts.p2p; + + +import java.util.concurrent.Callable; + +import javax.annotation.Nullable; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.IIcon; +import net.minecraftforge.common.util.ForgeDirection; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +import li.cil.oc.api.API; +import li.cil.oc.api.Items; +import li.cil.oc.api.Network; +import li.cil.oc.api.network.Environment; +import li.cil.oc.api.network.Message; +import li.cil.oc.api.network.Node; +import li.cil.oc.api.network.SidedEnvironment; +import li.cil.oc.api.network.Visibility; + +import appeng.api.networking.IGridNode; +import appeng.api.networking.ticking.IGridTickable; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.networking.ticking.TickingRequest; +import appeng.core.AELog; +import appeng.core.AppEng; +import appeng.core.settings.TickRates; +import appeng.hooks.TickHandler; +import appeng.integration.IntegrationType; +import appeng.me.GridAccessException; +import appeng.transformer.annotations.Integration.Interface; +import appeng.transformer.annotations.Integration.InterfaceList; + + +@InterfaceList(value = { @Interface(iface = "li.cil.oc.api.network.Environment", iname = "OpenComputers"), @Interface(iface = "li.cil.oc.api.network.SidedEnvironment", iname = "OpenComputers") }) +public final class PartP2POpenComputers extends PartP2PTunnel implements IGridTickable, Environment, SidedEnvironment +{ + @Nullable + private final Node node; + + private final Callable updateCallback; + + public PartP2POpenComputers(ItemStack is) + { + super( is ); + + if ( !AppEng.instance.isIntegrationEnabled( IntegrationType.OpenComputers ) ) + { + throw new RuntimeException( "OpenComputers is not installed!" ); + } + + // Avoid NPE when called in pre-init phase (part population). + if ( API.network != null ) + { + this.node = Network.newNode( this, Visibility.None ).create(); + } + else + { + this.node = null; // to satisfy final + } + + this.updateCallback = new UpdateCallback(); + } + + @Override + @SideOnly(Side.CLIENT) + public IIcon getTypeTexture() + { + return Items.get( "adapter" ).block().getBlockTextureFromSide( 2 ); + } + + @Override + public void removeFromWorld() + { + super.removeFromWorld(); + if ( this.node != null) + { + this.node.remove(); + } + } + + @Override + public void onTunnelNetworkChange() + { + super.onTunnelNetworkChange(); + try + { + this.proxy.getTick().wakeDevice( this.proxy.getNode() ); + } + catch( GridAccessException e ) + { + // ignore + } + } + + @Override + public void readFromNBT(NBTTagCompound data) + { + super.readFromNBT( data ); + if ( this.node != null) + { + this.node.load( data ); + } + } + + @Override + public void writeToNBT(NBTTagCompound data) + { + super.writeToNBT( data ); + if ( this.node != null) + { + this.node.save( data ); + } + } + + @Override + public TickingRequest getTickingRequest( IGridNode node ) + { + return new TickingRequest( TickRates.OpenComputersTunnel.min, TickRates.OpenComputersTunnel.max, true, false ); + } + + @Override + public TickRateModulation tickingRequest( IGridNode node, int ticksSinceLastCall ) + { + try + { + if( !this.proxy.getPath().isNetworkBooting() ) + { + if ( this.node() != null ) // Client side doesn't have nodes. + { + TickHandler.INSTANCE.addCallable( this.tile.getWorldObj(), this.updateCallback ); + } + + return TickRateModulation.SLEEP; + } + } + catch( GridAccessException e ) + { + // ignore + } + + return TickRateModulation.IDLE; + } + + private void updateConnections() + { + if ( this.proxy.isPowered() && this.proxy.isActive() ) + { + // Make sure we're connected to existing OC nodes in the world. + Network.joinOrCreateNetwork( this.getTile() ); + + if ( this.output ) + { + if ( this.getInput() != null && this.node != null ) + { + Network.joinOrCreateNetwork( this.getInput().getTile() ); + this.node.connect( this.getInput().node() ); + } + } + else + { + try + { + for ( PartP2POpenComputers output : this.getOutputs() ) + { + if ( this.node != null ) + { + Network.joinOrCreateNetwork( output.getTile() ); + this.node.connect( output.node() ); + } + } + } + catch ( GridAccessException e ) + { + AELog.error( e ); + } + } + } + else if ( this.node != null ) + { + this.node.remove(); + } + } + + @Nullable + @Override + public Node node() + { + return this.node; + } + + @Override + public void onConnect(Node node) { + } + + @Override + public void onDisconnect(Node node) { + } + + @Override + public void onMessage(Message message) { + } + + @Nullable + @Override + public Node sidedNode(ForgeDirection side) + { + return side == this.side ? this.node : null; + } + + @Override + public boolean canConnect(ForgeDirection side) + { + return side == this.side; + } + + private final class UpdateCallback implements Callable + { + @Nullable + @Override + public Void call() throws Exception + { + PartP2POpenComputers.this.updateConnections(); + + return null; + } + } +} diff --git a/src/main/java/appeng/parts/p2p/PartP2PTunnel.java b/src/main/java/appeng/parts/p2p/PartP2PTunnel.java index 1ec2f77fe..a95ef994e 100644 --- a/src/main/java/appeng/parts/p2p/PartP2PTunnel.java +++ b/src/main/java/appeng/parts/p2p/PartP2PTunnel.java @@ -336,6 +336,13 @@ public abstract class PartP2PTunnel extends PartBasicSt } break; + case COMPUTER_MESSAGE: + for( ItemStack stack : parts.p2PTunnelOpenComputers().maybeStack( 1 ).asSet() ) + { + newType = stack; + } + break; + default: break; } diff --git a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang index 17d7e3bd0..e3e6f7fc1 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang @@ -91,6 +91,7 @@ gui.appliedenergistics2.RedstoneTunnel=Redstone gui.appliedenergistics2.EUTunnel=EU gui.appliedenergistics2.RFTunnel=RF gui.appliedenergistics2.LightTunnel=Light +gui.appliedenergistics2.OCTunnel=OpenComputers gui.appliedenergistics2.security.extract.name=Withdraw gui.appliedenergistics2.security.inject.name=Deposit