diff --git a/src/api/java/appeng/api/parts/IPart.java b/src/api/java/appeng/api/parts/IPart.java index 7e6f9819d..530bb7073 100644 --- a/src/api/java/appeng/api/parts/IPart.java +++ b/src/api/java/appeng/api/parts/IPart.java @@ -355,4 +355,14 @@ public interface IPart extends IBoxProvider, ICustomCableConnection return null; } + /** + * Flag to be passed to the renderer. + * + * @return flag or null + */ + default Long getRenderFlag() + { + return null; + } + } \ No newline at end of file diff --git a/src/api/java/appeng/api/parts/IPartBakedModel.java b/src/api/java/appeng/api/parts/IPartBakedModel.java new file mode 100644 index 000000000..6444fc91d --- /dev/null +++ b/src/api/java/appeng/api/parts/IPartBakedModel.java @@ -0,0 +1,15 @@ + +package appeng.api.parts; + + +import java.util.List; + +import javax.annotation.Nullable; + +import net.minecraft.client.renderer.block.model.BakedQuad; + + +public interface IPartBakedModel +{ + List getPartQuads( @Nullable Long partFlags, long rand ); +} diff --git a/src/main/java/appeng/client/render/cablebus/CableBusBakedModel.java b/src/main/java/appeng/client/render/cablebus/CableBusBakedModel.java index 9bfe79a8d..ee46d86c9 100644 --- a/src/main/java/appeng/client/render/cablebus/CableBusBakedModel.java +++ b/src/main/java/appeng/client/render/cablebus/CableBusBakedModel.java @@ -44,6 +44,7 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.common.property.IExtendedBlockState; +import appeng.api.parts.IPartBakedModel; import appeng.api.parts.IPartModel; import appeng.api.util.AECableType; import appeng.api.util.AEColor; @@ -119,7 +120,15 @@ public class CableBusBakedModel implements IBakedModel throw new IllegalStateException( "Trying to use an unregistered part model: " + model ); } - List partQuads = bakedModel.getQuads( state, null, rand ); + List partQuads; + if( bakedModel instanceof IPartBakedModel ) + { + partQuads = ( (IPartBakedModel) bakedModel ).getPartQuads( renderState.getPartFlags().get( facing ), rand ); + } + else + { + partQuads = bakedModel.getQuads( state, null, rand ); + } // Rotate quads accordingly QuadRotator rotator = new QuadRotator(); diff --git a/src/main/java/appeng/client/render/cablebus/CableBusRenderState.java b/src/main/java/appeng/client/render/cablebus/CableBusRenderState.java index 1f6bbc3f3..cbd5690a8 100644 --- a/src/main/java/appeng/client/render/cablebus/CableBusRenderState.java +++ b/src/main/java/appeng/client/render/cablebus/CableBusRenderState.java @@ -74,6 +74,8 @@ public class CableBusRenderState // facades on this cable bus private List boundingBoxes = new ArrayList<>(); + private EnumMap partFlags = new EnumMap<>( EnumFacing.class ); + public CableCoreType getCoreType() { return this.coreType; @@ -154,6 +156,11 @@ public class CableBusRenderState return this.boundingBoxes; } + public EnumMap getPartFlags() + { + return this.partFlags; + } + @Override public int hashCode() { @@ -166,6 +173,7 @@ public class CableBusRenderState result = prime * result + ( ( this.channelsOnSide == null ) ? 0 : this.channelsOnSide.hashCode() ); result = prime * result + ( ( this.connectionTypes == null ) ? 0 : this.connectionTypes.hashCode() ); result = prime * result + ( ( this.coreType == null ) ? 0 : this.coreType.hashCode() ); + result = prime * result + ( ( this.partFlags == null ) ? 0 : this.partFlags.hashCode() ); return result; } @@ -190,7 +198,7 @@ public class CableBusRenderState return this.cableColor == other.cableColor && this.cableType == other.cableType && this.coreType == other.coreType && Objects .equals( this.attachmentConnections, other.attachmentConnections ) && Objects.equals( this.cableBusAdjacent, other.cableBusAdjacent ) && Objects.equals( this.channelsOnSide, other.channelsOnSide ) && Objects.equals( this.connectionTypes, - other.connectionTypes ); + other.connectionTypes ) && Objects.equals( this.partFlags, other.partFlags ); } } diff --git a/src/main/java/appeng/client/render/cablebus/P2PTunnelFrequencyBakedModel.java b/src/main/java/appeng/client/render/cablebus/P2PTunnelFrequencyBakedModel.java new file mode 100644 index 000000000..7faa91ae4 --- /dev/null +++ b/src/main/java/appeng/client/render/cablebus/P2PTunnelFrequencyBakedModel.java @@ -0,0 +1,142 @@ + +package appeng.client.render.cablebus; + + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ItemOverrideList; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.util.EnumFacing; + +import appeng.api.parts.IPartBakedModel; +import appeng.api.util.AEColor; +import appeng.util.Platform; + + +public class P2PTunnelFrequencyBakedModel implements IBakedModel, IPartBakedModel +{ + private final VertexFormat format; + private final TextureAtlasSprite texture; + + private final static Cache> modelCache = CacheBuilder.newBuilder().maximumSize( 100 ).build(); + + private static final int[][] QUAD_OFFSETS = new int[][] { + { 4, 10, 2 }, + { 10, 10, 2 }, + { 4, 4, 2 }, + { 10, 4, 2 } + }; + + public P2PTunnelFrequencyBakedModel( final VertexFormat format, final TextureAtlasSprite texture ) + { + this.format = format; + this.texture = texture; + } + + @Override + public List getPartQuads( Long partFlags, long rand ) + { + try + { + return modelCache.get( partFlags, () -> + { + short frequency = 0; + boolean active = false; + if( partFlags != null ) + { + frequency = (short) ( partFlags.longValue() & 0xffffL ); + active = ( partFlags.longValue() & 0x10000L ) != 0; + } + return getQuadsForFrequency( frequency, active ); + } ); + } + catch( ExecutionException e ) + { + return Collections.emptyList(); + } + } + + @Override + public List getQuads( IBlockState state, EnumFacing side, long rand ) + { + if( side != null ) + { + return Collections.emptyList(); + } + return getPartQuads( null, rand ); + } + + private List getQuadsForFrequency( final short frequency, final boolean active ) + { + final AEColor[] colors = Platform.p2p().toColors( frequency ); + final CubeBuilder cb = new CubeBuilder( this.format ); + + cb.setTexture( this.texture ); + cb.useStandardUV(); + cb.setRenderFullBright( active ); + + for( int i = 0; i < 4; ++i ) + { + final int[] offs = QUAD_OFFSETS[i]; + for( int j = 0; j < 4; ++j ) + { + final AEColor c = colors[j]; + if( active ) + { + cb.setColorRGB( c.dye.getColorValue() ); + } + else + { + final float cv[] = c.dye.getColorComponentValues(); + cb.setColorRGB( cv[0] * 0.5f, cv[1] * 0.5f, cv[2] * 0.5f ); + } + + final int startx = j % 2; + final int starty = 1 - j / 2; + + cb.addCube( offs[0] + startx, offs[1] + starty, offs[2], offs[0] + startx + 1, offs[1] + starty + 1, offs[2] + 1 ); + } + + } + return cb.getOutput(); + } + + @Override + public boolean isAmbientOcclusion() + { + return false; + } + + @Override + public boolean isGui3d() + { + return false; + } + + @Override + public boolean isBuiltInRenderer() + { + return true; + } + + @Override + public TextureAtlasSprite getParticleTexture() + { + return this.texture; + } + + @Override + public ItemOverrideList getOverrides() + { + return ItemOverrideList.NONE; + } +} diff --git a/src/main/java/appeng/client/render/cablebus/P2PTunnelFrequencyModel.java b/src/main/java/appeng/client/render/cablebus/P2PTunnelFrequencyModel.java new file mode 100644 index 000000000..6e6fcb927 --- /dev/null +++ b/src/main/java/appeng/client/render/cablebus/P2PTunnelFrequencyModel.java @@ -0,0 +1,43 @@ + +package appeng.client.render.cablebus; + + +import java.util.Collection; +import java.util.Collections; +import java.util.function.Function; + +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.model.IModel; +import net.minecraftforge.common.model.IModelState; + +import appeng.core.AppEng; + + +public class P2PTunnelFrequencyModel implements IModel +{ + private static final ResourceLocation TEXTURE = new ResourceLocation( AppEng.MOD_ID, "parts/p2p_tunnel_frequency" ); + + @Override + public Collection getTextures() + { + return Collections.singletonList( TEXTURE ); + } + + @Override + public IBakedModel bake( IModelState state, VertexFormat format, Function bakedTextureGetter ) + { + try + { + final TextureAtlasSprite texture = bakedTextureGetter.apply( TEXTURE ); + return new P2PTunnelFrequencyBakedModel( format, texture ); + } + catch( Exception e ) + { + throw new RuntimeException( e ); + } + } + +} diff --git a/src/main/java/appeng/items/parts/ItemPartRendering.java b/src/main/java/appeng/items/parts/ItemPartRendering.java index 9672ca07e..50f31642d 100644 --- a/src/main/java/appeng/items/parts/ItemPartRendering.java +++ b/src/main/java/appeng/items/parts/ItemPartRendering.java @@ -34,6 +34,7 @@ import appeng.api.util.AEColor; import appeng.bootstrap.IItemRendering; import appeng.bootstrap.ItemRenderingCustomizer; import appeng.client.render.StaticItemColor; +import appeng.client.render.cablebus.P2PTunnelFrequencyModel; import appeng.core.AppEng; import appeng.core.features.registries.PartModels; import appeng.parts.automation.PlaneConnections; @@ -128,6 +129,9 @@ public class ItemPartRendering extends ItemRenderingCustomizer } + // base p2p model with frequency + rendering.builtInModel( "models/part/builtin/p2p_tunnel_frequency", new P2PTunnelFrequencyModel() ); + List partResourceLocs = modelNames.stream() .map( name -> new ResourceLocation( AppEng.MOD_ID, name ) ) .collect( Collectors.toList() ); diff --git a/src/main/java/appeng/parts/CableBusContainer.java b/src/main/java/appeng/parts/CableBusContainer.java index 0a1e9507b..645a58db5 100644 --- a/src/main/java/appeng/parts/CableBusContainer.java +++ b/src/main/java/appeng/parts/CableBusContainer.java @@ -1247,6 +1247,8 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I continue; } + renderState.getPartFlags().put( facing, part.getRenderFlag() ); + // This will add the part's bounding boxes to the render state, which is required for facades final AEPartLocation loc = AEPartLocation.fromFacing( facing ); final IPartCollisionHelper bch = new BusCollisionHelper( renderState.getBoundingBoxes(), loc, null, true ); diff --git a/src/main/java/appeng/parts/p2p/P2PModels.java b/src/main/java/appeng/parts/p2p/P2PModels.java index fc5b96a84..6bc8060ce 100644 --- a/src/main/java/appeng/parts/p2p/P2PModels.java +++ b/src/main/java/appeng/parts/p2p/P2PModels.java @@ -38,6 +38,7 @@ class P2PModels public static final ResourceLocation MODEL_STATUS_OFF = new ResourceLocation( AppEng.MOD_ID, "part/p2p/p2p_tunnel_status_off" ); public static final ResourceLocation MODEL_STATUS_ON = new ResourceLocation( AppEng.MOD_ID, "part/p2p/p2p_tunnel_status_on" ); public static final ResourceLocation MODEL_STATUS_HAS_CHANNEL = new ResourceLocation( AppEng.MOD_ID, "part/p2p/p2p_tunnel_status_has_channel" ); + public static final ResourceLocation MODEL_FREQUENCY = new ResourceLocation( AppEng.MOD_ID, "part/builtin/p2p_tunnel_frequency" ); private final IPartModel modelsOff; private final IPartModel modelsOn; @@ -46,9 +47,10 @@ class P2PModels public P2PModels( String frontModelPath ) { ResourceLocation frontModel = new ResourceLocation( AppEng.MOD_ID, frontModelPath ); - this.modelsOff = new PartModel( MODEL_STATUS_OFF, frontModel ); - this.modelsOn = new PartModel( MODEL_STATUS_ON, frontModel ); - this.modelsHasChannel = new PartModel( MODEL_STATUS_HAS_CHANNEL, frontModel ); + + this.modelsOff = new PartModel( MODEL_STATUS_OFF, MODEL_FREQUENCY, frontModel ); + this.modelsOn = new PartModel( MODEL_STATUS_ON, MODEL_FREQUENCY, frontModel ); + this.modelsHasChannel = new PartModel( MODEL_STATUS_HAS_CHANNEL, MODEL_FREQUENCY, frontModel ); } public IPartModel getModel( boolean hasPower, boolean hasChannel ) diff --git a/src/main/java/appeng/parts/p2p/PartP2PTunnel.java b/src/main/java/appeng/parts/p2p/PartP2PTunnel.java index e93484e16..91a9e3679 100644 --- a/src/main/java/appeng/parts/p2p/PartP2PTunnel.java +++ b/src/main/java/appeng/parts/p2p/PartP2PTunnel.java @@ -19,10 +19,13 @@ package appeng.parts.p2p; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Optional; +import io.netty.buffer.ByteBuf; + import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -134,7 +137,7 @@ public abstract class PartP2PTunnel extends PartBasicSt { super.readFromNBT( data ); this.setOutput( data.getBoolean( "output" ) ); - this.setFrequency( data.getShort( "freq" ) ); + this.freq = data.getShort( "freq" ); } @Override @@ -145,6 +148,22 @@ public abstract class PartP2PTunnel extends PartBasicSt data.setShort( "freq", this.getFrequency() ); } + @Override + public boolean readFromStream( ByteBuf data ) throws IOException + { + final boolean c = super.readFromStream( data ); + final short oldf = this.freq; + this.freq = data.readShort(); + return c || oldf != this.freq; + } + + @Override + public void writeToStream( ByteBuf data ) throws IOException + { + super.writeToStream( data ); + data.writeShort( getFrequency() ); + } + @Override public float getCableConnectionLength( AECableType cable ) { @@ -381,7 +400,12 @@ public abstract class PartP2PTunnel extends PartBasicSt public void setFrequency( final short freq ) { + final short oldf = this.freq; this.freq = freq; + if( oldf != this.freq ) + { + this.getHost().markForUpdate(); + } } public boolean isOutput() @@ -393,4 +417,17 @@ public abstract class PartP2PTunnel extends PartBasicSt { this.output = output; } + + @Override + public Long getRenderFlag() + { + long ret = Short.toUnsignedLong( this.getFrequency() ); + + if( this.isActive() && this.isPowered() ) + { + ret |= 0x10000L; + } + + return ret; + } } diff --git a/src/main/resources/assets/appliedenergistics2/models/part/p2p/p2p_tunnel_base.json b/src/main/resources/assets/appliedenergistics2/models/part/p2p/p2p_tunnel_base.json index cbae9e42b..ded4e49a1 100644 --- a/src/main/resources/assets/appliedenergistics2/models/part/p2p/p2p_tunnel_base.json +++ b/src/main/resources/assets/appliedenergistics2/models/part/p2p/p2p_tunnel_base.json @@ -3,32 +3,628 @@ "front": "appliedenergistics2:items/part/p2p_tunnel_front", "sides": "appliedenergistics2:parts/p2p_tunnel_sides", "back": "appliedenergistics2:items/part/p2p_tunnel_back", - "back2": "appliedenergistics2:items/part/p2p_tunnel_back2", - "particle": "appliedenergistics2:items/part/p2p_tunnel_back" + "particle": "appliedenergistics2:items/part/p2p_tunnel_back", + "back2": "appliedenergistics2:items/part/p2p_tunnel_back2" }, "elements": [ { "from": [ - 2, - 2, + 4, + 4, 0 ], "to": [ - 14, - 14, + 12, + 12, 2 ], "faces": { "north": { + "uv": [ + 4, + 4, + 12, + 12 + ], "texture": "#type" } } }, + { + "from": [ + 6, + 5, + 3 + ], + "to": [ + 10, + 11, + 4 + ], + "faces": { + "east": { + "uv": [ + 12, + 5, + 13, + 11 + ], + "texture": "#back2" + }, + "south": { + "uv": [ + 6, + 5, + 10, + 11 + ], + "texture": "#back2" + }, + "west": { + "uv": [ + 3, + 5, + 4, + 11 + ], + "texture": "#back2" + }, + "up": { + "uv": [ + 6, + 3, + 10, + 4 + ], + "texture": "#back2" + }, + "down": { + "uv": [ + 6, + 12, + 10, + 13 + ], + "texture": "#back2" + } + } + }, + { + "from": [ + 5, + 6, + 3 + ], + "to": [ + 6, + 10, + 4 + ], + "faces": { + "east": { + "uv": [ + 12, + 6, + 13, + 10 + ], + "texture": "#back2" + }, + "south": { + "uv": [ + 5, + 6, + 6, + 10 + ], + "texture": "#back2" + }, + "west": { + "uv": [ + 3, + 6, + 4, + 10 + ], + "texture": "#back2" + }, + "up": { + "uv": [ + 5, + 3, + 6, + 4 + ], + "texture": "#back2" + }, + "down": { + "uv": [ + 5, + 12, + 6, + 13 + ], + "texture": "#back2" + } + } + }, + { + "from": [ + 10, + 6, + 3 + ], + "to": [ + 11, + 10, + 4 + ], + "faces": { + "east": { + "uv": [ + 12, + 6, + 13, + 10 + ], + "texture": "#back2" + }, + "south": { + "uv": [ + 10, + 6, + 11, + 10 + ], + "texture": "#back2" + }, + "west": { + "uv": [ + 3, + 6, + 4, + 10 + ], + "texture": "#back2" + }, + "up": { + "uv": [ + 10, + 3, + 11, + 4 + ], + "texture": "#back2" + }, + "down": { + "uv": [ + 10, + 12, + 11, + 13 + ], + "texture": "#back2" + } + } + }, + { + "from": [ + 6, + 4, + 2 + ], + "to": [ + 10, + 6, + 3 + ], + "faces": { + "east": { + "uv": [ + 13, + 10, + 14, + 12 + ], + "texture": "#sides" + }, + "south": { + "uv": [ + 6, + 10, + 10, + 12 + ], + "texture": "#back" + }, + "west": { + "uv": [ + 2, + 10, + 3, + 12 + ], + "texture": "#sides" + }, + "up": { + "uv": [ + 6, + 2, + 10, + 3 + ], + "texture": "#sides" + }, + "down": { + "uv": [ + 6, + 13, + 10, + 14 + ], + "texture": "#sides" + } + } + }, + { + "from": [ + 4, + 6, + 2 + ], + "to": [ + 12, + 10, + 3 + ], + "faces": { + "east": { + "uv": [ + 13, + 6, + 14, + 10 + ], + "texture": "#sides" + }, + "south": { + "uv": [ + 4, + 6, + 12, + 10 + ], + "texture": "#back" + }, + "west": { + "uv": [ + 2, + 6, + 3, + 10 + ], + "texture": "#sides" + }, + "up": { + "uv": [ + 4, + 2, + 12, + 3 + ], + "texture": "#sides" + }, + "down": { + "uv": [ + 4, + 13, + 12, + 14 + ], + "texture": "#sides" + } + } + }, + { + "from": [ + 6, + 10, + 2 + ], + "to": [ + 10, + 12, + 3 + ], + "faces": { + "east": { + "uv": [ + 13, + 4, + 14, + 6 + ], + "texture": "#sides" + }, + "south": { + "uv": [ + 6, + 4, + 10, + 6 + ], + "texture": "#back" + }, + "west": { + "uv": [ + 2, + 4, + 3, + 6 + ], + "texture": "#sides" + }, + "up": { + "uv": [ + 6, + 2, + 10, + 3 + ], + "texture": "#sides" + }, + "down": { + "uv": [ + 6, + 13, + 10, + 14 + ], + "texture": "#sides" + } + } + }, + { + "from": [ + 3, + 12, + 2 + ], + "to": [ + 13, + 13, + 3 + ], + "faces": { + "east": { + "uv": [ + 13, + 3, + 14, + 4 + ], + "texture": "#sides" + }, + "south": { + "uv": [ + 3, + 3, + 13, + 4 + ], + "texture": "#back" + }, + "west": { + "uv": [ + 2, + 3, + 3, + 4 + ], + "texture": "#sides" + }, + "up": { + "uv": [ + 3, + 2, + 13, + 3 + ], + "texture": "#sides" + }, + "down": { + "uv": [ + 3, + 13, + 13, + 14 + ], + "texture": "#sides" + } + } + }, + { + "from": [ + 12, + 4, + 2 + ], + "to": [ + 13, + 12, + 3 + ], + "faces": { + "east": { + "uv": [ + 13, + 4, + 14, + 12 + ], + "texture": "#sides" + }, + "south": { + "uv": [ + 12, + 4, + 13, + 12 + ], + "texture": "#back" + }, + "west": { + "uv": [ + 2, + 4, + 3, + 12 + ], + "texture": "#sides" + }, + "up": { + "uv": [ + 12, + 2, + 13, + 3 + ], + "texture": "#sides" + }, + "down": { + "uv": [ + 12, + 13, + 13, + 14 + ], + "texture": "#sides" + } + } + }, + { + "from": [ + 3, + 4, + 2 + ], + "to": [ + 4, + 12, + 3 + ], + "faces": { + "east": { + "uv": [ + 13, + 4, + 14, + 12 + ], + "texture": "#sides" + }, + "south": { + "uv": [ + 3, + 4, + 4, + 12 + ], + "texture": "#back" + }, + "west": { + "uv": [ + 2, + 4, + 3, + 12 + ], + "texture": "#sides" + }, + "up": { + "uv": [ + 3, + 2, + 4, + 3 + ], + "texture": "#sides" + }, + "down": { + "uv": [ + 3, + 13, + 4, + 14 + ], + "texture": "#sides" + } + } + }, + { + "from": [ + 3, + 3, + 2 + ], + "to": [ + 13, + 4, + 3 + ], + "faces": { + "east": { + "uv": [ + 13, + 12, + 14, + 13 + ], + "texture": "#sides" + }, + "south": { + "uv": [ + 3, + 12, + 13, + 13 + ], + "texture": "#back" + }, + "west": { + "uv": [ + 2, + 12, + 3, + 13 + ], + "texture": "#sides" + }, + "up": { + "uv": [ + 3, + 2, + 13, + 3 + ], + "texture": "#sides" + }, + "down": { + "uv": [ + 3, + 13, + 13, + 14 + ], + "texture": "#sides" + } + } + }, { "from": [ 2, 2, - 0 + 1 ], "to": [ 14, @@ -37,111 +633,332 @@ ], "faces": { "north": { + "uv": [ + 2, + 2, + 14, + 14 + ], "texture": "#front" }, + "east": { + "uv": [ + 14, + 2, + 15, + 14 + ], + "texture": "#sides" + }, "south": { + "uv": [ + 2, + 2, + 14, + 14 + ], "texture": "#back" }, "west": { - "texture": "#sides" - }, - "east": { + "uv": [ + 1, + 2, + 2, + 14 + ], "texture": "#sides" }, "up": { + "uv": [ + 2, + 1, + 14, + 2 + ], "texture": "#sides" }, "down": { + "uv": [ + 2, + 14, + 14, + 15 + ], "texture": "#sides" } } }, { "from": [ - 3, - 3, - 2 + 2, + 12, + 0 ], "to": [ - 13, - 13, - 3 + 14, + 14, + 1 ], "faces": { + "north": { + "uv": [ + 2, + 2, + 14, + 4 + ], + "texture": "#front" + }, + "east": { + "uv": [ + 15, + 2, + 16, + 4 + ], + "texture": "#sides" + }, "south": { + "uv": [ + 2, + 2, + 14, + 4 + ], "texture": "#back" }, "west": { - "texture": "#sides" - }, - "east": { + "uv": [ + 0, + 2, + 1, + 4 + ], "texture": "#sides" }, "up": { + "uv": [ + 2, + 0, + 14, + 1 + ], "texture": "#sides" }, "down": { + "uv": [ + 2, + 15, + 14, + 16 + ], "texture": "#sides" } } }, { "from": [ - 6, - 5, - 3 + 2, + 2, + 0 ], "to": [ - 10, - 11, - 4 + 14, + 4, + 1 ], "faces": { - "south": { - "texture": "#back2" - }, - "west": { - "texture": "#back2" + "north": { + "uv": [ + 2, + 12, + 14, + 14 + ], + "texture": "#front" }, "east": { - "texture": "#back2" + "uv": [ + 15, + 12, + 16, + 14 + ], + "texture": "#sides" + }, + "south": { + "uv": [ + 2, + 12, + 14, + 14 + ], + "texture": "#back" + }, + "west": { + "uv": [ + 0, + 12, + 1, + 14 + ], + "texture": "#sides" }, "up": { - "texture": "#back2" + "uv": [ + 2, + 0, + 14, + 1 + ], + "texture": "#sides" }, "down": { - "texture": "#back2" + "uv": [ + 2, + 15, + 14, + 16 + ], + "texture": "#sides" } } }, { "from": [ - 5, - 6, - 3 + 12, + 4, + 0 ], "to": [ - 11, - 10, - 4 + 14, + 12, + 1 ], "faces": { - "south": { - "texture": "#back2" - }, - "west": { - "texture": "#back2" + "north": { + "uv": [ + 2, + 4, + 4, + 12 + ], + "texture": "#front" }, "east": { - "texture": "#back2" + "uv": [ + 15, + 4, + 16, + 12 + ], + "texture": "#sides" + }, + "south": { + "uv": [ + 12, + 4, + 14, + 12 + ], + "texture": "#back" + }, + "west": { + "uv": [ + 0, + 4, + 1, + 12 + ], + "texture": "#sides" }, "up": { - "texture": "#back2" + "uv": [ + 12, + 0, + 14, + 1 + ], + "texture": "#sides" }, "down": { - "texture": "#back2" + "uv": [ + 12, + 15, + 14, + 16 + ], + "texture": "#sides" + } + } + }, + { + "from": [ + 2, + 4, + 0 + ], + "to": [ + 4, + 12, + 1 + ], + "faces": { + "north": { + "uv": [ + 12, + 4, + 14, + 12 + ], + "texture": "#front" + }, + "east": { + "uv": [ + 15, + 4, + 16, + 12 + ], + "texture": "#sides" + }, + "south": { + "uv": [ + 2, + 4, + 4, + 12 + ], + "texture": "#back" + }, + "west": { + "uv": [ + 0, + 4, + 1, + 12 + ], + "texture": "#sides" + }, + "up": { + "uv": [ + 2, + 0, + 4, + 1 + ], + "texture": "#sides" + }, + "down": { + "uv": [ + 2, + 15, + 4, + 16 + ], + "texture": "#sides" } } } ] -} +} \ No newline at end of file diff --git a/src/main/resources/assets/appliedenergistics2/textures/parts/p2p_tunnel_frequency.png b/src/main/resources/assets/appliedenergistics2/textures/parts/p2p_tunnel_frequency.png new file mode 100644 index 000000000..59ad3036f Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/parts/p2p_tunnel_frequency.png differ