diff --git a/src/main/java/appeng/block/misc/BlockPaint.java b/src/main/java/appeng/block/paint/BlockPaint.java similarity index 76% rename from src/main/java/appeng/block/misc/BlockPaint.java rename to src/main/java/appeng/block/paint/BlockPaint.java index 9ef1deb9..5bb13e66 100644 --- a/src/main/java/appeng/block/misc/BlockPaint.java +++ b/src/main/java/appeng/block/paint/BlockPaint.java @@ -16,15 +16,19 @@ * along with Applied Energistics 2. If not, see . */ -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 splotches = Collections.emptyList(); + if( te != null ) + { + splotches = te.getDots(); + } + + return extState.withProperty( SPLOTCHES, new PaintSplotches( splotches ) ); + } + @Override public BlockRenderLayer getBlockLayer() { diff --git a/src/main/java/appeng/block/paint/PaintBakedModel.java b/src/main/java/appeng/block/paint/PaintBakedModel.java new file mode 100644 index 00000000..5a541f18 --- /dev/null +++ b/src/main/java/appeng/block/paint/PaintBakedModel.java @@ -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 bakedTextureGetter ) + { + this.vertexFormat = vertexFormat; + this.textures = new TextureAtlasSprite[] { + bakedTextureGetter.apply( TEXTURE_PAINT1 ), + bakedTextureGetter.apply( TEXTURE_PAINT2 ), + bakedTextureGetter.apply( TEXTURE_PAINT3 ) + }; + } + + @Override + public List 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 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 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 getRequiredTextures() + { + return ImmutableList.of( + TEXTURE_PAINT1, TEXTURE_PAINT2, TEXTURE_PAINT3 + ); + } +} diff --git a/src/main/java/appeng/block/paint/PaintModel.java b/src/main/java/appeng/block/paint/PaintModel.java new file mode 100644 index 00000000..de9e90ff --- /dev/null +++ b/src/main/java/appeng/block/paint/PaintModel.java @@ -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 getDependencies() + { + return Collections.emptyList(); + } + + @Override + public Collection getTextures() + { + return PaintBakedModel.getRequiredTextures(); + } + + @Override + public IBakedModel bake( IModelState state, VertexFormat format, Function bakedTextureGetter ) + { + return new PaintBakedModel( format, bakedTextureGetter ); + } + + @Override + public IModelState getDefaultState() + { + return TRSRTransformation.identity(); + } + +} diff --git a/src/main/java/appeng/block/paint/PaintRendering.java b/src/main/java/appeng/block/paint/PaintRendering.java new file mode 100644 index 00000000..8967bbed --- /dev/null +++ b/src/main/java/appeng/block/paint/PaintRendering.java @@ -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 ); + } +} diff --git a/src/main/java/appeng/block/paint/PaintSplotches.java b/src/main/java/appeng/block/paint/PaintSplotches.java new file mode 100644 index 00000000..39664526 --- /dev/null +++ b/src/main/java/appeng/block/paint/PaintSplotches.java @@ -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 splotches; + + PaintSplotches( Collection splotches ) + { + this.splotches = ImmutableList.copyOf( splotches ); + } + + List getSplotches() + { + return splotches; + } + +} diff --git a/src/main/java/appeng/block/paint/PaintSplotchesProperty.java b/src/main/java/appeng/block/paint/PaintSplotchesProperty.java new file mode 100644 index 00000000..2f52cf50 --- /dev/null +++ b/src/main/java/appeng/block/paint/PaintSplotchesProperty.java @@ -0,0 +1,33 @@ +package appeng.block.paint; + + +import net.minecraftforge.common.property.IUnlistedProperty; + + +class PaintSplotchesProperty implements IUnlistedProperty +{ + + @Override + public String getName() + { + return "paint_splots"; + } + + @Override + public boolean isValid( PaintSplotches value ) + { + return value != null; + } + + @Override + public Class getType() + { + return PaintSplotches.class; + } + + @Override + public String valueToString( PaintSplotches value ) + { + return null; + } +} diff --git a/src/main/java/appeng/client/render/cablebus/CubeBuilder.java b/src/main/java/appeng/client/render/cablebus/CubeBuilder.java index 81dca1cc..738aa7bd 100644 --- a/src/main/java/appeng/client/render/cablebus/CubeBuilder.java +++ b/src/main/java/appeng/client/render/cablebus/CubeBuilder.java @@ -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; diff --git a/src/main/java/appeng/core/api/definitions/ApiBlocks.java b/src/main/java/appeng/core/api/definitions/ApiBlocks.java index 09329bf9..c21d6879 100644 --- a/src/main/java/appeng/core/api/definitions/ApiBlocks.java +++ b/src/main/java/appeng/core/api/definitions/ApiBlocks.java @@ -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() ); diff --git a/src/main/java/appeng/items/tools/powered/ToolColorApplicator.java b/src/main/java/appeng/items/tools/powered/ToolColorApplicator.java index 9fb68cd4..dacacbe4 100644 --- a/src/main/java/appeng/items/tools/powered/ToolColorApplicator.java +++ b/src/main/java/appeng/items/tools/powered/ToolColorApplicator.java @@ -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; diff --git a/src/main/java/appeng/tile/misc/TilePaint.java b/src/main/java/appeng/tile/misc/TilePaint.java index e4ae59e4..373326ca 100644 --- a/src/main/java/appeng/tile/misc/TilePaint.java +++ b/src/main/java/appeng/tile/misc/TilePaint.java @@ -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; diff --git a/src/main/resources/assets/appliedenergistics2/blockstates/paint.json b/src/main/resources/assets/appliedenergistics2/blockstates/paint.json new file mode 100644 index 00000000..1a19df38 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/blockstates/paint.json @@ -0,0 +1,7 @@ +{ + "variants": { + "normal": { + "model": "appliedenergistics2:paint" + } + } +} diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/paint1.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/paint1.png new file mode 100644 index 00000000..57beaf07 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/paint1.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/paint2.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/paint2.png new file mode 100644 index 00000000..5f273dc7 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/paint2.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/paint3.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/paint3.png new file mode 100644 index 00000000..3902d375 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/paint3.png differ