Implemented Glass Blocks (#51)

* Implemented connected texture glass blocks (different approach from 1.7).
This commit is contained in:
shartte 2016-08-16 16:04:31 +02:00 committed by Elix_x
parent 026de7d590
commit 115f73de2e
33 changed files with 741 additions and 10 deletions

View File

@ -62,6 +62,7 @@ import appeng.client.render.effects.EnergyFx;
import appeng.client.render.effects.LightningArcFX;
import appeng.client.render.effects.LightningFX;
import appeng.client.render.effects.VibrantFX;
import appeng.client.render.model.GlassModelLoader;
import appeng.client.render.model.UVLModelLoader;
import appeng.client.render.textures.ParticleTextures;
import appeng.core.AEConfig;
@ -93,6 +94,7 @@ public class ClientHelper extends ServerHelper
{
MinecraftForge.EVENT_BUS.register( this );
ModelLoaderRegistry.registerLoader( UVLModelLoader.INSTANCE );
ModelLoaderRegistry.registerLoader( new GlassModelLoader() );
for( IAEFeature feature : Api.INSTANCE.definitions().getFeatureRegistry().getRegisteredFeatures() )
{
feature.handler().registerStateMapper();

View File

@ -0,0 +1,313 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl>.
*/
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.GlassState;
import appeng.decorative.solid.QuartzGlassBlock;
public 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/BlockQuartzGlassA" );
static final ResourceLocation TEXTURE_B = new ResourceLocation( "appliedenergistics2:blocks/glass/BlockQuartzGlassB" );
static final ResourceLocation TEXTURE_C = new ResourceLocation( "appliedenergistics2:blocks/glass/BlockQuartzGlassC" );
static final ResourceLocation TEXTURE_D = new ResourceLocation( "appliedenergistics2:blocks/glass/BlockQuartzGlassD" );
// 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/BlockQuartzGlassFrame" + s ) )
.toArray( ResourceLocation[]::new );
}
private final TextureAtlasSprite[] glassTextures;
private final TextureAtlasSprite[] frameTextures;
private final VertexFormat vertexFormat;
public GlassBakedModel( VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> 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<BakedQuad> 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( QuartzGlassBlock.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<BakedQuad> quads = new ArrayList<>( 5 ); // At most 5
List<Vec3d> 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<Vec3d> 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;
}
}

View File

@ -0,0 +1,69 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl>.
*/
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<ResourceLocation> getDependencies()
{
return Collections.emptySet();
}
@Override
public Collection<ResourceLocation> getTextures()
{
return ImmutableSet.<ResourceLocation>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<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
{
return new GlassBakedModel( format, bakedTextureGetter );
}
@Override
public IModelState getDefaultState()
{
return TRSRTransformation.identity();
}
}

View File

@ -0,0 +1,55 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.model;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.ICustomModelLoader;
import net.minecraftforge.client.model.IModel;
import appeng.core.AppEng;
/**
* Model loader to manage connected texture glass.
*/
public class GlassModelLoader implements ICustomModelLoader
{
private static final GlassModel GLASS_MODEL = new GlassModel();
@Override
public boolean accepts( ResourceLocation modelLocation )
{
return modelLocation.getResourceDomain().equals( AppEng.MOD_ID ) && "models/block/builtin/connected_glass".equals( modelLocation.getResourcePath() );
}
@Override
public IModel loadModel( ResourceLocation modelLocation ) throws Exception
{
return GLASS_MODEL;
}
@Override
public void onResourceManagerReload( IResourceManager resourceManager )
{
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<EnumFacing, List<Vec3d>> cornersForFacing = generateCornersForFacings();
private RenderHelper() {
}
static List<Vec3d> getFaceCorners( EnumFacing side )
{
return cornersForFacing.get( side );
}
private static EnumMap<EnumFacing, List<Vec3d>> generateCornersForFacings()
{
EnumMap<EnumFacing, List<Vec3d>> result = new EnumMap<>( EnumFacing.class );
for( EnumFacing facing : EnumFacing.values() )
{
List<Vec3d> 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 );
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<EnumFacing> flushWith = EnumSet.noneOf( EnumFacing.class );
public GlassState( int x, int y, int z, EnumSet<EnumFacing> 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 );
}
}

View File

@ -22,19 +22,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.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.block.IHasSpecialItemModel;
import appeng.core.features.AEFeature;
import appeng.helpers.AEGlassMaterial;
public class QuartzGlassBlock extends AEBaseBlock
public class QuartzGlassBlock extends AEBaseBlock implements IHasSpecialItemModel
{
// This unlisted property is used to determine the actual block that should be rendered
public static final UnlistedGlassStateProperty GLASS_STATE = new UnlistedGlassStateProperty();
public QuartzGlassBlock()
{
super( Material.GLASS );
@ -43,6 +53,40 @@ public class QuartzGlassBlock extends AEBaseBlock
this.setFeature( EnumSet.of( AEFeature.DecorativeQuartzBlocks ) );
}
@Override
protected BlockStateContainer createBlockState()
{
IProperty[] listedProperties = new IProperty[0];
IUnlistedProperty[] unlistedProperties = new IUnlistedProperty[] { GLASS_STATE };
return new ExtendedBlockState( this, listedProperties, unlistedProperties );
}
@Override
public IBlockState getExtendedState( IBlockState state, IBlockAccess world, BlockPos pos )
{
EnumSet<EnumFacing> flushWith = EnumSet.noneOf( EnumFacing.class );
// Test every direction for another glass block
for( EnumFacing facing : EnumFacing.values() )
{
if( isGlassBlock( world, pos, facing ) )
{
flushWith.add( facing );
}
}
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 QuartzGlassBlock;
}
@Override
public BlockRenderLayer getBlockLayer()
{
@ -52,14 +96,23 @@ public class QuartzGlassBlock extends AEBaseBlock
@Override
public boolean shouldSideBeRendered( final IBlockState state, final IBlockAccess w, final BlockPos pos, final EnumFacing side )
{
final Material mat = w.getBlockState( pos ).getBlock().getMaterial(state);
BlockPos adjacentPos = pos.offset( side );
final Material mat = w.getBlockState( adjacentPos ).getBlock().getMaterial( state );
if( mat == Material.GLASS || mat == AEGlassMaterial.INSTANCE )
{
if( w.getBlockState( pos ).getBlock().getRenderType(state) == this.getRenderType(state) )
if( w.getBlockState( adjacentPos ).getBlock().getRenderType( state ) == this.getRenderType( state ) )
{
return false;
}
}
return super.shouldSideBeRendered( state, w, pos, side );
}
@Override
public boolean isFullCube( IBlockState state )
{
return false;
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<GlassState>
{
@Override
public String getName()
{
return "glass_state";
}
@Override
public boolean isValid( GlassState value )
{
return true;
}
@Override
public Class<GlassState> getType()
{
return GlassState.class;
}
@Override
public String valueToString( GlassState value )
{
return null;
}
}

View File

@ -1,5 +1,5 @@
{
"variants": {
"normal": { "model": "appliedenergistics2:QuartzBlock" }
"normal": { "model": "appliedenergistics2:builtin/connected_glass" }
}
}

View File

@ -0,0 +1,5 @@
{
"variants": {
"normal": { "model": "appliedenergistics2:builtin/connected_glass" }
}
}

View File

@ -1,6 +0,0 @@
{
"parent": "block/cube_all",
"textures": {
"all": "appliedenergistics2:blocks/QuartzOreBlock"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "block/cube_all",
"textures": {
"all": "appliedenergistics2:items/BlockQuartzGlass"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "block/cube_all",
"textures": {
"all": "appliedenergistics2:items/BlockQuartzGlass"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B