diff --git a/src/main/java/appeng/bootstrap/BlockRendering.java b/src/main/java/appeng/bootstrap/BlockRendering.java index 0cefd0dde..b0f0cad51 100644 --- a/src/main/java/appeng/bootstrap/BlockRendering.java +++ b/src/main/java/appeng/bootstrap/BlockRendering.java @@ -1,6 +1,8 @@ package appeng.bootstrap; +import java.util.HashMap; +import java.util.Map; import java.util.function.BiFunction; import net.minecraft.block.Block; @@ -9,6 +11,7 @@ import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.block.statemap.IStateMapper; import net.minecraft.client.renderer.color.IBlockColor; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraftforge.client.model.IModel; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -34,6 +37,9 @@ class BlockRendering implements IBlockRendering @SideOnly( Side.CLIENT ) private IStateMapper stateMapper; + @SideOnly( Side.CLIENT ) + private Map builtInModels = new HashMap<>(); + @SideOnly( Side.CLIENT ) public IBlockRendering modelCustomizer( BiFunction customizer ) { @@ -57,6 +63,13 @@ class BlockRendering implements IBlockRendering return this; } + @Override + public IBlockRendering builtInModel( String name, IModel model ) + { + this.builtInModels.put( name, model ); + return this; + } + @SideOnly( Side.CLIENT ) @Override public IBlockRendering stateMapper( IStateMapper mapper ) @@ -65,7 +78,7 @@ class BlockRendering implements IBlockRendering return this; } - void apply( FeatureFactory registry, Block block, Class tileEntityClass ) + void apply( FeatureFactory factory, Block block, Class tileEntityClass ) { if( tesr != null ) { @@ -73,27 +86,29 @@ class BlockRendering implements IBlockRendering { throw new IllegalStateException( "Tried to register a TESR for " + block + " even though no tile entity has been specified." ); } - registry.addBootstrapComponent( new TesrComponent( tileEntityClass, tesr ) ); + factory.addBootstrapComponent( new TesrComponent( tileEntityClass, tesr ) ); } if( modelCustomizer != null ) { - registry.modelOverrideComponent.addOverride( block.getRegistryName().getResourcePath(), modelCustomizer ); + factory.modelOverrideComponent.addOverride( block.getRegistryName().getResourcePath(), modelCustomizer ); } else if ( block instanceof AEBaseTileBlock ) { // This is a default rotating model if the base-block uses an AE tile entity which exposes UP/FRONT as extended props - registry.modelOverrideComponent.addOverride( block.getRegistryName().getResourcePath(), ( l, m ) -> new CachingRotatingBakedModel( m ) ); + factory.modelOverrideComponent.addOverride( block.getRegistryName().getResourcePath(), ( l, m ) -> new CachingRotatingBakedModel( m ) ); } + builtInModels.forEach( factory::addBuiltInModel ); + if( blockColor != null ) { - registry.addBootstrapComponent( new BlockColorComponent( block, blockColor ) ); + factory.addBootstrapComponent( new BlockColorComponent( block, blockColor ) ); } if( stateMapper != null ) { - registry.addBootstrapComponent( new StateMapperComponent( block, stateMapper ) ); + factory.addBootstrapComponent( new StateMapperComponent( block, stateMapper ) ); } } } diff --git a/src/main/java/appeng/bootstrap/FeatureFactory.java b/src/main/java/appeng/bootstrap/FeatureFactory.java index a150a0241..07b4862aa 100644 --- a/src/main/java/appeng/bootstrap/FeatureFactory.java +++ b/src/main/java/appeng/bootstrap/FeatureFactory.java @@ -7,12 +7,14 @@ import java.util.function.Supplier; import net.minecraft.block.Block; import net.minecraft.item.Item; +import net.minecraftforge.client.model.IModel; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import appeng.api.definitions.IItemDefinition; import appeng.api.util.AEColor; import appeng.api.util.AEColoredItemDefinition; +import appeng.bootstrap.components.BuiltInModelComponent; import appeng.bootstrap.components.InitComponent; import appeng.bootstrap.components.ModelOverrideComponent; import appeng.bootstrap.components.PostInitComponent; @@ -34,6 +36,9 @@ public class FeatureFactory @SideOnly( Side.CLIENT ) ModelOverrideComponent modelOverrideComponent; + @SideOnly( Side.CLIENT ) + private BuiltInModelComponent builtInModelComponent; + public FeatureFactory() { this.defaultFeatures = new AEFeature[] { AEFeature.Core }; @@ -42,7 +47,10 @@ public class FeatureFactory if( Platform.isClient() ) { modelOverrideComponent = new ModelOverrideComponent(); - this.bootstrapComponents.add( modelOverrideComponent ); + bootstrapComponents.add( modelOverrideComponent ); + + builtInModelComponent = new BuiltInModelComponent(); + bootstrapComponents.add( builtInModelComponent ); } } @@ -53,6 +61,7 @@ public class FeatureFactory if( Platform.isClient() ) { this.modelOverrideComponent = parent.modelOverrideComponent; + this.builtInModelComponent = parent.builtInModelComponent; } } @@ -108,9 +117,14 @@ public class FeatureFactory this.bootstrapComponents.add( component ); } + @SideOnly( Side.CLIENT ) + void addBuiltInModel( String path, IModel model ) + { + builtInModelComponent.addModel( path, model ); + } + public List getBootstrapComponents() { return bootstrapComponents; } - } diff --git a/src/main/java/appeng/bootstrap/IBlockRendering.java b/src/main/java/appeng/bootstrap/IBlockRendering.java index 6aaeed12f..d1240b7c5 100644 --- a/src/main/java/appeng/bootstrap/IBlockRendering.java +++ b/src/main/java/appeng/bootstrap/IBlockRendering.java @@ -7,8 +7,8 @@ import net.minecraft.client.renderer.block.model.IBakedModel; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.block.statemap.IStateMapper; import net.minecraft.client.renderer.color.IBlockColor; -import net.minecraft.client.renderer.color.IItemColor; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraftforge.client.model.IModel; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -31,4 +31,10 @@ public interface IBlockRendering @SideOnly( Side.CLIENT ) IBlockRendering tesr( TileEntitySpecialRenderer tesr ); + /** + * Registers a built-in model under the given resource path. + */ + @SideOnly( Side.CLIENT ) + IBlockRendering builtInModel( String name, IModel model ); + } diff --git a/src/main/java/appeng/bootstrap/IItemRendering.java b/src/main/java/appeng/bootstrap/IItemRendering.java index fb4dd8ee3..42830d380 100644 --- a/src/main/java/appeng/bootstrap/IItemRendering.java +++ b/src/main/java/appeng/bootstrap/IItemRendering.java @@ -8,6 +8,7 @@ import net.minecraft.client.renderer.ItemMeshDefinition; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.color.IItemColor; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.model.IModel; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -66,4 +67,11 @@ public interface IItemRendering */ @SideOnly( Side.CLIENT ) IItemRendering color( IItemColor itemColor ); + + /** + * Registers a built-in model under the given resource path. + */ + @SideOnly( Side.CLIENT ) + IItemRendering builtInModel( String name, IModel model ); + } diff --git a/src/main/java/appeng/bootstrap/ItemRendering.java b/src/main/java/appeng/bootstrap/ItemRendering.java index 9f8269100..2e054bd15 100644 --- a/src/main/java/appeng/bootstrap/ItemRendering.java +++ b/src/main/java/appeng/bootstrap/ItemRendering.java @@ -18,6 +18,7 @@ import net.minecraft.client.renderer.color.IItemColor; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.model.IModel; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -42,6 +43,9 @@ class ItemRendering implements IItemRendering @SideOnly( Side.CLIENT ) private Set variants = new HashSet<>(); + @SideOnly( Side.CLIENT ) + private Map builtInModels = new HashMap<>(); + @Override @SideOnly( Side.CLIENT ) public IItemRendering meshDefinition( ItemMeshDefinition meshDefinition ) @@ -73,6 +77,13 @@ class ItemRendering implements IItemRendering return this; } + @Override + public IItemRendering builtInModel( String name, IModel model ) + { + this.builtInModels.put( name, model ); + return this; + } + void apply( FeatureFactory factory, Item item ) { if( this.itemMeshDefinition != null ) @@ -110,6 +121,8 @@ class ItemRendering implements IItemRendering factory.addBootstrapComponent( new ItemModelComponent( item, ImmutableMap.of( 0, model ) ) ); } + builtInModels.forEach( factory::addBuiltInModel ); + if( !resources.isEmpty() ) { factory.addBootstrapComponent( new ItemVariantsComponent( item, resources ) ); diff --git a/src/main/java/appeng/bootstrap/components/BuiltInModelComponent.java b/src/main/java/appeng/bootstrap/components/BuiltInModelComponent.java new file mode 100644 index 000000000..f211353b9 --- /dev/null +++ b/src/main/java/appeng/bootstrap/components/BuiltInModelComponent.java @@ -0,0 +1,39 @@ +package appeng.bootstrap.components; + + +import java.util.HashMap; +import java.util.Map; + +import com.google.common.base.Preconditions; + +import net.minecraftforge.client.model.IModel; +import net.minecraftforge.client.model.ModelLoaderRegistry; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import appeng.client.render.model.BuiltInModelLoader; + + +@SideOnly( Side.CLIENT ) +public class BuiltInModelComponent implements PreInitComponent +{ + + private final Map builtInModels = new HashMap<>(); + + private boolean hasInitialized = false; + + public void addModel( String path, IModel model ) + { + Preconditions.checkState( !hasInitialized ); + builtInModels.put( path, model ); + } + + @Override + public void preInitialize( Side side ) + { + hasInitialized = true; + + BuiltInModelLoader loader = new BuiltInModelLoader( builtInModels ); + ModelLoaderRegistry.registerLoader( loader ); + } +} diff --git a/src/main/java/appeng/client/render/model/BuiltInModelLoader.java b/src/main/java/appeng/client/render/model/BuiltInModelLoader.java new file mode 100644 index 000000000..e0ddd8e23 --- /dev/null +++ b/src/main/java/appeng/client/render/model/BuiltInModelLoader.java @@ -0,0 +1,58 @@ +package appeng.client.render.model; + + +import java.util.Map; + +import com.google.common.collect.ImmutableMap; + +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.model.ICustomModelLoader; +import net.minecraftforge.client.model.IModel; + +import appeng.core.AppEng; + + +/** + * Manages built-in models. + */ +public class BuiltInModelLoader implements ICustomModelLoader +{ + + private final Map builtInModels; + + public BuiltInModelLoader( Map builtInModels ) + { + this.builtInModels = ImmutableMap.copyOf( builtInModels ); + } + + @Override + public boolean accepts( ResourceLocation modelLocation ) + { + if( !modelLocation.getResourceDomain().equals( AppEng.MOD_ID ) ) + { + return false; + } + + return builtInModels.containsKey( modelLocation.getResourcePath() ); + } + + @Override + public IModel loadModel( ResourceLocation modelLocation ) throws Exception + { + return builtInModels.get( modelLocation.getResourcePath() ); + } + + @Override + public void onResourceManagerReload( IResourceManager resourceManager ) + { + for( IModel model : builtInModels.values() ) + { + if( model instanceof IResourceManagerReloadListener ) + { + ( (IResourceManagerReloadListener) model ).onResourceManagerReload( resourceManager ); + } + } + } +} diff --git a/src/main/java/appeng/client/render/model/GlassBakedModel.java b/src/main/java/appeng/client/render/model/GlassBakedModel.java new file mode 100644 index 000000000..a8bdb24ec --- /dev/null +++ b/src/main/java/appeng/client/render/model/GlassBakedModel.java @@ -0,0 +1,314 @@ +/* + * 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.client.render.model; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; +import java.util.stream.IntStream; + +import javax.annotation.Nullable; + +import com.google.common.base.Function; +import com.google.common.base.Strings; + +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.ItemCameraTransforms; +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 net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; +import net.minecraftforge.common.property.IExtendedBlockState; + +import appeng.decorative.solid.BlockQuartzGlass; +import appeng.decorative.solid.GlassState; + + +class GlassBakedModel implements IBakedModel +{ + + private static final byte[][][] OFFSETS = generateOffsets(); + + // Alternating textures based on position + static final ResourceLocation TEXTURE_A = new ResourceLocation( "appliedenergistics2:blocks/glass/quartz_glass_a" ); + static final ResourceLocation TEXTURE_B = new ResourceLocation( "appliedenergistics2:blocks/glass/quartz_glass_b" ); + static final ResourceLocation TEXTURE_C = new ResourceLocation( "appliedenergistics2:blocks/glass/quartz_glass_c" ); + static final ResourceLocation TEXTURE_D = new ResourceLocation( "appliedenergistics2:blocks/glass/quartz_glass_d" ); + + // Frame texture + static final ResourceLocation[] TEXTURES_FRAME = generateTexturesFrame(); + + // Generates the required textures for the frame + private static ResourceLocation[] generateTexturesFrame() + { + return IntStream.range( 1, 16 ) + .mapToObj( Integer::toBinaryString ) + .map( s -> Strings.padStart( s, 4, '0' ) ) + .map( s -> new ResourceLocation( "appliedenergistics2:blocks/glass/quartz_glass_frame" + s ) ) + .toArray( ResourceLocation[]::new ); + } + + private final TextureAtlasSprite[] glassTextures; + + private final TextureAtlasSprite[] frameTextures; + + private final VertexFormat vertexFormat; + + public GlassBakedModel( VertexFormat format, Function bakedTextureGetter ) + { + this.glassTextures = new TextureAtlasSprite[] { + bakedTextureGetter.apply( TEXTURE_A ), + bakedTextureGetter.apply( TEXTURE_B ), + bakedTextureGetter.apply( TEXTURE_C ), + bakedTextureGetter.apply( TEXTURE_D ) + }; + + this.vertexFormat = format; + + // The first frame texture would be empty, so we simply leave it set to null here + this.frameTextures = new TextureAtlasSprite[16]; + for( int i = 0; i < TEXTURES_FRAME.length; i++ ) + { + this.frameTextures[1 + i] = bakedTextureGetter.apply( TEXTURES_FRAME[i] ); + } + } + + @Override + public List getQuads( @Nullable IBlockState state, @Nullable EnumFacing side, long rand ) + { + + if( !( state instanceof IExtendedBlockState ) || side == null ) + { + return Collections.emptyList(); + } + + IExtendedBlockState extState = (IExtendedBlockState) state; + + GlassState glassState = extState.getValue( BlockQuartzGlass.GLASS_STATE ); + + final int cx = Math.abs( glassState.getX() % 10 ); + final int cy = Math.abs( glassState.getY() % 10 ); + final int cz = Math.abs( glassState.getZ() % 10 ); + + int u = OFFSETS[cx][cy][cz] % 4; + int v = OFFSETS[9 - cx][9 - cy][9 - cz] % 4; + + int texIdx = Math.abs( ( OFFSETS[cx][cy][cz] + ( glassState.getX() + glassState.getY() + glassState.getZ() ) ) % 4 ); + + if( texIdx < 2 ) + { + u /= 2; + v /= 2; + } + + TextureAtlasSprite glassTexture = glassTextures[texIdx]; + + // Render the glass side + List quads = new ArrayList<>( 5 ); // At most 5 + + List corners = RenderHelper.getFaceCorners( side ); + quads.add( createQuad( side, corners, glassTexture, u, v ) ); + + /* + This needs some explanation: + The bit-field contains 4-bits, one for each direction that a frame may be drawn. + Converted to a number, the bit-field is then used as an index into the list of + frame textures, which have been created in such a way that their filenames + indicate, in which directions they contain borders. + i.e. bitmask = 0101 means a border should be drawn up and down (in terms of u,v space). + Converted to a number, this bitmask is 5. So the texture at index 5 is used. + That texture had "0101" in its filename to indicate this. + */ + int edgeBitmask = makeBitmask( glassState, side ); + TextureAtlasSprite sideSprite = frameTextures[edgeBitmask]; + if( sideSprite != null ) + { + quads.add( createQuad( side, corners, sideSprite, 0, 0 ) ); + } + + return quads; + } + + /** + * Creates the bitmask that indicates, in which directions (in terms of u,v space) a border should be drawn. + */ + private static int makeBitmask( GlassState state, EnumFacing side ) + { + switch( side ) + { + case DOWN: + return makeBitmask( state, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.NORTH, EnumFacing.WEST ); + case UP: + return makeBitmask( state, EnumFacing.SOUTH, EnumFacing.WEST, EnumFacing.NORTH, EnumFacing.EAST ); + case NORTH: + return makeBitmask( state, EnumFacing.UP, EnumFacing.WEST, EnumFacing.DOWN, EnumFacing.EAST ); + case SOUTH: + return makeBitmask( state, EnumFacing.UP, EnumFacing.EAST, EnumFacing.DOWN, EnumFacing.WEST ); + case WEST: + return makeBitmask( state, EnumFacing.UP, EnumFacing.SOUTH, EnumFacing.DOWN, EnumFacing.NORTH ); + case EAST: + return makeBitmask( state, EnumFacing.UP, EnumFacing.NORTH, EnumFacing.DOWN, EnumFacing.SOUTH ); + default: + throw new IllegalArgumentException( "Unsupported side!" ); + } + } + + private static int makeBitmask( GlassState state, EnumFacing up, EnumFacing right, EnumFacing down, EnumFacing left ) + { + + int bitmask = 0; + + if( !state.isFlushWith( up ) ) + { + bitmask |= 1; + } + if( !state.isFlushWith( right ) ) + { + bitmask |= 2; + } + if( !state.isFlushWith( down ) ) + { + bitmask |= 4; + } + if( !state.isFlushWith( left ) ) + { + bitmask |= 8; + } + return bitmask; + } + + private BakedQuad createQuad( EnumFacing side, List corners, TextureAtlasSprite sprite, float uOffset, float vOffset ) + { + return createQuad( side, corners.get( 0 ), corners.get( 1 ), corners.get( 2 ), corners.get( 3 ), sprite, uOffset, vOffset ); + } + + private BakedQuad createQuad( EnumFacing side, Vec3d c1, Vec3d c2, Vec3d c3, Vec3d c4, TextureAtlasSprite sprite, float uOffset, float vOffset ) + { + Vec3d normal = new Vec3d( side.getDirectionVec() ); + + // Apply the u,v shift. + // This mirrors the logic from OffsetIcon from 1.7 + float u1 = MathHelper.clamp_float( 0 - uOffset, 0, 16 ); + float u2 = MathHelper.clamp_float( 16 - uOffset, 0, 16 ); + float v1 = MathHelper.clamp_float( 0 - vOffset, 0, 16 ); + float v2 = MathHelper.clamp_float( 16 - vOffset, 0, 16 ); + + UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder( vertexFormat ); + builder.setTexture( sprite ); + putVertex( builder, normal, c1.xCoord, c1.yCoord, c1.zCoord, sprite, u1, v1 ); + putVertex( builder, normal, c2.xCoord, c2.yCoord, c2.zCoord, sprite, u1, v2 ); + putVertex( builder, normal, c3.xCoord, c3.yCoord, c3.zCoord, sprite, u2, v2 ); + putVertex( builder, normal, c4.xCoord, c4.yCoord, c4.zCoord, sprite, u2, v1 ); + return builder.build(); + } + + /* + This method is as complicated as it is, because the order in which we push data into the vertexbuffer actually has to be precisely the order + in which the vertex elements had been declared in the vertex format. + */ + private void putVertex( UnpackedBakedQuad.Builder builder, Vec3d normal, double x, double y, double z, TextureAtlasSprite sprite, float u, float v ) + { + for( int e = 0; e < vertexFormat.getElementCount(); e++ ) + { + switch( vertexFormat.getElement( e ).getUsage() ) + { + case POSITION: + builder.put( e, (float) x, (float) y, (float) z, 1.0f ); + break; + case COLOR: + builder.put( e, 1.0f, 1.0f, 1.0f, 1.0f ); + break; + case UV: + if( vertexFormat.getElement( e ).getIndex() == 0 ) + { + u = sprite.getInterpolatedU( u ); + v = sprite.getInterpolatedV( v ); + builder.put( e, u, v, 0f, 1f ); + break; + } + case NORMAL: + builder.put( e, (float) normal.xCoord, (float) normal.yCoord, (float) normal.zCoord, 0f ); + break; + default: + builder.put( e ); + break; + } + } + } + + @Override + public ItemOverrideList getOverrides() + { + return ItemOverrideList.NONE; + } + + @Override + public boolean isAmbientOcclusion() + { + return false; + } + + @Override + public boolean isGui3d() + { + return false; + } + + @Override + public boolean isBuiltInRenderer() + { + return false; + } + + @Override + public TextureAtlasSprite getParticleTexture() + { + return frameTextures[frameTextures.length - 1]; + } + + @Override + public ItemCameraTransforms getItemCameraTransforms() + { + return ItemCameraTransforms.DEFAULT; + } + + private static byte[][][] generateOffsets() + { + final Random r = new Random( 924 ); + final byte[][][] offset = new byte[10][10][10]; + + for( int x = 0; x < 10; x++ ) + { + for( int y = 0; y < 10; y++ ) + { + r.nextBytes( offset[x][y] ); + } + } + + return offset; + } +} diff --git a/src/main/java/appeng/client/render/model/GlassModel.java b/src/main/java/appeng/client/render/model/GlassModel.java new file mode 100644 index 000000000..51061a13d --- /dev/null +++ b/src/main/java/appeng/client/render/model/GlassModel.java @@ -0,0 +1,70 @@ +/* + * 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.client.render.model; + + +import java.util.Collection; +import java.util.Collections; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; + +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 net.minecraftforge.common.model.TRSRTransformation; + + +/** + * Model class for the connected texture glass model. + */ +public class GlassModel implements IModel +{ + + @Override + public Collection getDependencies() + { + return Collections.emptySet(); + } + + @Override + public Collection getTextures() + { + return ImmutableSet.builder() + .add( GlassBakedModel.TEXTURE_A, GlassBakedModel.TEXTURE_B, GlassBakedModel.TEXTURE_C, GlassBakedModel.TEXTURE_D ) + .add( GlassBakedModel.TEXTURES_FRAME ) + .build(); + } + + @Override + public IBakedModel bake( IModelState state, VertexFormat format, Function bakedTextureGetter ) + { + return new GlassBakedModel( format, bakedTextureGetter ); + } + + @Override + public IModelState getDefaultState() + { + return TRSRTransformation.identity(); + } + +} diff --git a/src/main/java/appeng/client/render/model/RenderHelper.java b/src/main/java/appeng/client/render/model/RenderHelper.java new file mode 100644 index 000000000..694708b77 --- /dev/null +++ b/src/main/java/appeng/client/render/model/RenderHelper.java @@ -0,0 +1,107 @@ +/* + * 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.client.render.model; + + +import java.util.EnumMap; +import java.util.List; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.Vec3d; + + +final class RenderHelper +{ + + private static EnumMap> cornersForFacing = generateCornersForFacings(); + + private RenderHelper() { + + } + + static List getFaceCorners( EnumFacing side ) + { + return cornersForFacing.get( side ); + } + + private static EnumMap> generateCornersForFacings() + { + EnumMap> result = new EnumMap<>( EnumFacing.class ); + + for( EnumFacing facing : EnumFacing.values() ) + { + List corners; + + float offset = ( facing.getAxisDirection() == EnumFacing.AxisDirection.NEGATIVE ) ? 0 : 1; + + switch( facing.getAxis() ) + { + default: + case X: + corners = Lists.newArrayList( + new Vec3d( offset, 1, 1 ), + new Vec3d( offset, 0, 1 ), + new Vec3d( offset, 0, 0 ), + new Vec3d( offset, 1, 0 ) + ); + break; + case Y: + corners = Lists.newArrayList( + new Vec3d( 1, offset, 1 ), + new Vec3d( 1, offset, 0 ), + new Vec3d( 0, offset, 0 ), + new Vec3d( 0, offset, 1 ) + ); + break; + case Z: + corners = Lists.newArrayList( + new Vec3d( 0, 1, offset ), + new Vec3d( 0, 0, offset ), + new Vec3d( 1, 0, offset ), + new Vec3d( 1, 1, offset ) + ); + break; + } + + if (facing.getAxisDirection() == EnumFacing.AxisDirection.NEGATIVE) { + corners = Lists.reverse( corners ); + } + + result.put( facing, ImmutableList.copyOf( corners ) ); + } + + return result; + } + + private static Vec3d adjust( Vec3d vec, EnumFacing.Axis axis, double delta ) + { + switch( axis ) + { + default: + case X: + return new Vec3d( vec.xCoord + delta, vec.yCoord, vec.zCoord ); + case Y: + return new Vec3d( vec.xCoord, vec.yCoord + delta, vec.zCoord ); + case Z: + return new Vec3d( vec.xCoord, vec.yCoord, vec.zCoord + delta ); + } + } +} diff --git a/src/main/java/appeng/core/api/definitions/ApiBlocks.java b/src/main/java/appeng/core/api/definitions/ApiBlocks.java index 60cfef523..403d9e2dc 100644 --- a/src/main/java/appeng/core/api/definitions/ApiBlocks.java +++ b/src/main/java/appeng/core/api/definitions/ApiBlocks.java @@ -46,8 +46,8 @@ import appeng.block.misc.BlockInscriber; import appeng.block.misc.BlockInterface; import appeng.block.misc.BlockLightDetector; import appeng.block.misc.BlockPaint; -import appeng.block.misc.BlockQuartzGrowthAccelerator; import appeng.block.misc.BlockQuartzFixture; +import appeng.block.misc.BlockQuartzGrowthAccelerator; import appeng.block.misc.BlockSecurityStation; import appeng.block.misc.BlockSkyCompass; import appeng.block.misc.BlockTinyTNT; @@ -77,6 +77,7 @@ import appeng.bootstrap.BlockRenderingCustomizer; import appeng.bootstrap.FeatureFactory; import appeng.bootstrap.IBlockRendering; import appeng.bootstrap.IItemRendering; +import appeng.client.render.model.GlassModel; import appeng.core.AppEng; import appeng.core.features.AEFeature; import appeng.debug.BlockChunkloader; @@ -201,6 +202,15 @@ public final class ApiBlocks implements IBlocks this.chiseledQuartzBlock = deco.block( "chiseled_quartz_block", BlockChiseledQuartz::new ).build(); this.quartzGlass = deco.block( "quartz_glass", BlockQuartzGlass::new ) .useCustomItemModel() + .rendering( new BlockRenderingCustomizer() + { + @Override + @SideOnly( Side.CLIENT ) + public void customize( IBlockRendering rendering, IItemRendering itemRendering ) + { + rendering.builtInModel( "models/block/builtin/quartz_glass", new GlassModel() ); + } + } ) .build(); this.quartzVibrantGlass = deco.block( "quartz_vibrant_glass", BlockQuartzLamp::new ) .addFeatures( AEFeature.DecorativeLights ) diff --git a/src/main/java/appeng/decorative/solid/BlockQuartzGlass.java b/src/main/java/appeng/decorative/solid/BlockQuartzGlass.java index 7e0e07473..abaf837a7 100644 --- a/src/main/java/appeng/decorative/solid/BlockQuartzGlass.java +++ b/src/main/java/appeng/decorative/solid/BlockQuartzGlass.java @@ -19,27 +19,29 @@ package appeng.decorative.solid; +import java.util.EnumSet; + import net.minecraft.block.material.Material; import net.minecraft.block.properties.IProperty; -import net.minecraft.block.properties.PropertyBool; +import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.property.ExtendedBlockState; +import net.minecraftforge.common.property.IExtendedBlockState; +import net.minecraftforge.common.property.IUnlistedProperty; import appeng.block.AEBaseBlock; +import appeng.helpers.AEGlassMaterial; public class BlockQuartzGlass extends AEBaseBlock { - public static final PropertyBool[] props = { PropertyBool.create( "down" ), PropertyBool.create( "up" ), PropertyBool.create( "north" ), PropertyBool.create( "south" ), PropertyBool.create( "west" ), PropertyBool.create( "east" ) }; - - private static boolean isGlassBlock( IBlockAccess world, BlockPos pos, EnumFacing facing ) - { - return world.getBlockState( pos.offset( facing ) ).getBlock() instanceof BlockQuartzGlass; - } + // This unlisted property is used to determine the actual block that should be rendered + public static final UnlistedGlassStateProperty GLASS_STATE = new UnlistedGlassStateProperty(); public BlockQuartzGlass() { @@ -49,25 +51,37 @@ public class BlockQuartzGlass extends AEBaseBlock } @Override - protected IProperty[] getAEStates() + protected BlockStateContainer createBlockState() { - return props; + IProperty[] listedProperties = new IProperty[0]; + IUnlistedProperty[] unlistedProperties = new IUnlistedProperty[] { GLASS_STATE }; + return new ExtendedBlockState( this, listedProperties, unlistedProperties ); } @Override - public int getMetaFromState( IBlockState state ) + public IBlockState getExtendedState( IBlockState state, IBlockAccess world, BlockPos pos ) { - return 0; - } - @Override - public IBlockState getActualState( IBlockState state, IBlockAccess world, BlockPos pos ) - { + EnumSet flushWith = EnumSet.noneOf( EnumFacing.class ); + // Test every direction for another glass block for( EnumFacing facing : EnumFacing.values() ) { - state = state.withProperty( props[facing.ordinal()], isGlassBlock( world, pos, facing ) ); + if( isGlassBlock( world, pos, facing ) ) + { + flushWith.add( facing ); + } } - return state; + + GlassState glassState = new GlassState( pos.getX(), pos.getY(), pos.getZ(), flushWith ); + + IExtendedBlockState extState = (IExtendedBlockState) state; + + return extState.withProperty( GLASS_STATE, glassState ); + } + + private static boolean isGlassBlock( IBlockAccess world, BlockPos pos, EnumFacing facing ) + { + return world.getBlockState( pos.offset( facing ) ).getBlock() instanceof BlockQuartzGlass; } @Override @@ -79,7 +93,17 @@ public class BlockQuartzGlass extends AEBaseBlock @Override public boolean shouldSideBeRendered( final IBlockState state, final IBlockAccess w, final BlockPos pos, final EnumFacing side ) { - return !isGlassBlock( w, pos, side ) && super.shouldSideBeRendered( state, w, pos, side ); + BlockPos adjacentPos = pos.offset( side ); + + final Material mat = w.getBlockState( adjacentPos ).getBlock().getMaterial( state ); + if( mat == Material.GLASS || mat == AEGlassMaterial.INSTANCE ) + { + if( w.getBlockState( adjacentPos ).getBlock().getRenderType( state ) == this.getRenderType( state ) ) + { + return false; + } + } + return super.shouldSideBeRendered( state, w, pos, side ); } @Override @@ -87,5 +111,4 @@ public class BlockQuartzGlass extends AEBaseBlock { return false; } - } diff --git a/src/main/java/appeng/decorative/solid/GlassState.java b/src/main/java/appeng/decorative/solid/GlassState.java new file mode 100644 index 000000000..831733119 --- /dev/null +++ b/src/main/java/appeng/decorative/solid/GlassState.java @@ -0,0 +1,67 @@ +/* + * 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.decorative.solid; + + +import java.util.EnumSet; + +import net.minecraft.util.EnumFacing; + + +/** + * Immutable (and thus thread-safe) class that encapsulates the rendering state required for a connected texture + * glass block. + */ +public final class GlassState +{ + + private final int x; + private final int y; + private final int z; + + private final EnumSet flushWith = EnumSet.noneOf( EnumFacing.class ); + + public GlassState( int x, int y, int z, EnumSet flushWith ) + { + this.x = x; + this.y = y; + this.z = z; + this.flushWith.addAll( flushWith ); + } + + public int getX() + { + return x; + } + + public int getY() + { + return y; + } + + public int getZ() + { + return z; + } + + public boolean isFlushWith( EnumFacing side ) + { + return flushWith.contains( side ); + } + +} diff --git a/src/main/java/appeng/decorative/solid/UnlistedGlassStateProperty.java b/src/main/java/appeng/decorative/solid/UnlistedGlassStateProperty.java new file mode 100644 index 000000000..4d240d5b7 --- /dev/null +++ b/src/main/java/appeng/decorative/solid/UnlistedGlassStateProperty.java @@ -0,0 +1,54 @@ +/* + * 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.decorative.solid; + + +import net.minecraftforge.common.property.IUnlistedProperty; + + +/** + * This unlisted property is used to transport the connected texture state into our model class. + */ +public class UnlistedGlassStateProperty implements IUnlistedProperty +{ + + @Override + public String getName() + { + return "glass_state"; + } + + @Override + public boolean isValid( GlassState value ) + { + return true; + } + + @Override + public Class getType() + { + return GlassState.class; + } + + @Override + public String valueToString( GlassState value ) + { + return null; + } +} diff --git a/src/main/resources/assets/appliedenergistics2/blockstates/quartz_glass.json b/src/main/resources/assets/appliedenergistics2/blockstates/quartz_glass.json index a34ef0e1e..87996316e 100644 --- a/src/main/resources/assets/appliedenergistics2/blockstates/quartz_glass.json +++ b/src/main/resources/assets/appliedenergistics2/blockstates/quartz_glass.json @@ -1,31 +1,7 @@ { - "multipart": [ - { - "apply": [{ "model": "appliedenergistics2:quartz_glass_1" }, { "model": "appliedenergistics2:quartz_glass_2" }, { "model": "appliedenergistics2:quartz_glass_3" }, { "model": "appliedenergistics2:quartz_glass_4" }] - }, - { - "when": { "down": "false" }, - "apply": { "model": "appliedenergistics2:quartz_glass_frame", "x": 90 } - }, - { - "when": { "up": "false" }, - "apply": { "model": "appliedenergistics2:quartz_glass_frame", "x": -90 } - }, - { - "when": { "north": "false" }, - "apply": { "model": "appliedenergistics2:quartz_glass_frame"} - }, - { - "when": { "south": "false" }, - "apply": { "model": "appliedenergistics2:quartz_glass_frame", "y": 180 } - }, - { - "when": { "west": "false" }, - "apply": { "model": "appliedenergistics2:quartz_glass_frame", "y": -90 } - }, - { - "when": { "east": "false" }, - "apply": { "model": "appliedenergistics2:quartz_glass_frame", "y": 90 } + "variants": { + "normal": { + "model": "appliedenergistics2:builtin/quartz_glass" } - ] -} + } +} \ No newline at end of file diff --git a/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_1.json b/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_1.json deleted file mode 100644 index 88c195a8a..000000000 --- a/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_1.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "block/cube_all", - "textures": { - "all": "appliedenergistics2:blocks/quartz_glass_1" - } -} diff --git a/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_2.json b/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_2.json deleted file mode 100644 index fde5e9940..000000000 --- a/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_2.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "block/cube_all", - "textures": { - "all": "appliedenergistics2:blocks/quartz_glass_2" - } -} diff --git a/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_3.json b/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_3.json deleted file mode 100644 index e29a0c872..000000000 --- a/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_3.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "block/cube_all", - "textures": { - "all": "appliedenergistics2:blocks/quartz_glass_3" - } -} diff --git a/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_4.json b/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_4.json deleted file mode 100644 index 7d6895f68..000000000 --- a/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_4.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "block/cube_all", - "textures": { - "all": "appliedenergistics2:blocks/quartz_glass_4" - } -} diff --git a/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_frame.json b/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_frame.json deleted file mode 100644 index 594c4f379..000000000 --- a/src/main/resources/assets/appliedenergistics2/models/block/quartz_glass_frame.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "textures": { - "0": "appliedenergistics2:blocks/quartz_glass_frame" - }, - "elements": [ - { - "name": "Frame", - "from": [ 0.0, 0.0, 0.0 ], - "to": [ 16.0, 16.0, 1.0 ], - "faces": { - "east": { "texture": "#0", "uv": [ 0.0, 0.0, 1.0, 16.0 ], "cullface": "east" }, - "west": { "texture": "#0", "uv": [ 0.0, 0.0, 1.0, 16.0 ], "cullface": "west" }, - "up": { "texture": "#0", "uv": [ 0.0, 0.0, 16.0, 1.0 ], "cullface": "up" }, - "down": { "texture": "#0", "uv": [ 0.0, 0.0, 16.0, 1.0 ], "cullface": "down" } - } - } - ] -} \ No newline at end of file diff --git a/src/main/resources/assets/appliedenergistics2/models/item/quartz_glass.json b/src/main/resources/assets/appliedenergistics2/models/item/quartz_glass.json index ae7ee206b..cfe7da7de 100644 --- a/src/main/resources/assets/appliedenergistics2/models/item/quartz_glass.json +++ b/src/main/resources/assets/appliedenergistics2/models/item/quartz_glass.json @@ -1,6 +1,6 @@ { "parent": "block/cube_all", "textures": { - "all": "appliedenergistics2:blocks/quartz_glass" + "all": "appliedenergistics2:items/quartz_glass" } } \ No newline at end of file diff --git a/src/main/resources/assets/appliedenergistics2/models/item/quartz_vibrant_glass.json b/src/main/resources/assets/appliedenergistics2/models/item/quartz_vibrant_glass.json index ae7ee206b..cfe7da7de 100644 --- a/src/main/resources/assets/appliedenergistics2/models/item/quartz_vibrant_glass.json +++ b/src/main/resources/assets/appliedenergistics2/models/item/quartz_vibrant_glass.json @@ -1,6 +1,6 @@ { "parent": "block/cube_all", "textures": { - "all": "appliedenergistics2:blocks/quartz_glass" + "all": "appliedenergistics2:items/quartz_glass" } } \ No newline at end of file diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass_1.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_a.png similarity index 100% rename from src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass_1.png rename to src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_a.png diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass_2.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_b.png similarity index 100% rename from src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass_2.png rename to src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_b.png diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass_3.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_c.png similarity index 100% rename from src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass_3.png rename to src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_c.png diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass_4.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_d.png similarity index 100% rename from src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass_4.png rename to src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_d.png diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0001.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0001.png new file mode 100644 index 000000000..0096ebbb4 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0001.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0010.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0010.png new file mode 100644 index 000000000..18e178931 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0010.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0011.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0011.png new file mode 100644 index 000000000..4c959e13e Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0011.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0100.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0100.png new file mode 100644 index 000000000..8c28e98e7 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0100.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0101.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0101.png new file mode 100644 index 000000000..c70506ed0 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0101.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0110.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0110.png new file mode 100644 index 000000000..0a07653a5 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0110.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0111.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0111.png new file mode 100644 index 000000000..bc2a7120b Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame0111.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1000.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1000.png new file mode 100644 index 000000000..94863092f Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1000.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1001.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1001.png new file mode 100644 index 000000000..6c7a463db Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1001.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1010.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1010.png new file mode 100644 index 000000000..6b63d1655 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1010.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1011.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1011.png new file mode 100644 index 000000000..627f8a209 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1011.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1100.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1100.png new file mode 100644 index 000000000..1b8163247 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1100.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1101.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1101.png new file mode 100644 index 000000000..67511a5ab Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1101.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1110.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1110.png new file mode 100644 index 000000000..e8d0be186 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1110.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1111.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1111.png new file mode 100644 index 000000000..1b44a2e81 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/glass/quartz_glass_frame1111.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass.png deleted file mode 100644 index 334373ab2..000000000 Binary files a/src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass.png and /dev/null differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass.png.mcmeta b/src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass.png.mcmeta deleted file mode 100644 index 2e22c0414..000000000 --- a/src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass.png.mcmeta +++ /dev/null @@ -1,5 +0,0 @@ -{ - "animation": { - "frametime": 100 - } -} \ No newline at end of file diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass_frame.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass_frame.png deleted file mode 100644 index e6943dd25..000000000 Binary files a/src/main/resources/assets/appliedenergistics2/textures/blocks/quartz_glass_frame.png and /dev/null differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/items/quartz_glass.png b/src/main/resources/assets/appliedenergistics2/textures/items/quartz_glass.png new file mode 100644 index 000000000..520ced321 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/items/quartz_glass.png differ