diff --git a/build.gradle b/build.gradle index b0fd1db5f..baf5de133 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,6 @@ repositories { apply from: 'gradle/scripts/dependencies.gradle' apply from: 'gradle/scripts/artifacts.gradle' -apply from: 'gradle/scripts/integration.gradle' apply from: 'gradle/scripts/optional.gradle' sourceCompatibility = JavaVersion.VERSION_1_8 diff --git a/gradle/scripts/integration.gradle b/gradle/scripts/integration.gradle deleted file mode 100644 index c05b128e1..000000000 --- a/gradle/scripts/integration.gradle +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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 . - */ - -// Should be provided by ForgeGradle, some idea user should confirm it. -apply plugin: 'idea' - -idea { - module { - inheritOutputDirs = true - - // excludes integration due to not being available upon port - excludeDirs += file('src/main/java/appeng/parts/layers/') - } -} \ No newline at end of file diff --git a/src/api/java/appeng/api/definitions/IParts.java b/src/api/java/appeng/api/definitions/IParts.java index 7044bff18..ce1880cda 100644 --- a/src/api/java/appeng/api/definitions/IParts.java +++ b/src/api/java/appeng/api/definitions/IParts.java @@ -78,7 +78,7 @@ public interface IParts IItemDefinition p2PTunnelLiquids(); - // IItemDefinition p2PTunnelEU(); + IItemDefinition p2PTunnelEU(); // IItemDefinition p2PTunnelRF(); diff --git a/src/main/java/appeng/core/Registration.java b/src/main/java/appeng/core/Registration.java index ecf2ba547..abff12002 100644 --- a/src/main/java/appeng/core/Registration.java +++ b/src/main/java/appeng/core/Registration.java @@ -63,6 +63,8 @@ import appeng.core.localization.GuiText; import appeng.core.localization.PlayerMessages; import appeng.core.stats.PlayerStatsRegistration; import appeng.hooks.TickHandler; +import appeng.integration.IntegrationRegistry; +import appeng.integration.IntegrationType; import appeng.items.materials.ItemMaterial; import appeng.items.parts.ItemFacade; import appeng.loot.ChestLoot; @@ -246,13 +248,11 @@ public final class Registration final Runnable recipeLoader = new RecipeLoader( recipeDirectory, customRecipeConfig, this.recipeHandler ); recipeLoader.run(); - // TODO readd layers - - // if( IntegrationRegistry.INSTANCE.isEnabled( IntegrationType.IC2 ) ) - // { - // partHelper.registerNewLayer( "appeng.parts.layers.LayerIEnergySink", "ic2.api.energy.tile.IEnergySink" ); - // partHelper.registerNewLayer( "appeng.parts.layers.LayerIEnergySource", "ic2.api.energy.tile.IEnergySource" ); - // } + if( IntegrationRegistry.INSTANCE.isEnabled( IntegrationType.IC2 ) ) + { + partHelper.registerNewLayer( "appeng.parts.layers.LayerIEnergySink", "ic2.api.energy.tile.IEnergySink" ); + partHelper.registerNewLayer( "appeng.parts.layers.LayerIEnergySource", "ic2.api.energy.tile.IEnergySource" ); + } // // if( IntegrationRegistry.INSTANCE.isEnabled( IntegrationType.RF ) ) // { diff --git a/src/main/java/appeng/core/api/ApiPart.java b/src/main/java/appeng/core/api/ApiPart.java index ea3144c63..771e5eb1f 100644 --- a/src/main/java/appeng/core/api/ApiPart.java +++ b/src/main/java/appeng/core/api/ApiPart.java @@ -28,7 +28,10 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import com.google.common.base.Joiner; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableList; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; @@ -64,9 +67,16 @@ import appeng.tile.networking.TileCableBus; public class ApiPart implements IPartHelper { - private final Map> tileImplementations = new HashMap<>(); - private final Map, String> interfaces2Layer = new HashMap, String>(); - private final Map roots = new HashMap(); + private final LoadingCache> cache = CacheBuilder.newBuilder().build( new CacheLoader>() + { + @Override + public Class load( CacheKey key ) throws Exception + { + return generateCombinedClass( key ); + } + } ); + + private final Map, String> interfaces2Layer = new HashMap<>(); private final List desc = new LinkedList(); public void initFMPSupport() @@ -80,64 +90,79 @@ public class ApiPart implements IPartHelper } } + /** + * Conceptually this method will build a new class hierarchy that is rooted at the given base class, and includes a chain of all registered layers. + *

+ * To accomplish this, it takes the first registered layer, replaces it's inheritance from LayerBase with an inheritance from the given baseClass, + * and uses the resulting class as the parent class for the next registered layer, for which it repeats this process. This process is then repeated + * until a class hierarchy of all layers is formed. While janking out the inheritance from LayerBase, it'll make also sure that calls to that + * classes method will instead be forwarded to the superclass that was inserted as part of the described process. + *

+ * Example: If layers A and B are registered, and TileCableBus is passed in as the baseClass, a synthetic class A_B_TileCableBus should be returned, + * which has A_B_TileCableBus -extends-> B_TileCableBus -extends-> TileCableBus as it's class hierarchy, where A_B_TileCableBus has been generated + * from A, and B_TileCableBus has been generated from B. + */ public Class getCombinedInstance( final Class baseClass ) { - String base = baseClass.getName(); - if( this.desc.isEmpty() ) { + // No layers registered... return baseClass; } - final String description = base + ':' + Joiner.on( ";" ).skipNulls().join( this.desc.iterator() ); - - if( this.tileImplementations.get( description ) != null ) - { - return this.tileImplementations.get( description ); - } - - String f = base;// TileCableBus.class.getName(); - String Addendum = baseClass.getSimpleName(); - Class myClass = baseClass; - - String path = f; - - for( final String name : this.desc ) - { - try - { - final String newPath = path + ';' + name; - myClass = this.getClassByDesc( baseClass.getSimpleName(), newPath, f, this.interfaces2Layer.get( Class.forName( name ) ) ); - path = newPath; - } - catch( final Throwable t ) - { - AELog.warn( "Error loading " + name ); - AELog.debug( t ); - } - f = myClass.getName(); - } - - this.tileImplementations.put( description, myClass ); - - return myClass; + return cache.getUnchecked( new CacheKey( baseClass, this.desc ) ); } - private Class getClassByDesc( final String addendum, final String fullPath, final String root, final String next ) + private Class generateCombinedClass( CacheKey cacheKey ) { - if( this.roots.get( fullPath ) != null ) + final Class parentClass; + + // Get the list of interfaces that still need to be implemented beyond the current one + List remainingInterfaces = cacheKey.getInterfaces().subList( 1, cacheKey.getInterfaces().size() ); + + // We are not at the root of the class hierarchy yet + if( !remainingInterfaces.isEmpty() ) { - return this.roots.get( fullPath ); + CacheKey parentKey = new CacheKey( cacheKey.getBaseClass(), remainingInterfaces ); + parentClass = cache.getUnchecked( parentKey ); + } + else + { + parentClass = cacheKey.getBaseClass(); } + // Which interface should be implemented in this layer? + String interfaceName = cacheKey.getInterfaces().get( 0 ); + + try + { + // This is the particular interface that this layer was registered for. Loading the class may fail if i.e. an API is broken or not present + // and in this case, the layer will be skipped! + Class interfaceClass = Class.forName( interfaceName ); + String layerImpl = this.interfaces2Layer.get( interfaceClass ); + + return this.getClassByDesc( parentClass, layerImpl ); + } + catch( final Throwable t ) + { + AELog.warn( "Error loading " + interfaceName ); + AELog.debug( t ); + return parentClass; + } + + } + + @SuppressWarnings( "unchecked" ) + private Class getClassByDesc( Class baseClass, final String next ) + { final ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_MAXS ); final ClassNode n = this.getReader( next ); final String originalName = n.name; try { - n.name = n.name + '_' + addendum; - n.superName = Class.forName( root ).getName().replace( ".", "/" ); + n.name = n.name + '_' + baseClass.getSimpleName(); + n.superName = baseClass.getName().replace( '.', '/' ); } catch( final Throwable t ) { @@ -167,14 +192,13 @@ public class ApiPart implements IPartHelper try { final Object fish = clazz.newInstance(); - final Class rootC = Class.forName( root ); boolean hasError = false; - if( !rootC.isInstance( fish ) ) + if( !baseClass.isInstance( fish ) ) { hasError = true; - AELog.error( "Error, Expected layer to implement " + root + " did not." ); + AELog.error( "Error, Expected layer to implement " + baseClass + " did not." ); } if( fish instanceof LayerBase ) @@ -183,19 +207,16 @@ public class ApiPart implements IPartHelper AELog.error( "Error, Expected layer to NOT implement LayerBase but it DID." ); } - if( !fullPath.contains( ".fmp." ) ) + if( !( fish instanceof TileCableBus ) ) { - if( !( fish instanceof TileCableBus ) ) - { - hasError = true; - AELog.error( "Error, Expected layer to implement TileCableBus did not." ); - } + hasError = true; + AELog.error( "Error, Expected layer to implement TileCableBus did not." ); + } - if( !( fish instanceof TileEntity ) ) - { - hasError = true; - AELog.error( "Error, Expected layer to implement TileEntity did not." ); - } + if( !( fish instanceof TileEntity ) ) + { + hasError = true; + AELog.error( "Error, Expected layer to implement TileEntity did not." ); } if( !hasError ) @@ -209,7 +230,6 @@ public class ApiPart implements IPartHelper AELog.debug( t ); } - this.roots.put( fullPath, clazz ); return clazz; } @@ -260,10 +280,19 @@ public class ApiPart implements IPartHelper defineClassMethod.setAccessible( true ); try { - final Object[] argsA = { name, name, b }; + final Object[] argsA = { + name, + name, + b + }; b = (byte[]) runTransformersMethod.invoke( loader, argsA ); - final Object[] args = { name, b, 0, b.length }; + final Object[] args = { + name, + b, + 0, + b.length + }; clazz = (Class) defineClassMethod.invoke( loader, args ); } finally @@ -319,7 +348,7 @@ public class ApiPart implements IPartHelper private static class DefaultPackageClassNameRemapper extends Remapper { - private final HashMap inputOutput = new HashMap(); + private final HashMap inputOutput = new HashMap<>(); @Override public String map( final String typeName ) @@ -332,4 +361,53 @@ public class ApiPart implements IPartHelper return o; } } + + + private static class CacheKey + { + private final Class baseClass; + + private final List interfaces; + + private CacheKey( Class baseClass, List interfaces ) + { + this.baseClass = baseClass; + this.interfaces = ImmutableList.copyOf( interfaces ); + } + + private Class getBaseClass() + { + return baseClass; + } + + private List getInterfaces() + { + return interfaces; + } + + @Override + public boolean equals( Object o ) + { + if( this == o ) + { + return true; + } + if( o == null || getClass() != o.getClass() ) + { + return false; + } + + CacheKey cacheKey = (CacheKey) o; + + return baseClass.equals( cacheKey.baseClass ) && interfaces.equals( cacheKey.interfaces ); + } + + @Override + public int hashCode() + { + int result = baseClass.hashCode(); + result = 31 * result + interfaces.hashCode(); + return result; + } + } } diff --git a/src/main/java/appeng/core/api/definitions/ApiParts.java b/src/main/java/appeng/core/api/definitions/ApiParts.java index 48a3b40cd..8739ba64d 100644 --- a/src/main/java/appeng/core/api/definitions/ApiParts.java +++ b/src/main/java/appeng/core/api/definitions/ApiParts.java @@ -62,7 +62,7 @@ public final class ApiParts implements IParts private final IItemDefinition p2PTunnelRedstone; private final IItemDefinition p2PTunnelItems; private final IItemDefinition p2PTunnelLiquids; - // private final IItemDefinition p2PTunnelEU; + private final IItemDefinition p2PTunnelEU; // private final IItemDefinition p2PTunnelRF; private final IItemDefinition p2PTunnelLight; // private final IItemDefinition p2PTunnelOpenComputers; @@ -113,7 +113,7 @@ public final class ApiParts implements IParts this.p2PTunnelRedstone = new DamagedItemDefinition( "part.tunnel.redstone", itemPart.createPart( PartType.P2PTunnelRedstone ) ); this.p2PTunnelItems = new DamagedItemDefinition( "part.tunnel.item", itemPart.createPart( PartType.P2PTunnelItems ) ); this.p2PTunnelLiquids = new DamagedItemDefinition( "part.tunnel.fluid", itemPart.createPart( PartType.P2PTunnelLiquids ) ); - // this.p2PTunnelEU = new DamagedItemDefinition( itemMultiPart.createPart( PartType.P2PTunnelEU ) ); + this.p2PTunnelEU = new DamagedItemDefinition( "part.tunnel.eu", itemPart.createPart( PartType.P2PTunnelEU ) ); // this.p2PTunnelRF = new DamagedItemDefinition( itemMultiPart.createPart( PartType.P2PTunnelRF ) ); this.p2PTunnelLight = new DamagedItemDefinition( "part.tunnel.light", itemPart.createPart( PartType.P2PTunnelLight ) ); // this.p2PTunnelOpenComputers = new DamagedItemDefinition( itemMultiPart.createPart( @@ -286,13 +286,13 @@ public final class ApiParts implements IParts return this.p2PTunnelLiquids; } - /* - * @Override - * public IItemDefinition p2PTunnelEU() - * { - * return this.p2PTunnelEU; - * } - * @Override + @Override + public IItemDefinition p2PTunnelEU() + { + return this.p2PTunnelEU; + } + + /* @Override * public IItemDefinition p2PTunnelRF() * { * return this.p2PTunnelRF; diff --git a/src/main/java/appeng/items/parts/ItemPart.java b/src/main/java/appeng/items/parts/ItemPart.java index 3cd13ea3b..3e76baa5d 100644 --- a/src/main/java/appeng/items/parts/ItemPart.java +++ b/src/main/java/appeng/items/parts/ItemPart.java @@ -28,7 +28,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; - import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -49,13 +48,9 @@ import appeng.api.implementations.items.IItemGroup; import appeng.api.parts.IPart; import appeng.api.parts.IPartItem; import appeng.api.util.AEColor; -import appeng.core.AEConfig; -import appeng.core.features.AEFeature; import appeng.core.features.ActivityState; import appeng.core.features.ItemStackSrc; import appeng.core.localization.GuiText; -import appeng.integration.IntegrationRegistry; -import appeng.integration.IntegrationType; import appeng.items.AEBaseItem; @@ -110,16 +105,7 @@ public final class ItemPart extends AEBaseItem implements IPartItem, IItemGroup } } - boolean enabled = true; - for( final AEFeature f : mat.getFeature() ) - { - enabled = enabled && AEConfig.instance.isFeatureEnabled( f ); - } - - for( final IntegrationType integrationType : mat.getIntegrations() ) - { - enabled &= IntegrationRegistry.INSTANCE.isEnabled( integrationType ); - } + boolean enabled = mat.isEnabled(); final int partDamage = mat.getBaseDamage() + varID; final ActivityState state = ActivityState.from( enabled ); diff --git a/src/main/java/appeng/items/parts/PartType.java b/src/main/java/appeng/items/parts/PartType.java index fc641fcb0..8e7689169 100644 --- a/src/main/java/appeng/items/parts/PartType.java +++ b/src/main/java/appeng/items/parts/PartType.java @@ -37,9 +37,11 @@ import net.minecraftforge.fml.relauncher.SideOnly; import appeng.api.parts.IPart; import appeng.api.util.AEColor; +import appeng.core.AEConfig; import appeng.core.AppEng; import appeng.core.features.AEFeature; import appeng.core.localization.GuiText; +import appeng.integration.IntegrationRegistry; import appeng.integration.IntegrationType; import appeng.parts.automation.PartAnnihilationPlane; import appeng.parts.automation.PartExportBus; @@ -57,6 +59,7 @@ import appeng.parts.networking.PartCableGlass; import appeng.parts.networking.PartCableSmart; import appeng.parts.networking.PartDenseCable; import appeng.parts.networking.PartQuartzFiber; +import appeng.parts.p2p.PartP2PIC2Power; import appeng.parts.p2p.PartP2PItems; import appeng.parts.p2p.PartP2PLight; import appeng.parts.p2p.PartP2PLiquids; @@ -222,8 +225,15 @@ public enum PartType } }, - // P2PTunnelEU( 465, EnumSet.of( AEFeature.P2PTunnel, AEFeature.P2PTunnelEU ), EnumSet.of( IntegrationType.IC2 ), - // PartP2PIC2Power.class, GuiText.EUTunnel ), + P2PTunnelEU( 465, "p2p_tunnel_ic2", EnumSet.of( AEFeature.P2PTunnel, AEFeature.P2PTunnelEU ), EnumSet.of( IntegrationType.IC2 ), + PartP2PIC2Power.class, GuiText.EUTunnel ) + { + @Override + String getUnlocalizedName() + { + return "P2PTunnel"; + } + }, // P2PTunnelRF( 466, EnumSet.of( AEFeature.P2PTunnel, AEFeature.P2PTunnelRF ), EnumSet.of( IntegrationType.RF ), // PartP2PRFPower.class, GuiText.RFTunnel ), @@ -249,6 +259,7 @@ public enum PartType @SideOnly( Side.CLIENT ) private List itemModels; private final Set models; + private final boolean enabled; private Constructor constructor; PartType( final int baseMetaValue, final String itemModel, final Set features, final Set integrations, final Class c ) @@ -263,16 +274,31 @@ public enum PartType this.integrations = Collections.unmodifiableSet( integrations ); this.myPart = c; this.extraName = en; - if ( Platform.isClient() ) + + // The part is enabled if all features + integrations it needs are enabled + this.enabled = features.stream().allMatch( AEConfig.instance::isFeatureEnabled ) + && integrations.stream().allMatch( IntegrationRegistry.INSTANCE::isEnabled ); + + if( enabled ) { - this.itemModels = createItemModels( itemModel ); - } - if( c != null ) - { - this.models = new HashSet<>( PartModelsHelper.createModels( c ) ); + // Only load models if the part is enabled, otherwise we also run into class-loading issues while + // scanning for annotations + if( Platform.isClient() ) + { + this.itemModels = createItemModels( itemModel ); + } + if( c != null ) + { + this.models = new HashSet<>( PartModelsHelper.createModels( c ) ); + } + else + { + this.models = Collections.emptySet(); + } } else { + this.itemModels = Collections.emptyList(); this.models = Collections.emptySet(); } } @@ -289,6 +315,11 @@ public enum PartType return new ModelResourceLocation( new ResourceLocation( AppEng.MOD_ID, "part/" + baseName ), "inventory" ); } + public boolean isEnabled() + { + return enabled; + } + int getBaseDamage() { return this.baseDamage; diff --git a/src/main/java/appeng/parts/layers/InvLayerData.java b/src/main/java/appeng/parts/layers/InvLayerData.java deleted file mode 100644 index 795710dc7..000000000 --- a/src/main/java/appeng/parts/layers/InvLayerData.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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 java.util.List; - -import net.minecraft.inventory.IInventory; -import net.minecraft.inventory.ISidedInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumFacing; - - -public class InvLayerData -{ - - // a simple empty array for empty stuff.. - private static final int[] NULL_SIDES = {}; - - // cache of inventory state. - private final int[][] sides; - private final List inventories; - private final List slots; - - public InvLayerData( final int[][] a, final List b, final List c ) - { - this.sides = a; - this.inventories = b; - this.slots = c; - } - - public ItemStack decreaseStackSize( final int slot, final int amount ) - { - if( this.isSlotValid( slot ) ) - { - return this.slots.get( slot ).decreaseStackSize( amount ); - } - - return null; - } - - /** - * check if a slot index is valid, prevent crashes from bad code :) - * - * @param slot slot index - * - * @return true, if the slot exists. - */ - boolean isSlotValid( final int slot ) - { - return this.slots != null && slot >= 0 && slot < this.slots.size(); - } - - int getSizeInventory() - { - if( this.slots == null ) - { - return 0; - } - - return this.slots.size(); - } - - public ItemStack getStackInSlot( final int slot ) - { - if( this.isSlotValid( slot ) ) - { - return this.slots.get( slot ).getStackInSlot(); - } - - return null; - } - - public boolean isItemValidForSlot( final int slot, final ItemStack itemstack ) - { - if( this.isSlotValid( slot ) ) - { - return this.slots.get( slot ).isItemValidForSlot( itemstack ); - } - - return false; - } - - public void setInventorySlotContents( final int slot, final ItemStack itemstack ) - { - if( this.isSlotValid( slot ) ) - { - this.slots.get( slot ).setInventorySlotContents( itemstack ); - } - } - - public boolean canExtractItem( final int slot, final ItemStack itemstack, final EnumFacing side ) - { - if( this.isSlotValid( slot ) ) - { - return this.slots.get( slot ).canExtractItem( itemstack, side ); - } - - return false; - } - - public boolean canInsertItem( final int slot, final ItemStack itemstack, final EnumFacing side ) - { - if( this.isSlotValid( slot ) ) - { - return this.slots.get( slot ).canInsertItem( itemstack, side ); - } - - return false; - } - - void markDirty() - { - if( this.inventories != null ) - { - for( final IInventory inv : this.inventories ) - { - inv.markDirty(); - } - } - } - - public int[] getSlotsForFace( final EnumFacing side ) - { - if( this.sides == null || side == null ) - { - return NULL_SIDES; - } - return this.sides[side.ordinal()]; - } -} diff --git a/src/main/java/appeng/parts/layers/InvSot.java b/src/main/java/appeng/parts/layers/InvSot.java deleted file mode 100644 index 20f4b0134..000000000 --- a/src/main/java/appeng/parts/layers/InvSot.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 net.minecraft.inventory.ISidedInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumFacing; - - -public class InvSot -{ - - private final ISidedInventory partInv; - private final int index; - - public InvSot( final ISidedInventory part, final int slot ) - { - this.partInv = part; - this.index = slot; - } - - public ItemStack decreaseStackSize( final int j ) - { - return this.partInv.decrStackSize( this.index, j ); - } - - ItemStack getStackInSlot() - { - return this.partInv.getStackInSlot( this.index ); - } - - public boolean isItemValidForSlot( final ItemStack itemstack ) - { - return this.partInv.isItemValidForSlot( this.index, itemstack ); - } - - public void setInventorySlotContents( final ItemStack itemstack ) - { - this.partInv.setInventorySlotContents( this.index, itemstack ); - } - - public boolean canExtractItem( final ItemStack itemstack, final EnumFacing side ) - { - return this.partInv.canExtractItem( this.index, itemstack, side ); - } - - public boolean canInsertItem( final ItemStack itemstack, final EnumFacing side ) - { - return this.partInv.canInsertItem( this.index, itemstack, side ); - } -} diff --git a/src/main/java/appeng/parts/layers/LayerIEnergySink.java b/src/main/java/appeng/parts/layers/LayerIEnergySink.java index 84d4473c7..b000b0882 100644 --- a/src/main/java/appeng/parts/layers/LayerIEnergySink.java +++ b/src/main/java/appeng/parts/layers/LayerIEnergySink.java @@ -19,183 +19,186 @@ package appeng.parts.layers; -//import net.minecraft.tileentity.TileEntity; -//import net.minecraft.world.World; -//import net.minecraftforge.common.MinecraftForge; -//import ic2.api.energy.tile.IEnergyAcceptor; -//import ic2.api.energy.tile.IEnergySink; -//import ic2.api.energy.tile.IEnergyTile; -//import appeng.api.parts.IPart; -//import appeng.api.parts.IPartHost; -//import appeng.api.parts.LayerBase; -//import appeng.api.parts.LayerFlags; -//import appeng.api.util.ForgeDirection; -//import appeng.util.Platform; -// -// -//public class LayerIEnergySink extends LayerBase implements IEnergySink -//{ -// -// private TileEntity getEnergySinkTile() -// { -// IPartHost host = (IPartHost) this; -// return host.getTile(); -// } -// -// private World getEnergySinkWorld() -// { -// if( this.getEnergySinkTile() == null ) -// { -// return null; -// } -// -// return this.getEnergySinkTile().getWorld(); -// } -// -// private boolean isTileValid() -// { -// TileEntity te = this.getEnergySinkTile(); -// -// if( te == null ) -// { -// return false; -// } -// -// return !te.isInvalid() && te.getWorld().blockExists( te.xCoord, te.yCoord, te.zCoord ); -// } -// -// private void addToENet() -// { -// if( this.getEnergySinkWorld() == null ) -// { -// return; -// } -// -// // re-add -// this.removeFromENet(); -// -// if( !this.isInIC2() && Platform.isServer() && this.isTileValid() ) -// { -// this.getLayerFlags().add( LayerFlags.IC2_ENET ); -// MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileLoadEvent( (IEnergyTile) this.getEnergySinkTile() ) ); -// } -// } -// -// private void removeFromENet() -// { -// if( this.getEnergySinkWorld() == null ) -// { -// return; -// } -// -// if( this.isInIC2() && Platform.isServer() ) -// { -// this.getLayerFlags().remove( LayerFlags.IC2_ENET ); -// MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileUnloadEvent( (IEnergyTile) this.getEnergySinkTile() ) ); -// } -// } -// -// private boolean interestedInIC2() -// { -// if( !( (IPartHost) this ).isInWorld() ) -// { -// return false; -// } -// -// int interested = 0; -// for( ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS ) -// { -// IPart part = this.getPart( dir ); -// if( part instanceof IEnergyTile ) -// { -// interested++; -// } -// } -// return interested == 1;// if more then one tile is interested we need to abandon... -// } -// -// @Override -// public void partChanged() -// { -// super.partChanged(); -// -// if( this.interestedInIC2() ) -// { -// this.addToENet(); -// } -// else -// { -// this.removeFromENet(); -// } -// } -// -// @Override -// public boolean acceptsEnergyFrom( TileEntity emitter, ForgeDirection direction ) -// { -// if( !this.isInIC2() ) -// { -// return false; -// } -// -// IPart part = this.getPart( direction ); -// if( part instanceof IEnergySink ) -// { -// return ( (IEnergyAcceptor) part ).acceptsEnergyFrom( emitter, direction ); -// } -// return false; -// } -// -// private boolean isInIC2() -// { -// return this.getLayerFlags().contains( LayerFlags.IC2_ENET ); -// } -// -// @Override -// public double getDemandedEnergy() -// { -// if( !this.isInIC2() ) -// { -// return 0; -// } -// -// // this is a flawed implementation, that requires a change to the IC2 API. -// -// for( ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS ) -// { -// IPart part = this.getPart( dir ); -// if( part instanceof IEnergySink ) -// { -// // use lower number cause ic2 deletes power it sends that isn't received. -// return ( (IEnergySink) part ).getDemandedEnergy(); -// } -// } -// -// return 0; -// } -// -// @Override -// public int getSinkTier() -// { -// return Integer.MAX_VALUE; // no real options here... -// } -// -// @Override -// public double injectEnergy( ForgeDirection directionFrom, double amount, double voltage ) -// { -// if( !this.isInIC2() ) -// { -// return amount; -// } -// -// for( ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS ) -// { -// IPart part = this.getPart( dir ); -// if( part instanceof IEnergySink ) -// { -// return ( (IEnergySink) part ).injectEnergy( directionFrom, amount, voltage ); -// } -// } -// -// return amount; -// } -// } +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; + +import ic2.api.energy.tile.IEnergyAcceptor; +import ic2.api.energy.tile.IEnergyEmitter; +import ic2.api.energy.tile.IEnergySink; +import ic2.api.energy.tile.IEnergyTile; + +import appeng.api.parts.IPart; +import appeng.api.parts.IPartHost; +import appeng.api.parts.LayerBase; +import appeng.api.parts.LayerFlags; +import appeng.util.Platform; + + +public class LayerIEnergySink extends LayerBase implements IEnergySink +{ + + private TileEntity getEnergySinkTile() + { + IPartHost host = (IPartHost) this; + return host.getTile(); + } + + private World getEnergySinkWorld() + { + if( this.getEnergySinkTile() == null ) + { + return null; + } + + return this.getEnergySinkTile().getWorld(); + } + + private boolean isTileValid() + { + TileEntity te = this.getEnergySinkTile(); + + if( te == null ) + { + return false; + } + + return !te.isInvalid() && te.getWorld().isBlockLoaded( te.getPos() ); + } + + private void addToENet() + { + if( this.getEnergySinkWorld() == null ) + { + return; + } + + // re-add + this.removeFromENet(); + + if( !this.isInIC2() && Platform.isServer() && this.isTileValid() ) + { + this.getLayerFlags().add( LayerFlags.IC2_ENET ); + MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileLoadEvent( (IEnergyTile) this.getEnergySinkTile() ) ); + } + } + + private void removeFromENet() + { + if( this.getEnergySinkWorld() == null ) + { + return; + } + + if( this.isInIC2() && Platform.isServer() ) + { + this.getLayerFlags().remove( LayerFlags.IC2_ENET ); + MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileUnloadEvent( (IEnergyTile) this.getEnergySinkTile() ) ); + } + } + + private boolean interestedInIC2() + { + if( !( (IPartHost) this ).isInWorld() ) + { + return false; + } + + int interested = 0; + for( EnumFacing dir : EnumFacing.values() ) + { + IPart part = this.getPart( dir ); + if( part instanceof IEnergyTile ) + { + interested++; + } + } + return interested == 1;// if more then one tile is interested we need to abandon... + } + + @Override + public void partChanged() + { + super.partChanged(); + + if( this.interestedInIC2() ) + { + this.addToENet(); + } + else + { + this.removeFromENet(); + } + } + + @Override + public boolean acceptsEnergyFrom( IEnergyEmitter emitter, EnumFacing direction ) + { + if( !this.isInIC2() ) + { + return false; + } + + IPart part = this.getPart( direction ); + if( part instanceof IEnergySink ) + { + return ( (IEnergyAcceptor) part ).acceptsEnergyFrom( emitter, direction ); + } + return false; + } + + private boolean isInIC2() + { + return this.getLayerFlags().contains( LayerFlags.IC2_ENET ); + } + + @Override + public double getDemandedEnergy() + { + if( !this.isInIC2() ) + { + return 0; + } + + // this is a flawed implementation, that requires a change to the IC2 API. + + for( EnumFacing dir : EnumFacing.values() ) + { + IPart part = this.getPart( dir ); + if( part instanceof IEnergySink ) + { + // use lower number cause ic2 deletes power it sends that isn't received. + return ( (IEnergySink) part ).getDemandedEnergy(); + } + } + + return 0; + } + + @Override + public int getSinkTier() + { + return Integer.MAX_VALUE; // no real options here... + } + + @Override + public double injectEnergy( EnumFacing directionFrom, double amount, double voltage ) + { + if( !this.isInIC2() ) + { + return amount; + } + + for( EnumFacing dir : EnumFacing.values() ) + { + IPart part = this.getPart( dir ); + if( part instanceof IEnergySink ) + { + return ( (IEnergySink) part ).injectEnergy( directionFrom, amount, voltage ); + } + } + + return amount; + } +} diff --git a/src/main/java/appeng/parts/layers/LayerIEnergySource.java b/src/main/java/appeng/parts/layers/LayerIEnergySource.java index 1f0fe65db..652492b7e 100644 --- a/src/main/java/appeng/parts/layers/LayerIEnergySource.java +++ b/src/main/java/appeng/parts/layers/LayerIEnergySource.java @@ -19,188 +19,189 @@ package appeng.parts.layers; -//import net.minecraft.tileentity.TileEntity; -//import net.minecraft.world.World; -//import net.minecraftforge.common.MinecraftForge; -//import ic2.api.energy.tile.IEnergyEmitter; -//import ic2.api.energy.tile.IEnergySink; -//import ic2.api.energy.tile.IEnergySource; -//import ic2.api.energy.tile.IEnergyTile; -//import appeng.api.parts.IPart; -//import appeng.api.parts.IPartHost; -//import appeng.api.parts.LayerBase; -//import appeng.api.parts.LayerFlags; -//import appeng.api.util.ForgeDirection; -//import appeng.util.Platform; -// -// -//public class LayerIEnergySource extends LayerBase implements IEnergySource -//{ -// -// private TileEntity getEnergySourceTile() -// { -// IPartHost host = (IPartHost) this; -// return host.getTile(); -// } -// -// private World getEnergySourceWorld() -// { -// if( this.getEnergySourceTile() == null ) -// { -// return null; -// } -// return this.getEnergySourceTile().getWorld(); -// } -// -// private boolean isTileValid() -// { -// TileEntity te = this.getEnergySourceTile(); -// if( te == null ) -// { -// return false; -// } -// return !te.isInvalid(); -// } -// -// private void addToENet() -// { -// if( this.getEnergySourceWorld() == null ) -// { -// return; -// } -// -// // re-add -// this.removeFromENet(); -// -// if( !this.isInIC2() && Platform.isServer() && this.isTileValid() ) -// { -// this.getLayerFlags().add( LayerFlags.IC2_ENET ); -// MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileLoadEvent( (IEnergyTile) this.getEnergySourceTile() ) ); -// } -// } -// -// private void removeFromENet() -// { -// if( this.getEnergySourceWorld() == null ) -// { -// return; -// } -// -// if( this.isInIC2() && Platform.isServer() ) -// { -// this.getLayerFlags().remove( LayerFlags.IC2_ENET ); -// MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileUnloadEvent( (IEnergyTile) this.getEnergySourceTile() ) ); -// } -// } -// -// private boolean interestedInIC2() -// { -// if( !( (IPartHost) this ).isInWorld() ) -// { -// return false; -// } -// -// int interested = 0; -// for( ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS ) -// { -// IPart part = this.getPart( dir ); -// if( part instanceof IEnergyTile ) -// { -// interested++; -// } -// } -// return interested == 1;// if more then one tile is interested we need to abandon... -// } -// -// @Override -// public void partChanged() -// { -// super.partChanged(); -// -// if( this.interestedInIC2() ) -// { -// this.addToENet(); -// } -// else -// { -// this.removeFromENet(); -// } -// } -// -// @Override -// public boolean emitsEnergyTo( TileEntity receiver, ForgeDirection direction ) -// { -// if( !this.isInIC2() ) -// { -// return false; -// } -// -// IPart part = this.getPart( direction ); -// if( part instanceof IEnergySink ) -// { -// return ( (IEnergyEmitter) part ).emitsEnergyTo( receiver, direction ); -// } -// return false; -// } -// -// private boolean isInIC2() -// { -// return this.getLayerFlags().contains( LayerFlags.IC2_ENET ); -// } -// -// @Override -// public double getOfferedEnergy() -// { -// if( !this.isInIC2() ) -// { -// return 0; -// } -// -// // this is a flawed implementation, that requires a change to the IC2 API. -// -// for( ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS ) -// { -// IPart part = this.getPart( dir ); -// if( part instanceof IEnergySource ) -// { -// // use lower number cause ic2 deletes power it sends that isn't received. -// return ( (IEnergySource) part ).getOfferedEnergy(); -// } -// } -// -// return 0; -// } -// -// @Override -// public void drawEnergy( double amount ) -// { -// // this is a flawed implementation, that requires a change to the IC2 API. -// -// for( ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS ) -// { -// IPart part = this.getPart( dir ); -// if( part instanceof IEnergySource ) -// { -// ( (IEnergySource) part ).drawEnergy( amount ); -// return; -// } -// } -// } -// -// @Override -// public int getSourceTier() -// { -// // this is a flawed implementation, that requires a change to the IC2 API. -// -// for( ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS ) -// { -// IPart part = this.getPart( dir ); -// if( part instanceof IEnergySource ) -// { -// return ( (IEnergySource) part ).getSourceTier(); -// } -// } -// -// return 0; -// } -// } +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; + +import ic2.api.energy.tile.IEnergyAcceptor; +import ic2.api.energy.tile.IEnergyEmitter; +import ic2.api.energy.tile.IEnergySource; +import ic2.api.energy.tile.IEnergyTile; + +import appeng.api.parts.IPart; +import appeng.api.parts.IPartHost; +import appeng.api.parts.LayerBase; +import appeng.api.parts.LayerFlags; +import appeng.util.Platform; + + +public class LayerIEnergySource extends LayerBase implements IEnergySource +{ + + private TileEntity getEnergySourceTile() + { + IPartHost host = (IPartHost) this; + return host.getTile(); + } + + private World getEnergySourceWorld() + { + if( this.getEnergySourceTile() == null ) + { + return null; + } + return this.getEnergySourceTile().getWorld(); + } + + private boolean isTileValid() + { + TileEntity te = this.getEnergySourceTile(); + return te != null && !te.isInvalid(); + } + + private void addToENet() + { + if( this.getEnergySourceWorld() == null ) + { + return; + } + + // re-add + this.removeFromENet(); + + if( !this.isInIC2() && Platform.isServer() && this.isTileValid() ) + { + this.getLayerFlags().add( LayerFlags.IC2_ENET ); + MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileLoadEvent( (IEnergyTile) this.getEnergySourceTile() ) ); + } + } + + private void removeFromENet() + { + if( this.getEnergySourceWorld() == null ) + { + return; + } + + if( this.isInIC2() && Platform.isServer() ) + { + this.getLayerFlags().remove( LayerFlags.IC2_ENET ); + MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileUnloadEvent( (IEnergyTile) this.getEnergySourceTile() ) ); + } + } + + private boolean interestedInIC2() + { + if( !( (IPartHost) this ).isInWorld() ) + { + return false; + } + + int interested = 0; + for( EnumFacing dir : EnumFacing.values() ) + { + IPart part = this.getPart( dir ); + if( part instanceof IEnergyTile ) + { + interested++; + } + } + return interested == 1;// if more then one tile is interested we need to abandon... + } + + @Override + public void partChanged() + { + super.partChanged(); + + if( this.interestedInIC2() ) + { + this.addToENet(); + } + else + { + this.removeFromENet(); + } + } + + @Override + public boolean emitsEnergyTo( IEnergyAcceptor receiver, EnumFacing direction ) + { + if( !this.isInIC2() ) + { + return false; + } + + IPart part = this.getPart( direction ); + if( part instanceof IEnergyEmitter ) + { + return ( (IEnergyEmitter) part ).emitsEnergyTo( receiver, direction ); + } + return false; + } + + private boolean isInIC2() + { + return this.getLayerFlags().contains( LayerFlags.IC2_ENET ); + } + + @Override + public double getOfferedEnergy() + { + if( !this.isInIC2() ) + { + return 0; + } + + // this is a flawed implementation, that requires a change to the IC2 API. + + for( EnumFacing dir : EnumFacing.values() ) + { + IPart part = this.getPart( dir ); + if( part instanceof IEnergySource ) + { + // use lower number cause ic2 deletes power it sends that isn't received. + return ( (IEnergySource) part ).getOfferedEnergy(); + } + } + + return 0; + } + + @Override + public void drawEnergy( double amount ) + { + // this is a flawed implementation, that requires a change to the IC2 API. + + for( EnumFacing dir : EnumFacing.values() ) + { + IPart part = this.getPart( dir ); + if( part instanceof IEnergySource ) + { + ( (IEnergySource) part ).drawEnergy( amount ); + return; + } + } + } + + @Override + public int getSourceTier() + { + // this is a flawed implementation, that requires a change to the IC2 API. + + for( EnumFacing dir : EnumFacing.values() ) + { + IPart part = this.getPart( dir ); + if( part instanceof IEnergySource ) + { + return ( (IEnergySource) part ).getSourceTier(); + } + } + + return 0; + } + + + +} diff --git a/src/main/java/appeng/parts/layers/LayerIFluidHandler.java b/src/main/java/appeng/parts/layers/LayerIFluidHandler.java deleted file mode 100644 index 52e74c655..000000000 --- a/src/main/java/appeng/parts/layers/LayerIFluidHandler.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 net.minecraftforge.fluids.FluidStack; -//import net.minecraftforge.fluids.FluidTankInfo; -//import net.minecraftforge.fluids.IFluidHandler; -//import appeng.api.parts.IPart; -//import appeng.api.parts.LayerBase; -//import appeng.api.util.ForgeDirection; -// -// -//public class LayerIFluidHandler extends LayerBase implements IFluidHandler -//{ -// -// private static final FluidTankInfo[] EMPTY_LIST = new FluidTankInfo[0]; -// -// @Override -// public int fill( ForgeDirection from, FluidStack resource, boolean doFill ) -// { -// IPart part = this.getPart( from ); -// if( part instanceof IFluidHandler ) -// { -// return ( (IFluidHandler) part ).fill( from, resource, doFill ); -// } -// return 0; -// } -// -// @Override -// public FluidStack drain( ForgeDirection from, FluidStack resource, boolean doDrain ) -// { -// IPart part = this.getPart( from ); -// if( part instanceof IFluidHandler ) -// { -// return ( (IFluidHandler) part ).drain( from, resource, doDrain ); -// } -// return null; -// } -// -// @Override -// public FluidStack drain( ForgeDirection from, int maxDrain, boolean doDrain ) -// { -// IPart part = this.getPart( from ); -// if( part instanceof IFluidHandler ) -// { -// return ( (IFluidHandler) part ).drain( from, maxDrain, doDrain ); -// } -// return null; -// } -// -// @Override -// public boolean canFill( ForgeDirection from, net.minecraftforge.fluids.Fluid fluid ) -// { -// IPart part = this.getPart( from ); -// if( part instanceof IFluidHandler ) -// { -// return ( (IFluidHandler) part ).canFill( from, fluid ); -// } -// return false; -// } -// -// @Override -// public boolean canDrain( ForgeDirection from, net.minecraftforge.fluids.Fluid fluid ) -// { -// IPart part = this.getPart( from ); -// if( part instanceof IFluidHandler ) -// { -// return ( (IFluidHandler) part ).canDrain( from, fluid ); -// } -// return false; -// } -// -// @Override -// public FluidTankInfo[] getTankInfo( ForgeDirection from ) -// { -// IPart part = this.getPart( from ); -// if( part instanceof IFluidHandler ) -// { -// return ( (IFluidHandler) part ).getTankInfo( from ); -// } -// return EMPTY_LIST; -// } -// } diff --git a/src/main/java/appeng/parts/layers/LayerIPipeConnection.java b/src/main/java/appeng/parts/layers/LayerIPipeConnection.java deleted file mode 100644 index 42cf778ba..000000000 --- a/src/main/java/appeng/parts/layers/LayerIPipeConnection.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of Applied Energistics 2. - * Copyright (c) 2013 - 2015, 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 buildcraft.api.transport.IPipeConnection; -//import buildcraft.api.transport.IPipeTile.PipeType; -//import appeng.api.parts.IPart; -//import appeng.api.parts.LayerBase; -//import appeng.api.util.ForgeDirection; -//import appeng.helpers.Reflected; -// -// -//@Reflected -//public class LayerIPipeConnection extends LayerBase implements IPipeConnection -//{ -// -// @Override -// public ConnectOverride overridePipeConnection( PipeType type, ForgeDirection with ) -// { -// IPart part = this.getPart( with ); -// if( part instanceof IPipeConnection ) -// { -// return ( (IPipeConnection) part ).overridePipeConnection( type, with ); -// } -// return ConnectOverride.DEFAULT; -// } -// } diff --git a/src/main/java/appeng/parts/layers/LayerISidedInventory.java b/src/main/java/appeng/parts/layers/LayerISidedInventory.java deleted file mode 100644 index 502821d81..000000000 --- a/src/main/java/appeng/parts/layers/LayerISidedInventory.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * 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 java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.IInventory; -import net.minecraft.inventory.ISidedInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.text.ITextComponent; - -import appeng.api.parts.IPart; -import appeng.api.parts.IPartHost; -import appeng.api.parts.LayerBase; -import appeng.api.util.AEPartLocation; - - -/** - * Inventory wrapper for parts, - * - * this is considerably more complicated then the other wrappers as it requires creating a "unified inventory". - * - * You must use {@link ISidedInventory} instead of {@link IInventory}. - * - * If your inventory changes in between placement and removal, you must trigger a PartChange on the {@link IPartHost} so - * it can recalculate the inventory wrapper. - */ -public class LayerISidedInventory extends LayerBase implements ISidedInventory -{ - - // a simple empty array for empty stuff.. - private static final int[] NULL_SIDES = {}; - - private InvLayerData invLayer = null; - - /** - * Recalculate inventory wrapper cache. - */ - @Override - public void notifyNeighbors() - { - // cache of inventory state. - int[][] sideData = null; - List inventories = null; - List slots = null; - - inventories = new ArrayList(); - int slotCount = 0; - - for( final AEPartLocation side : AEPartLocation.SIDE_LOCATIONS ) - { - final IPart bp = this.getPart( side ); - if( bp instanceof ISidedInventory ) - { - final ISidedInventory part = (ISidedInventory) bp; - slotCount += part.getSizeInventory(); - inventories.add( part ); - } - } - - if( inventories.isEmpty() || slotCount == 0 ) - { - inventories = null; - } - else - { - sideData = new int[][] { NULL_SIDES, NULL_SIDES, NULL_SIDES, NULL_SIDES, NULL_SIDES, NULL_SIDES }; - slots = new ArrayList( Collections.nCopies( slotCount, (InvSot) null ) ); - - int offsetForLayer = 0; - int offsetForPart = 0; - for( final ISidedInventory sides : inventories ) - { - offsetForPart = 0; - slotCount = sides.getSizeInventory(); - - AEPartLocation currentSide = AEPartLocation.INTERNAL; - for( final AEPartLocation side : AEPartLocation.SIDE_LOCATIONS ) - { - if( this.getPart( side ) == sides ) - { - currentSide = side; - break; - } - } - - final int[] cSidesList = sideData[currentSide.ordinal()] = new int[slotCount]; - for( int cSlot = 0; cSlot < slotCount; cSlot++ ) - { - cSidesList[cSlot] = offsetForLayer; - slots.set( offsetForLayer, new InvSot( sides, offsetForPart ) ); - offsetForLayer++; - offsetForPart++; - } - } - } - - if( sideData == null || slots == null ) - { - this.invLayer = null; - } - else - { - this.invLayer = new InvLayerData( sideData, inventories, slots ); - } - - // make sure inventory is updated before we call FMP. - super.notifyNeighbors(); - } - - @Override - public int getSizeInventory() - { - if( this.invLayer == null ) - { - return 0; - } - - return this.invLayer.getSizeInventory(); - } - - @Override - public ItemStack getStackInSlot( final int slot ) - { - if( this.invLayer == null ) - { - return null; - } - - return this.invLayer.getStackInSlot( slot ); - } - - @Override - public ItemStack decrStackSize( final int slot, final int amount ) - { - if( this.invLayer == null ) - { - return null; - } - - return this.invLayer.decreaseStackSize( slot, amount ); - } - - @Override - public ItemStack removeStackFromSlot( final int slot ) - { - return null; - } - - @Override - public void setInventorySlotContents( final int slot, final ItemStack itemstack ) - { - if( this.invLayer == null ) - { - return; - } - - this.invLayer.setInventorySlotContents( slot, itemstack ); - } - - @Override - public String getName() - { - return "AEMultiPart"; - } - - @Override - public boolean hasCustomName() - { - return false; - } - - @Override - public int getInventoryStackLimit() - { - return 64; // no options here. - } - - @Override - public boolean isUseableByPlayer( final EntityPlayer entityplayer ) - { - return false; - } - - @Override - public void openInventory( final EntityPlayer player ) - { - } - - @Override - public void closeInventory( final EntityPlayer player ) - { - } - - @Override - public boolean isItemValidForSlot( final int slot, final ItemStack itemstack ) - { - if( this.invLayer == null ) - { - return false; - } - - return this.invLayer.isItemValidForSlot( slot, itemstack ); - } - - @Override - public void markDirty() - { - if( this.invLayer != null ) - { - this.invLayer.markDirty(); - } - - super.markForSave(); - } - - @Override - public int[] getSlotsForFace( final EnumFacing side ) - { - if( this.invLayer != null ) - { - return this.invLayer.getSlotsForFace( side ); - } - - return NULL_SIDES; - } - - @Override - public boolean canInsertItem( final int slot, final ItemStack itemstack, final EnumFacing side ) - { - if( this.invLayer == null ) - { - return false; - } - - return this.invLayer.canInsertItem( slot, itemstack, side ); - } - - @Override - public boolean canExtractItem( final int slot, final ItemStack itemstack, final EnumFacing side ) - { - if( this.invLayer == null ) - { - return false; - } - - return this.invLayer.canExtractItem( slot, itemstack, side ); - } - - @Override - public int getField( final int id ) - { - return 0; - } - - @Override - public void setField( final int id, final int value ) - { - - } - - @Override - public int getFieldCount() - { - return 0; - } - - @Override - public void clear() - { - - } - - @Override - public ITextComponent getDisplayName() - { - return null; - } -} diff --git a/src/main/java/appeng/parts/layers/LayerPressure.java b/src/main/java/appeng/parts/layers/LayerPressure.java deleted file mode 100644 index 542065c31..000000000 --- a/src/main/java/appeng/parts/layers/LayerPressure.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 pneumaticCraft.api.tileentity.IAirHandler; -//import pneumaticCraft.api.tileentity.ISidedPneumaticMachine; -// -//import appeng.api.parts.IPart; -//import appeng.api.parts.LayerBase; -// -// -//public class LayerPressure extends LayerBase implements ISidedPneumaticMachine -//{ -// -// @Nullable -// @Override -// public IAirHandler getAirHandler( ForgeDirection side ) -// { -// IPart part = this.getPart( side ); -// if( part instanceof ISidedPneumaticMachine ) -// { -// return ( (ISidedPneumaticMachine) part ).getAirHandler( side ); -// } -// -// return null; -// } -// -// } diff --git a/src/main/java/appeng/parts/layers/LayerSidedEnvironment.java b/src/main/java/appeng/parts/layers/LayerSidedEnvironment.java deleted file mode 100644 index 9df88befa..000000000 --- a/src/main/java/appeng/parts/layers/LayerSidedEnvironment.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.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.api.util.ForgeDirection; -//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/PartP2PIC2Power.java b/src/main/java/appeng/parts/p2p/PartP2PIC2Power.java index d63876946..041313884 100644 --- a/src/main/java/appeng/parts/p2p/PartP2PIC2Power.java +++ b/src/main/java/appeng/parts/p2p/PartP2PIC2Power.java @@ -19,247 +19,245 @@ package appeng.parts.p2p; -//import java.util.LinkedList; -// -//import net.minecraft.init.Blocks; -//import net.minecraft.item.ItemStack; -//import net.minecraft.nbt.NBTTagCompound; -//import net.minecraft.tileentity.TileEntity; -//import net.minecraft.util.IIcon; -//import net.minecraftforge.common.util.ForgeDirection; -// -//import cpw.mods.fml.relauncher.Side; -//import cpw.mods.fml.relauncher.SideOnly; -// -//import appeng.api.config.PowerUnits; -//import appeng.integration.IntegrationType; -//import appeng.me.GridAccessException; -//import appeng.me.cache.helpers.TunnelCollection; -//import appeng.transformer.annotations.Integration.Interface; -//import appeng.transformer.annotations.Integration.InterfaceList; -//import appeng.util.Platform; -// -// -//@InterfaceList( value = { @Interface( iface = "ic2.api.energy.tile.IEnergySink", iname = IntegrationType.IC2 ), @Interface( iface = "ic2.api.energy.tile.IEnergySource", iname = IntegrationType.IC2 ) } ) -//public class PartP2PIC2Power extends PartP2PTunnel implements ic2.api.energy.tile.IEnergySink, ic2.api.energy.tile.IEnergySource -//{ -// -// // two packet buffering... -// double OutputEnergyA; -// double OutputEnergyB; -// // two packet buffering... -// double OutputVoltageA; -// double OutputVoltageB; -// -// public PartP2PIC2Power( ItemStack is ) -// { -// super( is ); -// } -// -// @Override -// @SideOnly( Side.CLIENT ) -// public IIcon getTypeTexture() -// { -// return Blocks.diamond_block.getBlockTextureFromSide( 0 ); -// } -// -// @Override -// public void readFromNBT( NBTTagCompound tag ) -// { -// super.readFromNBT( tag ); -// this.OutputEnergyA = tag.getDouble( "OutputPacket" ); -// this.OutputEnergyB = tag.getDouble( "OutputPacket2" ); -// this.OutputVoltageA = tag.getDouble( "OutputVoltageA" ); -// this.OutputVoltageB = tag.getDouble( "OutputVoltageB" ); -// } -// -// @Override -// public void writeToNBT( NBTTagCompound tag ) -// { -// super.writeToNBT( tag ); -// tag.setDouble( "OutputPacket", this.OutputEnergyA ); -// tag.setDouble( "OutputPacket2", this.OutputEnergyB ); -// tag.setDouble( "OutputVoltageA", this.OutputVoltageA ); -// tag.setDouble( "OutputVoltageB", this.OutputVoltageB ); -// } -// -// @Override -// public void onTunnelConfigChange() -// { -// this.getHost().partChanged(); -// } -// -// @Override -// public void onTunnelNetworkChange() -// { -// this.getHost().notifyNeighbors(); -// } -// -// @Override -// public boolean acceptsEnergyFrom( TileEntity emitter, ForgeDirection direction ) -// { -// if( !this.output ) -// { -// return direction == this.side; -// } -// return false; -// } -// -// @Override -// public boolean emitsEnergyTo( TileEntity receiver, ForgeDirection direction ) -// { -// if( this.output ) -// { -// return direction == this.side; -// } -// return false; -// } -// -// @Override -// public double getDemandedEnergy() -// { -// if( this.output ) -// { -// return 0; -// } -// -// try -// { -// for( PartP2PIC2Power t : this.getOutputs() ) -// { -// if( t.OutputEnergyA <= 0.0001 || t.OutputEnergyB <= 0.0001 ) -// { -// return 2048; -// } -// } -// } -// catch( GridAccessException e ) -// { -// return 0; -// } -// -// return 0; -// } -// -// @Override -// public int getSinkTier() -// { -// return 4; -// } -// -// @Override -// public double injectEnergy( ForgeDirection directionFrom, double amount, double voltage ) -// { -// TunnelCollection outs; -// try -// { -// outs = this.getOutputs(); -// } -// catch( GridAccessException e ) -// { -// return amount; -// } -// -// if( outs.isEmpty() ) -// { -// return amount; -// } -// -// LinkedList options = new LinkedList(); -// for( PartP2PIC2Power o : outs ) -// { -// if( o.OutputEnergyA <= 0.01 ) -// { -// options.add( o ); -// } -// } -// -// if( options.isEmpty() ) -// { -// for( PartP2PIC2Power o : outs ) -// { -// if( o.OutputEnergyB <= 0.01 ) -// { -// options.add( o ); -// } -// } -// } -// -// if( options.isEmpty() ) -// { -// for( PartP2PIC2Power o : outs ) -// { -// options.add( o ); -// } -// } -// -// if( options.isEmpty() ) -// { -// return amount; -// } -// -// PartP2PIC2Power x = Platform.pickRandom( options ); -// -// if( x != null && x.OutputEnergyA <= 0.001 ) -// { -// this.queueTunnelDrain( PowerUnits.EU, amount ); -// x.OutputEnergyA = amount; -// x.OutputVoltageA = voltage; -// return 0; -// } -// -// if( x != null && x.OutputEnergyB <= 0.001 ) -// { -// this.queueTunnelDrain( PowerUnits.EU, amount ); -// x.OutputEnergyB = amount; -// x.OutputVoltageB = voltage; -// return 0; -// } -// -// return amount; -// } -// -// public float getPowerDrainPerTick() -// { -// return 0.5f; -// } -// -// @Override -// public double getOfferedEnergy() -// { -// if( this.output ) -// { -// return this.OutputEnergyA; -// } -// return 0; -// } -// -// @Override -// public void drawEnergy( double amount ) -// { -// this.OutputEnergyA -= amount; -// if( this.OutputEnergyA < 0.001 ) -// { -// this.OutputEnergyA = this.OutputEnergyB; -// this.OutputEnergyB = 0; -// -// this.OutputVoltageA = this.OutputVoltageB; -// this.OutputVoltageB = 0; -// } -// } -// -// @Override -// public int getSourceTier() -// { -// if( this.output ) -// { -// return this.calculateTierFromVoltage( this.OutputVoltageA ); -// } -// return 4; -// } -// -// private int calculateTierFromVoltage( double voltage ) -// { -// return ic2.api.energy.EnergyNet.instance.getTierFromPower( voltage ); -// } -// } +import java.util.LinkedList; +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; + +import ic2.api.energy.tile.IEnergyAcceptor; +import ic2.api.energy.tile.IEnergyEmitter; +import ic2.api.energy.tile.IEnergySink; +import ic2.api.energy.tile.IEnergySource; + +import appeng.api.config.PowerUnits; +import appeng.integration.IntegrationType; +import appeng.items.parts.PartModels; +import appeng.me.GridAccessException; +import appeng.me.cache.helpers.TunnelCollection; +import appeng.transformer.annotations.Integration.Interface; +import appeng.transformer.annotations.Integration.InterfaceList; +import appeng.util.Platform; + + +@InterfaceList( value = { + @Interface( iface = "ic2.api.energy.tile.IEnergySink", iname = IntegrationType.IC2 ), + @Interface( iface = "ic2.api.energy.tile.IEnergySource", iname = IntegrationType.IC2 ) +} ) +public class PartP2PIC2Power extends PartP2PTunnel implements IEnergySink, IEnergySource +{ + + private static final String TAG_BUFFERED_ENERGY_1 = "bufferedEnergy1"; + private static final String TAG_BUFFERED_ENERGY_2 = "bufferedEnergy2"; + private static final String TAG_BUFFERED_VOLTAGE_1 = "outputPacket1"; + private static final String TAG_BUFFERED_VOLTAGE_2 = "outputPacket2"; + + private static final P2PModels MODELS = new P2PModels( "part/p2p/p2p_tunnel_ic2" ); + + @PartModels + public static List getModels() + { + return MODELS.getModels(); + } + + // Buffer the energy + voltage for two IC2 ENET packets + private double bufferedEnergy1; + private double bufferedVoltage1; + private double bufferedEnergy2; + private double bufferedVoltage2; + + public PartP2PIC2Power( ItemStack is ) + { + super( is ); + } + + @Override + public void readFromNBT( NBTTagCompound tag ) + { + super.readFromNBT( tag ); + this.bufferedEnergy1 = tag.getDouble( TAG_BUFFERED_ENERGY_1 ); + this.bufferedEnergy2 = tag.getDouble( TAG_BUFFERED_ENERGY_2 ); + this.bufferedVoltage1 = tag.getDouble( TAG_BUFFERED_VOLTAGE_1 ); + this.bufferedVoltage2 = tag.getDouble( TAG_BUFFERED_VOLTAGE_2 ); + } + + @Override + public void writeToNBT( NBTTagCompound tag ) + { + super.writeToNBT( tag ); + tag.setDouble( TAG_BUFFERED_ENERGY_1, this.bufferedEnergy1 ); + tag.setDouble( TAG_BUFFERED_ENERGY_2, this.bufferedEnergy2 ); + tag.setDouble( TAG_BUFFERED_VOLTAGE_1, this.bufferedVoltage1 ); + tag.setDouble( TAG_BUFFERED_VOLTAGE_2, this.bufferedVoltage2 ); + } + + @Override + public void onTunnelConfigChange() + { + this.getHost().partChanged(); + } + + @Override + public void onTunnelNetworkChange() + { + this.getHost().notifyNeighbors(); + } + + @Override + public boolean acceptsEnergyFrom( IEnergyEmitter emitter, EnumFacing direction ) + { + return !this.isOutput() && direction == this.getSide().getFacing(); + } + + @Override + public boolean emitsEnergyTo( IEnergyAcceptor receiver, EnumFacing direction ) + { + return this.isOutput() && direction == this.getSide().getFacing(); + } + + @Override + public double getDemandedEnergy() + { + if( this.isOutput() ) + { + return 0; + } + + try + { + for( PartP2PIC2Power t : this.getOutputs() ) + { + if( t.bufferedEnergy1 <= 0.0001 || t.bufferedEnergy2 <= 0.0001 ) + { + return 2048; + } + } + } + catch( GridAccessException e ) + { + return 0; + } + + return 0; + } + + @Override + public int getSinkTier() + { + return 4; + } + + @Override + public double injectEnergy( EnumFacing directionFrom, double amount, double voltage ) + { + TunnelCollection outs; + try + { + outs = this.getOutputs(); + } + catch( GridAccessException e ) + { + return amount; + } + + if( outs.isEmpty() ) + { + return amount; + } + + LinkedList options = new LinkedList<>(); + for( PartP2PIC2Power o : outs ) + { + if( o.bufferedEnergy1 <= 0.01 ) + { + options.add( o ); + } + } + + if( options.isEmpty() ) + { + for( PartP2PIC2Power o : outs ) + { + if( o.bufferedEnergy2 <= 0.01 ) + { + options.add( o ); + } + } + } + + if( options.isEmpty() ) + { + for( PartP2PIC2Power o : outs ) + { + options.add( o ); + } + } + + if( options.isEmpty() ) + { + return amount; + } + + PartP2PIC2Power x = Platform.pickRandom( options ); + + if( x != null && x.bufferedEnergy1 <= 0.001 ) + { + this.queueTunnelDrain( PowerUnits.EU, amount ); + x.bufferedEnergy1 = amount; + x.bufferedVoltage1 = voltage; + return 0; + } + + if( x != null && x.bufferedEnergy2 <= 0.001 ) + { + this.queueTunnelDrain( PowerUnits.EU, amount ); + x.bufferedEnergy2 = amount; + x.bufferedVoltage2 = voltage; + return 0; + } + + return amount; + } + + @Override + public double getOfferedEnergy() + { + if( this.isOutput() ) + { + return this.bufferedEnergy1; + } + return 0; + } + + @Override + public void drawEnergy( double amount ) + { + this.bufferedEnergy1 -= amount; + if( this.bufferedEnergy1 < 0.001 ) + { + this.bufferedEnergy1 = this.bufferedEnergy2; + this.bufferedEnergy2 = 0; + + this.bufferedVoltage1 = this.bufferedVoltage2; + this.bufferedVoltage2 = 0; + } + } + + @Override + public int getSourceTier() + { + // Sadly IC2 doesn't support changing the tier once we're registered, so we + // go with the highest here... At this point it's somewhat unclear as to what effect + // this realistically has. + return 4; + } + + @Override + public List getStaticModels() + { + return MODELS.getModel( isPowered(), isActive() ); + } + +} diff --git a/src/main/java/appeng/parts/p2p/PartP2PTunnel.java b/src/main/java/appeng/parts/p2p/PartP2PTunnel.java index e75d193c4..9cb1cef01 100644 --- a/src/main/java/appeng/parts/p2p/PartP2PTunnel.java +++ b/src/main/java/appeng/parts/p2p/PartP2PTunnel.java @@ -235,14 +235,9 @@ public abstract class PartP2PTunnel extends PartBasicSt newType = parts.p2PTunnelLiquids().maybeStack( 1 ).orElse( null ); break; - /* - * case IC2_POWER: - * for( ItemStack stack : parts.p2PTunnelEU().maybeStack( 1 ).asSet() ) - * { - * newType = stack; - * } - * break; - */ + case IC2_POWER: + newType = parts.p2PTunnelEU().maybeStack( 1 ).orElse( null ); + break; case ITEM: newType = parts.p2PTunnelItems().maybeStack( 1 ).orElse( null ); diff --git a/src/main/resources/assets/appliedenergistics2/models/item/part/p2p_tunnel_ic2.json b/src/main/resources/assets/appliedenergistics2/models/item/part/p2p_tunnel_ic2.json new file mode 100644 index 000000000..97cf9ed48 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/part/p2p_tunnel_ic2.json @@ -0,0 +1,6 @@ +{ + "parent": "appliedenergistics2:item/part/p2p_tunnel", + "textures": { + "type": "minecraft:blocks/diamond_block" + } +} diff --git a/src/main/resources/assets/appliedenergistics2/models/part/p2p/p2p_tunnel_ic2.json b/src/main/resources/assets/appliedenergistics2/models/part/p2p/p2p_tunnel_ic2.json new file mode 100644 index 000000000..546f8e215 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/part/p2p/p2p_tunnel_ic2.json @@ -0,0 +1,6 @@ +{ + "parent": "appliedenergistics2:part/p2p/p2p_tunnel_base", + "textures": { + "type": "minecraft:blocks/diamond_block" + } +}