From b2a5a4822a46bc05928a2043995cd00d7063c1e6 Mon Sep 17 00:00:00 2001 From: Zelophed Date: Sat, 18 Jul 2020 20:07:22 +0200 Subject: [PATCH] more changes to heater and particles -heater now uses a enum for the blaze state -added new particles for the heater -changed heaters voxel shape --- build.gradle | 4 + .../com/simibubi/create/AllParticleTypes.java | 32 ++- .../java/com/simibubi/create/AllShapes.java | 8 +- .../simibubi/create/compat/jei/CreateJEI.java | 1 + .../components/fan/EncasedFanTileEntity.java | 16 +- .../mixer/MechanicalMixerTileEntity.java | 8 +- .../contraptions/particle/CubeParticle.java | 147 ++++++++++++ .../particle/CubeParticleData.java | 83 +++++++ .../contraptions/processing/HeaterBlock.java | 88 +++++-- .../processing/HeaterRenderer.java | 8 +- .../processing/HeaterTileEntity.java | 217 +++++++++++++----- .../content/logistics/InWorldProcessing.java | 5 +- .../assets/create/particles/cube.json | 3 + 13 files changed, 510 insertions(+), 110 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticle.java create mode 100644 src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticleData.java create mode 100644 src/main/resources/assets/create/particles/cube.json diff --git a/build.gradle b/build.gradle index f665ed05d..b8cf8d5e0 100644 --- a/build.gradle +++ b/build.gradle @@ -69,6 +69,10 @@ minecraft { } } +compileJava { + options.compilerArgs = ["-Xdiags:verbose"] +} + sourceSets.main.resources { srcDir 'src/generated/resources' } diff --git a/src/main/java/com/simibubi/create/AllParticleTypes.java b/src/main/java/com/simibubi/create/AllParticleTypes.java index fbce493c2..c47062d0b 100644 --- a/src/main/java/com/simibubi/create/AllParticleTypes.java +++ b/src/main/java/com/simibubi/create/AllParticleTypes.java @@ -2,13 +2,11 @@ package com.simibubi.create; import java.util.function.Supplier; -import com.simibubi.create.content.contraptions.particle.AirFlowParticleData; -import com.simibubi.create.content.contraptions.particle.HeaterParticleData; -import com.simibubi.create.content.contraptions.particle.ICustomParticle; -import com.simibubi.create.content.contraptions.particle.RotationIndicatorParticleData; +import com.simibubi.create.content.contraptions.particle.*; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.IParticleFactory; import net.minecraft.client.particle.ParticleManager; import net.minecraft.particles.IParticleData; import net.minecraft.particles.ParticleType; @@ -23,15 +21,21 @@ public enum AllParticleTypes { ROTATION_INDICATOR(RotationIndicatorParticleData::new), AIR_FLOW(AirFlowParticleData::new), - HEATER_PARTICLE(HeaterParticleData::new) + HEATER_PARTICLE(HeaterParticleData::new), + CUBE(CubeParticleData::dummy, CubeParticle.Factory::new) ; private ParticleEntry entry; - private AllParticleTypes(Supplier> typeFactory) { + AllParticleTypes(Supplier> typeFactory) { String asId = Lang.asId(this.name()); - entry = new ParticleEntry(new ResourceLocation(Create.ID, asId), typeFactory); + entry = new ParticleEntry<>(new ResourceLocation(Create.ID, asId), typeFactory); + } + + AllParticleTypes(Supplier> typeFactory, Supplier> particleMetaFactory) { + String asId = Lang.asId(this.name()); + entry = new ParticleEntry<>(new ResourceLocation(Create.ID, asId), typeFactory, particleMetaFactory); } public static void register(RegistryEvent.Register> event) { @@ -56,12 +60,18 @@ public enum AllParticleTypes { private class ParticleEntry { Supplier> typeFactory; + Supplier> particleMetaFactory; ParticleType type; ResourceLocation id; - public ParticleEntry(ResourceLocation id, Supplier> typeFactory) { + public ParticleEntry(ResourceLocation id, Supplier> typeFactory, Supplier> particleMetaFactory) { this.id = id; this.typeFactory = typeFactory; + this.particleMetaFactory = particleMetaFactory; + } + + public ParticleEntry(ResourceLocation id, Supplier> typeFactory) { + this(id, typeFactory, null); } ParticleType getType() { @@ -85,8 +95,10 @@ public enum AllParticleTypes { @OnlyIn(Dist.CLIENT) void registerFactory(ParticleManager particles) { makeType(); - particles.registerFactory(type, typeFactory.get() - .getFactory()); + if (particleMetaFactory == null) + particles.registerFactory(type, typeFactory.get().getFactory()); + else + particles.registerFactory(type, particleMetaFactory.get()); } } diff --git a/src/main/java/com/simibubi/create/AllShapes.java b/src/main/java/com/simibubi/create/AllShapes.java index aeda326eb..3533cf14c 100644 --- a/src/main/java/com/simibubi/create/AllShapes.java +++ b/src/main/java/com/simibubi/create/AllShapes.java @@ -113,11 +113,11 @@ public class AllShapes { BASIN_BLOCK_SHAPE = shape(0, 2, 0, 16, 13, 16).erase(2, 5, 2, 14, 14, 14) .add(2, 0, 2, 14, 2, 14) - .build(), + .build(), HEATER_BLOCK_SHAPE = - shape(2, 0, 2, 14, 16, 14).add(0, 0, 0, 16, 2, 16) - .erase(3, 5, 3, 13, 16, 13) - .build(), + shape(2, 0, 2, 14, 14, 14).add(0, 0, 0, 16, 4, 16).build(), + HEATER_BLOCK_SPECIAL_COLLISION_SHAPE = + shape(0, 0, 0, 16, 4, 16).build(), CRUSHING_WHEEL_COLLISION_SHAPE = cuboid(0, 0, 0, 16, 22, 16), MECHANICAL_PROCESSOR_SHAPE = shape(VoxelShapes.fullCube()).erase(4, 0, 4, 12, 16, 12) .build(), diff --git a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java index d547d67c5..18d414246 100644 --- a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java +++ b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java @@ -162,6 +162,7 @@ public class CreateJEI implements IModPlugin { registration.addRecipeCatalyst(new ItemStack(AllItems.BLOCKZAPPER.get()), blockzapperCategory.getUid()); registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_MIXER.get()), mixingCategory.getUid()); registration.addRecipeCatalyst(new ItemStack(AllBlocks.BASIN.get()), mixingCategory.getUid()); + registration.addRecipeCatalyst(new ItemStack(AllBlocks.HEATER.get()), mixingCategory.getUid()); registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_SAW.get()), sawingCategory.getUid()); registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_SAW.get()), blockCuttingCategory.getUid()); registration.addRecipeCatalyst(new ItemStack(Blocks.STONECUTTER), blockCuttingCategory.getUid()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java index 64992ef0d..0b08cfb3e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java @@ -6,9 +6,7 @@ import com.simibubi.create.content.contraptions.processing.HeaterBlock; import com.simibubi.create.content.logistics.block.chute.ChuteTileEntity; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.CKinetics; - import net.minecraft.block.BlockState; -import net.minecraft.block.CampfireBlock; import net.minecraft.nbt.CompoundNBT; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntity; @@ -78,9 +76,17 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity { if (world == null) return false; BlockState checkState = world.getBlockState(pos.down()); - return checkState.getBlock().isIn(AllBlockTags.FAN_HEATERS.tag) - && ((!checkState.has(HeaterBlock.BLAZE_LEVEL)) || checkState.get(HeaterBlock.BLAZE_LEVEL) >= 1) - && (!checkState.has(BlockStateProperties.LIT) || checkState.get(BlockStateProperties.LIT)); + + if (!checkState.getBlock().isIn(AllBlockTags.FAN_HEATERS.tag)) + return false; + + if (checkState.has(HeaterBlock.BLAZE_LEVEL) && !checkState.get(HeaterBlock.BLAZE_LEVEL).min(HeaterBlock.HeatLevel.FADING)) + return false; + + if (checkState.has(BlockStateProperties.LIT) && !checkState.get(BlockStateProperties.LIT)) + return false; + + return true; } public float getMaxDistance() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java index a5de28be4..6cf5041bd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java @@ -232,7 +232,7 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { if (!(recipe instanceof MixingRecipe)) return true; - return ((MixingRecipe) recipe).getHeatLevelRequired() <= getHeatLevelApplied(); + return ((MixingRecipe) recipe).getHeatLevelRequired() <= getHeatLevelApplied().ordinal(); } @Override @@ -269,12 +269,12 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { return running; } - private int getHeatLevelApplied() { + private HeaterBlock.HeatLevel getHeatLevelApplied() { if (world == null) - return 0; + return HeaterBlock.HeatLevel.NONE; BlockState state = world.getBlockState(pos.down(3)); if (state.has(HeaterBlock.BLAZE_LEVEL)) return state.get(HeaterBlock.BLAZE_LEVEL); - return AllTags.AllBlockTags.FAN_HEATERS.matches(state) ? 1 : 0; + return AllTags.AllBlockTags.FAN_HEATERS.matches(state) ? HeaterBlock.HeatLevel.SMOULDERING : HeaterBlock.HeatLevel.NONE; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticle.java b/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticle.java new file mode 100644 index 000000000..dafdaa6b4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticle.java @@ -0,0 +1,147 @@ +package com.simibubi.create.content.contraptions.particle; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.IVertexBuilder; +import net.minecraft.client.particle.IParticleFactory; +import net.minecraft.client.particle.IParticleRenderType; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; + +public class CubeParticle extends Particle { + + public static final Vec3d[] CUBE = { + // TOP + new Vec3d(1, 1, -1), new Vec3d(1, 1, 1), new Vec3d(-1, 1, 1), new Vec3d(-1, 1, -1), + + // BOTTOM + new Vec3d(-1, -1, -1), new Vec3d(-1, -1, 1), new Vec3d(1, -1, 1), new Vec3d(1, -1, -1), + + // FRONT + new Vec3d(-1, -1, 1), new Vec3d(-1, 1, 1), new Vec3d(1, 1, 1), new Vec3d(1, -1, 1), + + // BACK + new Vec3d(1, -1, -1), new Vec3d(1, 1, -1), new Vec3d(-1, 1, -1), new Vec3d(-1, -1, -1), + + // LEFT + new Vec3d(-1, -1, -1), new Vec3d(-1, 1, -1), new Vec3d(-1, 1, 1), new Vec3d(-1, -1, 1), + + // RIGHT + new Vec3d(1, -1, 1), new Vec3d(1, 1, 1), new Vec3d(1, 1, -1), new Vec3d(1, -1, -1) }; + + public static final Vec3d[] CUBE_NORMALS = { + //modified normals for the sides + new Vec3d(0, 1, 0), + new Vec3d(0, -1, 0), + new Vec3d(0, 0, 1), + new Vec3d(0, 0, 1), + new Vec3d(0, 0, 1), + new Vec3d(0, 0, 1), + + + /*new Vec3d(0, 1, 0), + new Vec3d(0, -1, 0), + new Vec3d(0, 0, 1), + new Vec3d(0, 0, -1), + new Vec3d(-1, 0, 0), + new Vec3d(1, 0, 0)*/ + }; + + private static final IParticleRenderType renderType = new IParticleRenderType() { + @Override + public void beginRender(BufferBuilder builder, TextureManager textureManager) { + RenderSystem.disableTexture(); + + //transparent, additive blending + //RenderSystem.depthMask(false); + //RenderSystem.enableBlend(); + //RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE); + //RenderSystem.enableLighting(); + + //opaque + RenderSystem.depthMask(true); + RenderSystem.disableBlend(); + RenderSystem.enableLighting(); + + builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); + } + + @Override + public void finishRender(Tessellator tessellator) { + tessellator.draw(); + RenderSystem.enableTexture(); + } + }; + + protected float scale; + + public CubeParticle(World world, double x, double y, double z, double motionX, double motionY, double motionZ) { + super(world, x, y, z); + this.motionX = motionX; + this.motionY = motionY; + this.motionZ = motionZ; + + setScale(0.2F); + } + + public void setScale(float scale) { + this.scale = scale; + this.setSize(scale, scale); + } + + public void averageAge(int age) { + this.maxAge = (int) (age + (rand.nextDouble() * 2D - 1D) * 8); + } + + @Override + public void buildGeometry(IVertexBuilder builder, ActiveRenderInfo renderInfo, float p_225606_3_) { + Vec3d projectedView = renderInfo.getProjectedView(); + float lerpedX = (float)(MathHelper.lerp(p_225606_3_, this.prevPosX, this.posX) - projectedView.getX()); + float lerpedY = (float)(MathHelper.lerp(p_225606_3_, this.prevPosY, this.posY) - projectedView.getY()); + float lerpedZ = (float)(MathHelper.lerp(p_225606_3_, this.prevPosZ, this.posZ) - projectedView.getZ()); + + //int light = getBrightnessForRender(p_225606_3_); + int light = 15728880;//15<<20 && 15<<4 + double ageMultiplier = 1 - Math.pow(age, 3) / Math.pow(maxAge, 3); + + for (int i = 0; i < 6; i++) { + //6 faces to a cube + for (int j = 0; j < 4; j++) { + Vec3d vec = CUBE[i * 4 + j]; + vec = vec + /*.rotate(?)*/ + .scale(scale * ageMultiplier) + .add(lerpedX, lerpedY, lerpedZ); + + Vec3d normal = CUBE_NORMALS[i]; + builder.vertex(vec.x, vec.y, vec.z).color(particleRed, particleGreen, particleBlue, particleAlpha).texture(0,0).light(light).normal((float)normal.x,(float) normal.y,(float) normal.z).endVertex(); + } + } + } + + @Override + public IParticleRenderType getRenderType() { + return renderType; + } + + public static class Factory implements IParticleFactory { + + public Factory() {} + + @Override + public Particle makeParticle(CubeParticleData data, World world, double x, double y, double z, double motionX, double motionY, double motionZ) { + CubeParticle particle = new CubeParticle(world, x, y, z, motionX, motionY, motionZ); + particle.setColor(data.r, data.g, data.b); + particle.setScale(data.scale); + particle.averageAge(data.avgAge); + return particle; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticleData.java b/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticleData.java new file mode 100644 index 000000000..fc198fd2e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticleData.java @@ -0,0 +1,83 @@ +package com.simibubi.create.content.contraptions.particle; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.simibubi.create.AllParticleTypes; +import net.minecraft.client.particle.ParticleManager; +import net.minecraft.network.PacketBuffer; +import net.minecraft.particles.IParticleData; +import net.minecraft.particles.ParticleType; + +import java.util.Locale; + +public class CubeParticleData implements IParticleData, ICustomParticle { + + public static final IParticleData.IDeserializer DESERIALIZER = new IParticleData.IDeserializer() { + @Override + public CubeParticleData deserialize(ParticleType type, StringReader reader) throws CommandSyntaxException { + reader.expect(' '); + float r = reader.readFloat(); + reader.expect(' '); + float g = reader.readFloat(); + reader.expect(' '); + float b = reader.readFloat(); + reader.expect(' '); + float scale = reader.readFloat(); + reader.expect(' '); + int avgAge = reader.readInt(); + return new CubeParticleData(r, g, b, scale, avgAge); + } + + @Override + public CubeParticleData read(ParticleType type, PacketBuffer buffer) { + return new CubeParticleData(buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readInt()); + } + }; + + final float r; + final float g; + final float b; + final float scale; + final int avgAge; + + public CubeParticleData(float r, float g, float b, float scale, int avgAge) { + this.r = r; + this.g = g; + this.b = b; + this.scale = scale; + this.avgAge = avgAge; + } + + public static CubeParticleData dummy() { + return new CubeParticleData(0, 0, 0, 0, 0); + } + + @Override + public IDeserializer getDeserializer() { + return DESERIALIZER; + } + + @Override + public ParticleManager.IParticleMetaFactory getFactory() { + return null; + } + + @Override + public ParticleType getType() { + return AllParticleTypes.CUBE.get(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeFloat(r); + buffer.writeFloat(g); + buffer.writeFloat(b); + buffer.writeFloat(scale); + buffer.writeInt(avgAge); + } + + @Override + public String getParameters() { + return String.format(Locale.ROOT, "%s %f %f %f %f %d", AllParticleTypes.CUBE.parameter(), r, g, b, scale, avgAge); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/HeaterBlock.java b/src/main/java/com/simibubi/create/content/contraptions/processing/HeaterBlock.java index 9013dabcf..f5721df2e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/HeaterBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/HeaterBlock.java @@ -7,18 +7,20 @@ import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.utility.Lang; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BlockItemUseContext; -import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.state.EnumProperty; import net.minecraft.state.IProperty; -import net.minecraft.state.IntegerProperty; import net.minecraft.state.StateContainer.Builder; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ActionResultType; import net.minecraft.util.Hand; +import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.MathHelper; @@ -31,11 +33,12 @@ import net.minecraft.world.World; @ParametersAreNonnullByDefault public class HeaterBlock extends Block implements ITE { - public static IProperty BLAZE_LEVEL = IntegerProperty.create("blaze_level", 0, 4); + //public static IProperty BLAZE_LEVEL = IntegerProperty.create("blaze_level", 0, 4); + public static IProperty BLAZE_LEVEL = EnumProperty.create("blaze", HeatLevel.class); public HeaterBlock(Properties properties) { super(properties); - setDefaultState(super.getDefaultState().with(BLAZE_LEVEL, 0)); + setDefaultState(super.getDefaultState().with(BLAZE_LEVEL, HeatLevel.NONE)); } @Override @@ -46,7 +49,7 @@ public class HeaterBlock extends Block implements ITE { @Override public boolean hasTileEntity(BlockState state) { - return state.get(BLAZE_LEVEL) >= 1; + return state.get(BLAZE_LEVEL).min(HeatLevel.SMOULDERING); } @Nullable @@ -61,28 +64,36 @@ public class HeaterBlock extends Block implements ITE { } @Override - public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, - BlockRayTraceResult blockRayTraceResult) { + public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult blockRayTraceResult) { if (!hasTileEntity(state)) return ActionResultType.PASS; + TileEntity te = world.getTileEntity(pos); - if (te instanceof HeaterTileEntity && ((HeaterTileEntity) te).tryUpdateFuel(player.getHeldItem(hand), player)) { - if (!player.isCreative()) - player.getHeldItem(hand) - .shrink(1); - return ActionResultType.SUCCESS; - } - return ActionResultType.PASS; + if (!(te instanceof HeaterTileEntity)) + return ActionResultType.PASS; + + if (!((HeaterTileEntity) te).tryUpdateFuel(player.getHeldItem(hand), player)) + return ActionResultType.PASS; + + if (!player.isCreative()) + player.getHeldItem(hand).shrink(1); + + return ActionResultType.SUCCESS; } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - ItemStack item = context.getItem(); - BlockState state = super.getStateForPlacement(context); - return (state != null ? state : getDefaultState()).with(BLAZE_LEVEL, - (item.hasTag() && item.getTag() != null && item.getTag() - .contains("has_blaze") && item.getTag() - .getBoolean("has_blaze")) ? 1 : 0); + if (!context.getItem().hasTag()) + return getDefaultState(); + + CompoundNBT tag = context.getItem().getTag(); + if (!tag.contains("has_blaze")) + return getDefaultState(); + + if (tag.getBoolean("has_blaze")) + return getDefaultState().with(BLAZE_LEVEL, HeatLevel.SMOULDERING); + + return getDefaultState(); } @Override @@ -91,16 +102,43 @@ public class HeaterBlock extends Block implements ITE { } @Override - public int getLightValue(BlockState state, IBlockReader world, BlockPos pos) { - return MathHelper.clamp(state.get(BLAZE_LEVEL) * 4 - 1, 0, 15); + public VoxelShape getCollisionShape(BlockState p_220071_1_, IBlockReader p_220071_2_, BlockPos p_220071_3_, ISelectionContext p_220071_4_) { + if (p_220071_4_ == ISelectionContext.dummy()) + return AllShapes.HEATER_BLOCK_SPECIAL_COLLISION_SHAPE; + + return super.getShape(p_220071_1_, p_220071_2_, p_220071_3_, p_220071_4_); } - static void setBlazeLevel(@Nullable World world, BlockPos pos, int blazeLevel) { + @Override + public int getLightValue(BlockState state, IBlockReader world, BlockPos pos) { + return MathHelper.clamp(state.get(BLAZE_LEVEL).ordinal() * 4 - 1, 0, 15); + } + + static void setBlazeLevel(@Nullable World world, BlockPos pos, HeatLevel blazeLevel) { if (world != null) world.setBlockState(pos, world.getBlockState(pos).with(BLAZE_LEVEL, blazeLevel)); } - public static int getHeaterLevel(BlockState blockState) { - return blockState.has(HeaterBlock.BLAZE_LEVEL) ? blockState.get(HeaterBlock.BLAZE_LEVEL) : 0; + public static HeatLevel getHeaterLevel(BlockState blockState) { + return blockState.has(HeaterBlock.BLAZE_LEVEL) ? blockState.get(HeaterBlock.BLAZE_LEVEL) : HeatLevel.NONE; + } + + public enum HeatLevel implements IStringSerializable { + NONE, + SMOULDERING, + FADING, + KINDLED, + SEETHING, + //if you think you have better names let me know :) + ; + + @Override + public String getName() { + return Lang.asId(name()); + } + + public boolean min(HeatLevel heatLevel) { + return this.ordinal() >= heatLevel.ordinal(); + } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/HeaterRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/processing/HeaterRenderer.java index 67cb923d4..bb4750280 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/HeaterRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/HeaterRenderer.java @@ -16,13 +16,13 @@ import java.util.HashMap; public class HeaterRenderer extends SafeTileEntityRenderer { private static final Minecraft INSTANCE = Minecraft.getInstance(); - private static final HashMap blazeModelMap = new HashMap<>(); + private static final HashMap blazeModelMap = new HashMap<>(); public HeaterRenderer(TileEntityRendererDispatcher dispatcher) { super(dispatcher); - blazeModelMap.put(2, AllBlockPartials.BLAZE_HEATER_BLAZE_TWO); - blazeModelMap.put(3, AllBlockPartials.BLAZE_HEATER_BLAZE_THREE); - blazeModelMap.put(4, AllBlockPartials.BLAZE_HEATER_BLAZE_FOUR); + blazeModelMap.put(HeaterBlock.HeatLevel.FADING, AllBlockPartials.BLAZE_HEATER_BLAZE_TWO); + blazeModelMap.put(HeaterBlock.HeatLevel.KINDLED, AllBlockPartials.BLAZE_HEATER_BLAZE_THREE); + blazeModelMap.put(HeaterBlock.HeatLevel.SEETHING, AllBlockPartials.BLAZE_HEATER_BLAZE_FOUR); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/HeaterTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/processing/HeaterTileEntity.java index 2aea9afb3..03614594b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/HeaterTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/HeaterTileEntity.java @@ -5,56 +5,75 @@ import java.util.Random; import com.simibubi.create.AllItems; import com.simibubi.create.content.contraptions.components.deployer.DeployerFakePlayer; -import com.simibubi.create.content.contraptions.particle.HeaterParticleData; +import com.simibubi.create.content.contraptions.particle.CubeParticleData; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; - +import com.simibubi.create.foundation.utility.ColorHelper; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.projectile.EggEntity; import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.tileentity.TileEntity; import net.minecraft.particles.IParticleData; -import net.minecraft.particles.ParticleTypes; import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.event.entity.ProjectileImpactEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +@Mod.EventBusSubscriber public class HeaterTileEntity extends SmartTileEntity { - private int fuelLevel; - private int burnTimeRemaining; + + private final static int[][] heatParticleColors = { + {0x3B141A, 0x47141A, 0x7A3B24, 0x854D26}, + {0x2A0103, 0x741B0A, 0xC38246, 0xCCBD78}, + {0x630B03, 0x8B3503, 0xBC8200, 0xCCC849}, + {0x1C6378, 0x4798B5, 0x4DA6C0, 0xBAC8CE} + }; + private static final int maxHeatCapacity = 10000; + private int remainingBurnTime; + private FuelType activeFuel; + public HeaterTileEntity(TileEntityType tileEntityTypeIn) { super(tileEntityTypeIn); - fuelLevel = 0; - burnTimeRemaining = 0; - setLazyTickRate(20); + activeFuel = FuelType.NONE; + remainingBurnTime = 0; + setLazyTickRate(40); } @Override public void tick() { super.tick(); - if (burnTimeRemaining > 0) { - burnTimeRemaining--; - if (burnTimeRemaining <= 0 && fuelLevel > 1) { - fuelLevel--; - burnTimeRemaining = maxHeatCapacity / 2; - } - updateHeatLevel(); - markDirty(); + + spawnParticles(getHeatLevel()); + + if (remainingBurnTime <= 0) { + return; } + remainingBurnTime--; + if (remainingBurnTime == 0) + if (activeFuel == FuelType.SPECIAL) { + activeFuel = FuelType.NORMAL; + remainingBurnTime = maxHeatCapacity / 2; + updateHeatLevel(); + } else { + activeFuel = FuelType.NONE; + updateHeatLevel(); + } + markDirty(); } @Override public void lazyTick() { super.lazyTick(); - spawnParticles(ParticleTypes.SMOKE); - int heatLevel = getHeatLevel(); - if (heatLevel >= 2) - spawnParticles(ParticleTypes.FLAME); - if (heatLevel > 3) { - spawnParticles(new HeaterParticleData(0.3f, 0.3f, 1f)); - } + //using lazy ticks to transition between kindled and fading, this doesn't need to happen instantly at the threshold + updateHeatLevel(); } @Override @@ -62,62 +81,148 @@ public class HeaterTileEntity extends SmartTileEntity { @Override public CompoundNBT write(CompoundNBT compound) { - compound.putInt("fuelLevel", fuelLevel); - compound.putInt("burnTimeRemaining", burnTimeRemaining); + compound.putInt("fuelLevel", activeFuel.ordinal()); + compound.putInt("burnTimeRemaining", remainingBurnTime); return super.write(compound); } @Override public void read(CompoundNBT compound) { - fuelLevel = compound.getInt("fuelLevel"); - burnTimeRemaining = compound.getInt("burnTimeRemaining"); + activeFuel = FuelType.values()[compound.getInt("fuelLevel")]; + remainingBurnTime = compound.getInt("burnTimeRemaining"); super.read(compound); - if (fuelLevel == 0) - burnTimeRemaining = 0; updateHeatLevel(); } + /** + * @return true if the heater updated its burn time and a item should be consumed + */ boolean tryUpdateFuel(ItemStack itemStack, PlayerEntity player) { - boolean specialFuelUsed = itemStack.getItem() == AllItems.FUEL_PELLET.get(); - int burnTime = - itemStack.getItem() == Items.EGG ? 150 : (specialFuelUsed ? 1000 : ForgeHooks.getBurnTime(itemStack)); - int newFuelLevel = (specialFuelUsed ? 2 : 1); - if (burnTime <= 0 || newFuelLevel < fuelLevel) - return false; - if (newFuelLevel > this.fuelLevel) { - fuelLevel = newFuelLevel; - burnTimeRemaining = burnTime; - } else { - if (burnTimeRemaining + burnTime > maxHeatCapacity && player instanceof DeployerFakePlayer) - return false; - burnTimeRemaining = MathHelper.clamp(burnTimeRemaining + burnTime, 0, maxHeatCapacity); + FuelType newFuel = FuelType.NONE; + int burnTick = ForgeHooks.getBurnTime(itemStack); + if (burnTick > 0) + newFuel = FuelType.NORMAL; + if (itemStack.getItem() == AllItems.FUEL_PELLET.get()) { + burnTick = 1000; + newFuel = FuelType.SPECIAL; } + + if (newFuel == FuelType.NONE || newFuel.ordinal() < activeFuel.ordinal()) + return false; + + if (newFuel == activeFuel) { + if (remainingBurnTime + burnTick > maxHeatCapacity && player instanceof DeployerFakePlayer) + return false; + + remainingBurnTime = MathHelper.clamp(remainingBurnTime + burnTick, 0, maxHeatCapacity); + } else { + activeFuel = newFuel; + remainingBurnTime = burnTick; + } + updateHeatLevel(); return true; } - public int getHeatLevel() { + public HeaterBlock.HeatLevel getHeatLevel() { return HeaterBlock.getHeaterLevel(getBlockState()); } private void updateHeatLevel() { - if (fuelLevel == 2) - HeaterBlock.setBlazeLevel(world, pos, 4); - else if (fuelLevel == 0 || burnTimeRemaining <= 0) - HeaterBlock.setBlazeLevel(world, pos, 1); - else { - HeaterBlock.setBlazeLevel(world, pos, (double) burnTimeRemaining / maxHeatCapacity > 0.1 ? 3 : 2); + switch (activeFuel) { + case SPECIAL: + HeaterBlock.setBlazeLevel(world, pos, HeaterBlock.HeatLevel.SEETHING); + break; + case NORMAL: + boolean lowPercent = (double) remainingBurnTime / maxHeatCapacity < 0.1; + HeaterBlock.setBlazeLevel(world, pos, lowPercent ? HeaterBlock.HeatLevel.FADING : HeaterBlock.HeatLevel.KINDLED); + break; + case NONE: + HeaterBlock.setBlazeLevel(world, pos, HeaterBlock.HeatLevel.SMOULDERING); } } - private void spawnParticles(IParticleData basicparticletype) { + private void spawnParticles(HeaterBlock.HeatLevel heatLevel) { if (world == null) return; + + if (heatLevel == HeaterBlock.HeatLevel.NONE) + return; + + Random r = world.getRandom(); + if (heatLevel == HeaterBlock.HeatLevel.SMOULDERING) { + if (r.nextDouble() > 0.25) + return; + + Vec3d color = randomColor(heatLevel); + spawnParticle(new CubeParticleData((float) color.x,(float) color.y,(float) color.z, 0.03F, 15), 0.015, 0.1); + } else if (heatLevel == HeaterBlock.HeatLevel.FADING) { + if (r.nextDouble() > 0.5) + return; + + Vec3d color = randomColor(heatLevel); + spawnParticle(new CubeParticleData((float) color.x,(float) color.y,(float) color.z, 0.035F, 18), 0.03, 0.15); + } else if (heatLevel == HeaterBlock.HeatLevel.KINDLED) { + Vec3d color = randomColor(heatLevel); + spawnParticle(new CubeParticleData((float) color.x,(float) color.y,(float) color.z, 0.04F, 21), 0.05, 0.2); + }else if (heatLevel == HeaterBlock.HeatLevel.SEETHING) { + for (int i = 0; i < 2; i++) { + if (r.nextDouble() > 0.6) + return; + Vec3d color = randomColor(heatLevel); + spawnParticle(new CubeParticleData((float) color.x,(float) color.y,(float) color.z, 0.045F, 24), 0.06, 0.22); + } + } + } + + private void spawnParticle(IParticleData particleData, double speed, double spread) { Random random = world.getRandom(); - world.addOptionalParticle(basicparticletype, true, - (double) pos.getX() + 0.5D + random.nextDouble() / 3.0D * (double) (random.nextBoolean() ? 1 : -1), - (double) pos.getY() + random.nextDouble() + random.nextDouble(), - (double) pos.getZ() + 0.5D + random.nextDouble() / 3.0D * (double) (random.nextBoolean() ? 1 : -1), 0.0D, - 0.07D, 0.0D); + + world.addOptionalParticle( + particleData, + (double) pos.getX() + 0.5D + (random.nextDouble() * 2.0 - 1D) * spread, + (double) pos.getY() + 0.6D + random.nextDouble() / 10.0, + (double) pos.getZ() + 0.5D + (random.nextDouble() * 2.0 - 1D) * spread, + 0.0D, + speed, + 0.0D); + } + + private static Vec3d randomColor(HeaterBlock.HeatLevel heatLevel) { + if (heatLevel == HeaterBlock.HeatLevel.NONE) + return new Vec3d(0,0,0); + + return ColorHelper.getRGB(heatParticleColors[heatLevel.ordinal()-1][(int) (Math.random()*4)]); + } + + @SubscribeEvent + public static void eggsGetEaten(ProjectileImpactEvent.Throwable event) { + if (!(event.getThrowable() instanceof EggEntity)) + return; + + if (event.getRayTraceResult().getType() != RayTraceResult.Type.BLOCK) + return; + + TileEntity tile = event.getThrowable().world.getTileEntity(new BlockPos(event.getRayTraceResult().getHitVec())); + if (!(tile instanceof HeaterTileEntity)) { + return; + } + + event.setCanceled(true); + event.getThrowable().setMotion(Vec3d.ZERO); + event.getThrowable().remove(); + + HeaterTileEntity heater = (HeaterTileEntity) tile; + if (heater.activeFuel != FuelType.SPECIAL) + heater.activeFuel = FuelType.NORMAL; + heater.remainingBurnTime = MathHelper.clamp(heater.remainingBurnTime + 80, 0, maxHeatCapacity); + heater.markDirty(); + + } + + private enum FuelType { + NONE, + NORMAL, + SPECIAL } } diff --git a/src/main/java/com/simibubi/create/content/logistics/InWorldProcessing.java b/src/main/java/com/simibubi/create/content/logistics/InWorldProcessing.java index b5abab707..ccae9be56 100644 --- a/src/main/java/com/simibubi/create/content/logistics/InWorldProcessing.java +++ b/src/main/java/com/simibubi/create/content/logistics/InWorldProcessing.java @@ -7,6 +7,7 @@ import java.util.Optional; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.content.contraptions.components.fan.SplashingRecipe; +import com.simibubi.create.content.contraptions.processing.HeaterBlock; import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; import com.simibubi.create.foundation.config.AllConfigs; @@ -62,9 +63,9 @@ public class InWorldProcessing { if (fluidState.getFluid() == Fluids.WATER || fluidState.getFluid() == Fluids.FLOWING_WATER) return Type.SPLASHING; if (blockState.getBlock() == Blocks.FIRE - || (blockState.getBlock() == Blocks.CAMPFIRE && blockState.get(CampfireBlock.LIT)) || getHeaterLevel(blockState) == 1) + || (blockState.getBlock() == Blocks.CAMPFIRE && blockState.get(CampfireBlock.LIT)) || getHeaterLevel(blockState) == HeaterBlock.HeatLevel.SMOULDERING) return Type.SMOKING; - if (blockState.getBlock() == Blocks.LAVA || getHeaterLevel(blockState) >= 2) + if (blockState.getBlock() == Blocks.LAVA || getHeaterLevel(blockState).min(HeaterBlock.HeatLevel.FADING)) return Type.BLASTING; return null; } diff --git a/src/main/resources/assets/create/particles/cube.json b/src/main/resources/assets/create/particles/cube.json new file mode 100644 index 000000000..0e0dcd235 --- /dev/null +++ b/src/main/resources/assets/create/particles/cube.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file