Fixes #2377: Paint blocks now render correctly.

This commit is contained in:
Sebastian Hartte 2016-10-15 11:50:55 +02:00
parent 070b35f3db
commit c590e7f6e6
14 changed files with 400 additions and 7 deletions

View File

@ -16,15 +16,19 @@
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
package appeng.block.paint;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.material.MapColor;
import net.minecraft.block.material.MaterialLiquid;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
@ -34,16 +38,22 @@ import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.property.ExtendedBlockState;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import appeng.block.AEBaseTileBlock;
import appeng.helpers.Splotch;
import appeng.tile.misc.TilePaint;
import appeng.util.Platform;
public class BlockPaint extends AEBaseTileBlock
{
static final PaintSplotchesProperty SPLOTCHES = new PaintSplotchesProperty();
public BlockPaint()
{
super( new MaterialLiquid( MapColor.AIR ) );
@ -54,6 +64,28 @@ public class BlockPaint extends AEBaseTileBlock
this.setOpaque( false );
}
@Override
protected BlockStateContainer createBlockState()
{
return new ExtendedBlockState( this, new IProperty[0], new IUnlistedProperty[] { SPLOTCHES } );
}
@Override
public IBlockState getExtendedState( IBlockState state, IBlockAccess world, BlockPos pos )
{
IExtendedBlockState extState = (IExtendedBlockState) state;
TilePaint te = getTileEntity( world, pos );
Collection<Splotch> splotches = Collections.emptyList();
if( te != null )
{
splotches = te.getDots();
}
return extState.withProperty( SPLOTCHES, new PaintSplotches( splotches ) );
}
@Override
public BlockRenderLayer getBlockLayer()
{

View File

@ -0,0 +1,196 @@
package appeng.block.paint;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
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.minecraftforge.common.property.IExtendedBlockState;
import appeng.client.render.cablebus.CubeBuilder;
import appeng.core.AppEng;
import appeng.helpers.Splotch;
/**
* Renders paint blocks, which render multiple "splotches" that have been applied to the sides of adjacent blocks using a
* matter cannon with paint balls.
*/
class PaintBakedModel implements IBakedModel
{
private static final ResourceLocation TEXTURE_PAINT1 = new ResourceLocation( AppEng.MOD_ID, "blocks/paint1" );
private static final ResourceLocation TEXTURE_PAINT2 = new ResourceLocation( AppEng.MOD_ID, "blocks/paint2" );
private static final ResourceLocation TEXTURE_PAINT3 = new ResourceLocation( AppEng.MOD_ID, "blocks/paint3" );
private final VertexFormat vertexFormat;
private final TextureAtlasSprite[] textures;
PaintBakedModel( VertexFormat vertexFormat, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
{
this.vertexFormat = vertexFormat;
this.textures = new TextureAtlasSprite[] {
bakedTextureGetter.apply( TEXTURE_PAINT1 ),
bakedTextureGetter.apply( TEXTURE_PAINT2 ),
bakedTextureGetter.apply( TEXTURE_PAINT3 )
};
}
@Override
public List<BakedQuad> getQuads( @Nullable IBlockState state, @Nullable EnumFacing side, long rand )
{
if( side != null )
{
return Collections.emptyList();
}
if( !( state instanceof IExtendedBlockState ) )
{
// This is the inventory model which should usually not be used other than in special cases
List<BakedQuad> quads = new ArrayList<>( 1 );
CubeBuilder builder = new CubeBuilder( this.vertexFormat, quads );
builder.setTexture( textures[0] );
builder.addCube( 0, 0, 0, 16, 16, 16 );
return quads;
}
IExtendedBlockState extendedBlockState = (IExtendedBlockState) state;
PaintSplotches splotchesState = extendedBlockState.getValue( BlockPaint.SPLOTCHES );
if( splotchesState == null )
{
return Collections.emptyList();
}
List<Splotch> splotches = splotchesState.getSplotches();
CubeBuilder builder = new CubeBuilder( vertexFormat );
float offsetConstant = 0.001f;
for( final Splotch s : splotches) {
if( s.isLumen() )
{
builder.setColorRGB( s.getColor().whiteVariant );
builder.setRenderFullBright( true );
}
else
{
builder.setColorRGB( s.getColor().mediumVariant );
builder.setRenderFullBright( false );
}
float offset = offsetConstant;
offsetConstant += 0.001f;
final float buffer = 0.1f;
float pos_x = s.x();
float pos_y = s.y();
pos_x = Math.max( buffer, Math.min( 1.0f - buffer, pos_x ) );
pos_y = Math.max( buffer, Math.min( 1.0f - buffer, pos_y ) );
TextureAtlasSprite ico = textures[s.getSeed() % textures.length];
builder.setTexture( ico );
builder.setCustomUv( s.getSide().getOpposite(), 0, 0, 16, 16 );
switch( s.getSide() )
{
case UP:
offset = 1.0f - offset;
builder.addQuad( EnumFacing.DOWN, pos_x - buffer, offset, pos_y - buffer,
pos_x + buffer, offset, pos_y + buffer );
break;
case DOWN:
builder.addQuad( EnumFacing.UP, pos_x - buffer, offset, pos_y - buffer,
pos_x + buffer, offset, pos_y + buffer );
break;
case EAST:
offset = 1.0f - offset;
builder.addQuad( EnumFacing.WEST, offset, pos_x - buffer, pos_y - buffer,
offset, pos_x + buffer, pos_y + buffer );
break;
case WEST:
builder.addQuad( EnumFacing.EAST, offset, pos_x - buffer, pos_y - buffer,
offset, pos_x + buffer, pos_y + buffer );
break;
case SOUTH:
offset = 1.0f - offset;
builder.addQuad( EnumFacing.NORTH, pos_x - buffer, pos_y - buffer, offset,
pos_x + buffer, pos_y + buffer, offset );
break;
case NORTH:
builder.addQuad( EnumFacing.SOUTH, pos_x - buffer, pos_y - buffer, offset,
pos_x + buffer, pos_y + buffer, offset );
break;
default:
}
}
return builder.getOutput();
}
@Override
public boolean isAmbientOcclusion()
{
return false;
}
@Override
public boolean isGui3d()
{
return true;
}
@Override
public boolean isBuiltInRenderer()
{
return false;
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return textures[0];
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return ItemCameraTransforms.DEFAULT;
}
@Override
public ItemOverrideList getOverrides()
{
return ItemOverrideList.NONE;
}
static List<ResourceLocation> getRequiredTextures()
{
return ImmutableList.of(
TEXTURE_PAINT1, TEXTURE_PAINT2, TEXTURE_PAINT3
);
}
}

View File

@ -0,0 +1,45 @@
package appeng.block.paint;
import java.util.Collection;
import java.util.Collections;
import com.google.common.base.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 net.minecraftforge.common.model.TRSRTransformation;
class PaintModel implements IModel
{
@Override
public Collection<ResourceLocation> getDependencies()
{
return Collections.emptyList();
}
@Override
public Collection<ResourceLocation> getTextures()
{
return PaintBakedModel.getRequiredTextures();
}
@Override
public IBakedModel bake( IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
{
return new PaintBakedModel( format, bakedTextureGetter );
}
@Override
public IModelState getDefaultState()
{
return TRSRTransformation.identity();
}
}

View File

@ -0,0 +1,23 @@
package appeng.block.paint;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
public class PaintRendering extends BlockRenderingCustomizer
{
@Override
@SideOnly( Side.CLIENT )
public void customize( IBlockRendering rendering, IItemRendering itemRendering )
{
rendering.builtInModel( "models/block/paint", new PaintModel() );
// Disable auto rotation
rendering.modelCustomizer( ( location, model ) -> model );
}
}

View File

@ -0,0 +1,30 @@
package appeng.block.paint;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.ImmutableList;
import appeng.helpers.Splotch;
/**
* Used to transfer the state about paint splotches from the game thread to the render thread.
*/
class PaintSplotches
{
private final List<Splotch> splotches;
PaintSplotches( Collection<Splotch> splotches )
{
this.splotches = ImmutableList.copyOf( splotches );
}
List<Splotch> getSplotches()
{
return splotches;
}
}

View File

@ -0,0 +1,33 @@
package appeng.block.paint;
import net.minecraftforge.common.property.IUnlistedProperty;
class PaintSplotchesProperty implements IUnlistedProperty<PaintSplotches>
{
@Override
public String getName()
{
return "paint_splots";
}
@Override
public boolean isValid( PaintSplotches value )
{
return value != null;
}
@Override
public Class<PaintSplotches> getType()
{
return PaintSplotches.class;
}
@Override
public String valueToString( PaintSplotches value )
{
return null;
}
}

View File

@ -103,6 +103,30 @@ public class CubeBuilder
}
}
public void addQuad( EnumFacing face, float x1, float y1, float z1, float x2, float y2, float z2 )
{
// If brightness is forced to specific values, extend the vertex format to contain the multi-texturing lightmap
// offset
VertexFormat savedFormat = null;
if( renderFullBright )
{
savedFormat = format;
format = new VertexFormat( savedFormat );
if( !format.getElements().contains( DefaultVertexFormats.TEX_2S ) )
{
format.addElement( DefaultVertexFormats.TEX_2S );
}
}
putFace( face, x1, y1, z1, x2, y2, z2 );
// Restore old format
if( savedFormat != null )
{
format = savedFormat;
}
}
private static final class UvVector
{
float u1;

View File

@ -46,7 +46,6 @@ import appeng.block.misc.BlockCondenser;
import appeng.block.misc.BlockInscriber;
import appeng.block.misc.BlockInterface;
import appeng.block.misc.BlockLightDetector;
import appeng.block.misc.BlockPaint;
import appeng.block.misc.BlockQuartzFixture;
import appeng.block.misc.BlockQuartzGrowthAccelerator;
import appeng.block.misc.BlockSecurityStation;
@ -67,6 +66,8 @@ import appeng.block.networking.BlockWireless;
import appeng.block.networking.CableBusRendering;
import appeng.block.networking.ControllerRendering;
import appeng.block.networking.WirelessRendering;
import appeng.block.paint.BlockPaint;
import appeng.block.paint.PaintRendering;
import appeng.block.qnb.BlockQuantumLinkChamber;
import appeng.block.qnb.BlockQuantumRing;
import appeng.block.qnb.QuantumBridgeRendering;
@ -373,7 +374,10 @@ public final class ApiBlocks implements IBlocks
this.lightDetector = registry.block( "light_detector", BlockLightDetector::new ).features( AEFeature.LightDetector )
.useCustomItemModel()
.build();
this.paint = registry.block( "paint", BlockPaint::new ).features( AEFeature.PaintBalls ).build();
this.paint = registry.block( "paint", BlockPaint::new )
.features( AEFeature.PaintBalls )
.rendering( new PaintRendering() )
.build();
this.skyStoneStairs = makeStairs( "sky_stone_stairs", registry, this.skyStoneBlock() );
this.smoothSkyStoneStairs = makeStairs( "smooth_sky_stone_stairs", registry, this.smoothSkyStoneBlock() );

View File

@ -62,7 +62,7 @@ import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.api.util.AEColor;
import appeng.api.util.DimensionalCoord;
import appeng.block.misc.BlockPaint;
import appeng.block.paint.BlockPaint;
import appeng.block.networking.BlockCableBus;
import appeng.core.AEConfig;
import appeng.core.localization.GuiText;

View File

@ -21,11 +21,10 @@ package appeng.tile.misc;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import com.google.common.collect.ImmutableList;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
@ -270,7 +269,7 @@ public class TilePaint extends AEBaseTile
{
if( this.dots == null )
{
return ImmutableList.of();
return Collections.emptyList();
}
return this.dots;

View File

@ -0,0 +1,7 @@
{
"variants": {
"normal": {
"model": "appliedenergistics2:paint"
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B