From c7b6be2e81380eafd48ed89de573e482a7ce9843 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Mon, 30 May 2022 18:43:30 +0200 Subject: [PATCH] Blazier Reworks - Integrated new Blaze Burner assets by Kryppers - Blaze burners now render independently when on a contraption --- .../com/simibubi/create/AllBlockPartials.java | 17 +- .../java/com/simibubi/create/AllBlocks.java | 2 + .../java/com/simibubi/create/AllShapes.java | 3 +- .../com/simibubi/create/AllSpriteShifts.java | 8 +- .../animations/AnimatedBlazeBurner.java | 63 +- .../processing/burner/BlazeBurnerBlock.java | 30 +- .../burner/BlazeBurnerMovementBehaviour.java | 125 ++++ .../burner/BlazeBurnerRenderer.java | 128 +++- .../burner/BlazeBurnerTileEntity.java | 195 +++--- .../logistics/trains/TrackGraphSync.java | 2 +- .../entity/CarriageContraptionEntity.java | 2 +- .../foundation/data/BuilderTransformers.java | 1 + .../foundation/render/SuperByteBuffer.java | 48 +- .../blaze/{kindled.json => active.json} | 4 +- .../block/blaze_burner/blaze/fading.json | 23 - .../models/block/blaze_burner/blaze/idle.json | 23 + .../block/blaze_burner/blaze/smouldering.json | 22 - .../blaze/{seething.json => super.json} | 2 +- .../models/block/blaze_burner/blaze_cage.mtl | 14 + .../models/block/blaze_burner/blaze_cage.obj | 300 +++++++++ .../models/block/blaze_burner/blaze_flame.mtl | 13 + .../models/block/blaze_burner/blaze_flame.obj | 170 +++++ .../models/block/blaze_burner/blaze_rods.mtl | 14 + .../block/blaze_burner/blaze_rods_large.obj | 148 ++++ .../block/blaze_burner/blaze_rods_small.obj | 148 ++++ .../models/block/blaze_burner/block.json | 175 +---- .../block/blaze_burner/block_with_blaze.json | 198 +----- .../block/blaze_burner/block_with_fire.json | 205 +----- .../blaze_burner/block_with_soul_fire.json | 9 +- .../models/block/blaze_burner/campfire.mtl | 25 + .../models/block/blaze_burner/campfire.obj | 343 ++++++++++ .../models/block/blaze_burner/flame.json | 9 + .../models/block/blaze_burner/goggles.json | 19 + .../create/models/block/blaze_burner/item.mtl | 26 + .../create/models/block/blaze_burner/item.obj | 634 ++++++++++++++++++ .../models/block/blaze_burner/rods_large.json | 9 + .../models/block/blaze_burner/rods_small.json | 9 + .../blaze_burner/superheated_rods_large.json | 9 + .../blaze_burner/superheated_rods_small.json | 9 + .../create/textures/block/blaze_active.png | Bin 0 -> 320 bytes .../textures/block/blaze_burner_flame.png | Bin 0 -> 217 bytes .../block/blaze_burner_flame_scroll.png | Bin 0 -> 249 bytes .../blaze_burner_flame_superheated_scroll.png | Bin 0 -> 255 bytes .../textures/block/blaze_burner_inner.png | Bin 423 -> 0 bytes .../textures/block/blaze_burner_side.png | Bin 262 -> 0 bytes .../textures/block/blaze_heater_brazier.png | Bin 711 -> 483 bytes .../block/blaze_heater_brazier_soul.png | Bin 0 -> 7887 bytes .../{blaze_kindled.png => blaze_idle.png} | Bin .../textures/block/blaze_smouldering.png | Bin 323 -> 0 bytes .../{blaze_seething.png => blaze_super.png} | Bin .../assets/create/textures/block/hat_test.png | Bin 0 -> 831 bytes 51 files changed, 2446 insertions(+), 738 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerMovementBehaviour.java rename src/main/resources/assets/create/models/block/blaze_burner/blaze/{kindled.json => active.json} (87%) delete mode 100644 src/main/resources/assets/create/models/block/blaze_burner/blaze/fading.json create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/blaze/idle.json delete mode 100644 src/main/resources/assets/create/models/block/blaze_burner/blaze/smouldering.json rename src/main/resources/assets/create/models/block/blaze_burner/blaze/{seething.json => super.json} (93%) create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/blaze_cage.mtl create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/blaze_cage.obj create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/blaze_flame.mtl create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/blaze_flame.obj create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/blaze_rods.mtl create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/blaze_rods_large.obj create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/blaze_rods_small.obj create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/campfire.mtl create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/campfire.obj create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/flame.json create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/goggles.json create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/item.mtl create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/item.obj create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/rods_large.json create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/rods_small.json create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/superheated_rods_large.json create mode 100644 src/main/resources/assets/create/models/block/blaze_burner/superheated_rods_small.json create mode 100644 src/main/resources/assets/create/textures/block/blaze_active.png create mode 100644 src/main/resources/assets/create/textures/block/blaze_burner_flame.png create mode 100644 src/main/resources/assets/create/textures/block/blaze_burner_flame_scroll.png create mode 100644 src/main/resources/assets/create/textures/block/blaze_burner_flame_superheated_scroll.png delete mode 100644 src/main/resources/assets/create/textures/block/blaze_burner_inner.png delete mode 100644 src/main/resources/assets/create/textures/block/blaze_burner_side.png create mode 100644 src/main/resources/assets/create/textures/block/blaze_heater_brazier_soul.png rename src/main/resources/assets/create/textures/block/{blaze_kindled.png => blaze_idle.png} (100%) delete mode 100644 src/main/resources/assets/create/textures/block/blaze_smouldering.png rename src/main/resources/assets/create/textures/block/{blaze_seething.png => blaze_super.png} (100%) create mode 100644 src/main/resources/assets/create/textures/block/hat_test.png diff --git a/src/main/java/com/simibubi/create/AllBlockPartials.java b/src/main/java/com/simibubi/create/AllBlockPartials.java index 3ba6dbdbe..f2e6c1647 100644 --- a/src/main/java/com/simibubi/create/AllBlockPartials.java +++ b/src/main/java/com/simibubi/create/AllBlockPartials.java @@ -6,7 +6,6 @@ import java.util.Map; import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; @@ -137,10 +136,17 @@ public class AllBlockPartials { SIGNAL_RED = block("track_signal/red_tube"), SIGNAL_YELLOW_CUBE = block("track_signal/yellow_cube"), SIGNAL_YELLOW_GLOW = block("track_signal/yellow_glow"), SIGNAL_YELLOW = block("track_signal/yellow_tube"), + BLAZE_GOGGLES = block("blaze_burner/goggles"), + BLAZE_IDLE = block("blaze_burner/blaze/idle"), BLAZE_ACTIVE = block("blaze_burner/blaze/active"), + BLAZE_SUPER = block("blaze_burner/blaze/super"), BLAZE_BURNER_FLAME = block("blaze_burner/flame"), + BLAZE_BURNER_RODS = block("blaze_burner/rods_small"), BLAZE_BURNER_RODS_2 = block("blaze_burner/rods_large"), + BLAZE_BURNER_SUPER_RODS = block("blaze_burner/superheated_rods_small"), + BLAZE_BURNER_SUPER_RODS_2 = block("blaze_burner/superheated_rods_large"), + WHISTLE_MOUTH_LARGE = block("steam_whistle/large_mouth"), WHISTLE_MOUTH_MEDIUM = block("steam_whistle/medium_mouth"), WHISTLE_MOUTH_SMALL = block("steam_whistle/small_mouth"), - + CRAFTING_BLUEPRINT_1x1 = entity("crafting_blueprint_small"), CRAFTING_BLUEPRINT_2x2 = entity("crafting_blueprint_medium"), CRAFTING_BLUEPRINT_3x3 = entity("crafting_blueprint_large"), @@ -155,8 +161,6 @@ public class AllBlockPartials { public static final Map> PIPE_ATTACHMENTS = new EnumMap<>(FluidTransportBehaviour.AttachmentTypes.class); - public static final Map BLAZES = - new EnumMap<>(BlazeBurnerBlock.HeatLevel.class); public static final Map METAL_GIRDER_BRACKETS = new EnumMap<>(Direction.class); public static final Map TOOLBOX_LIDS = new EnumMap<>(DyeColor.class); @@ -171,11 +175,6 @@ public class AllBlockPartials { } PIPE_ATTACHMENTS.put(type, map); } - for (BlazeBurnerBlock.HeatLevel heat : BlazeBurnerBlock.HeatLevel.values()) { - if (heat == BlazeBurnerBlock.HeatLevel.NONE) - continue; - BLAZES.put(heat, block("blaze_burner/blaze/" + heat.getSerializedName())); - } for (DyeColor color : DyeColor.values()) TOOLBOX_LIDS.put(color, block("toolbox/lid/" + Lang.asId(color.name()))); for (Direction d : Iterate.horizontalDirections) diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 14d006c72..7a9a910b9 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -104,6 +104,7 @@ import com.simibubi.create.content.contraptions.processing.BasinMovementBehaviou import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlockItem; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerInteractionBehaviour; +import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerMovementBehaviour; import com.simibubi.create.content.contraptions.processing.burner.LitBlazeBurnerBlock; import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock; import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlock; @@ -632,6 +633,7 @@ public class AllBlocks { .tag(AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.FAN_HEATERS.tag) .loot((lt, block) -> lt.add(block, BlazeBurnerBlock.buildLootTable())) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) + .onRegister(addMovementBehaviour(new BlazeBurnerMovementBehaviour())) .onRegister(addInteractionBehaviour(new BlazeBurnerInteractionBehaviour())) .item(BlazeBurnerBlockItem::withBlaze) .model(AssetLookup.customBlockItemModel("blaze_burner", "block_with_blaze")) diff --git a/src/main/java/com/simibubi/create/AllShapes.java b/src/main/java/com/simibubi/create/AllShapes.java index f61c0764c..750dc55d5 100644 --- a/src/main/java/com/simibubi/create/AllShapes.java +++ b/src/main/java/com/simibubi/create/AllShapes.java @@ -205,8 +205,7 @@ public class AllShapes { SPEED_CONTROLLER = shape(0, 0, 0, 16, 4, 16).add(1, 1, 1, 15, 13, 15) .add(0, 8, 0, 16, 14, 16) .build(), - HEATER_BLOCK_SHAPE = shape(2, 0, 2, 14, 14, 14).add(0, 0, 0, 16, 4, 16) - .build(), + HEATER_BLOCK_SHAPE = shape(1, 0, 1, 15, 14, 15).build(), HEATER_BLOCK_SPECIAL_COLLISION_SHAPE = shape(0, 0, 0, 16, 4, 16).build(), CRUSHING_WHEEL_COLLISION_SHAPE = cuboid(0, 0, 0, 16, 16, 16), SEAT = cuboid(0, 0, 0, 16, 8, 16), SEAT_COLLISION = cuboid(0, 0, 0, 16, 6, 16), diff --git a/src/main/java/com/simibubi/create/AllSpriteShifts.java b/src/main/java/com/simibubi/create/AllSpriteShifts.java index 071e09d87..7ef3b44ae 100644 --- a/src/main/java/com/simibubi/create/AllSpriteShifts.java +++ b/src/main/java/com/simibubi/create/AllSpriteShifts.java @@ -25,6 +25,11 @@ public class AllSpriteShifts { public static final Map DYED_BELTS = new IdentityHashMap<>(), DYED_OFFSET_BELTS = new IdentityHashMap<>(), DYED_DIAGONAL_BELTS = new IdentityHashMap<>(); + public static final SpriteShiftEntry BURNER_FLAME = + SpriteShifter.get("block/blaze_burner_flame", "block/blaze_burner_flame_scroll"), + SUPER_BURNER_FLAME = + SpriteShifter.get("block/blaze_burner_flame", "block/blaze_burner_flame_superheated_scroll"); + public static final CTSpriteShiftEntry FRAMED_GLASS = getCT(OMNIDIRECTIONAL, "palettes/framed_glass", "palettes/framed_glass"), HORIZONTAL_FRAMED_GLASS = @@ -51,8 +56,7 @@ public class AllSpriteShifts { CHASSIS_STICKY = omni("linear_chassis_end_sticky"); public static final CTSpriteShiftEntry BRASS_TUNNEL_TOP = vertical("brass_tunnel_top"), - FLUID_TANK = getCT(CTType.RECTANGLE, "fluid_tank"), - FLUID_TANK_TOP = getCT(CTType.RECTANGLE, "fluid_tank_top"), + FLUID_TANK = getCT(CTType.RECTANGLE, "fluid_tank"), FLUID_TANK_TOP = getCT(CTType.RECTANGLE, "fluid_tank_top"), CREATIVE_FLUID_TANK = getCT(CTType.CROSS, "creative_fluid_tank"); public static final Couple VAULT_TOP = vault("top"), VAULT_FRONT = vault("front"), diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java index 6ed5c54d5..3f76002bf 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java @@ -2,13 +2,22 @@ package com.simibubi.create.compat.jei.category.animations; import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.math.Vector3f; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.foundation.block.render.SpriteShiftEntry; +import com.simibubi.create.foundation.render.CachedBufferer; import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; import net.minecraft.util.Mth; +import net.minecraft.world.level.block.Blocks; public class AnimatedBlazeBurner extends AnimatedKinetics { @@ -26,19 +35,61 @@ public class AnimatedBlazeBurner extends AnimatedKinetics { matrixStack.mulPose(Vector3f.YP.rotationDegrees(22.5f)); int scale = 23; - blockElement(AllBlocks.BLAZE_BURNER.getDefaultState()) - .atLocal(0, 1.65, 0) + float offset = (Mth.sin(AnimationTickHolder.getRenderTime() / 16f) + 0.5f) / 16f; + + blockElement(AllBlocks.BLAZE_BURNER.getDefaultState()).atLocal(0, 1.65, 0) .scale(scale) .render(matrixStack); - float offset = (Mth.sin(AnimationTickHolder.getRenderTime() / 16f) + 0.5f) / 16f; - PartialModel blaze = AllBlockPartials.BLAZES.get(heatLevel); - blockElement(blaze) - .atLocal(1, 1.65 + offset, 1) + PartialModel blaze = + heatLevel == HeatLevel.SEETHING ? AllBlockPartials.BLAZE_SUPER : AllBlockPartials.BLAZE_ACTIVE; + PartialModel rods2 = heatLevel == HeatLevel.SEETHING ? AllBlockPartials.BLAZE_BURNER_SUPER_RODS_2 + : AllBlockPartials.BLAZE_BURNER_RODS_2; + + blockElement(blaze).atLocal(1, 1.8, 1) + .rotate(0, 180, 0) + .scale(scale) + .render(matrixStack); + blockElement(rods2).atLocal(1, 1.7 + offset, 1) .rotate(0, 180, 0) .scale(scale) .render(matrixStack); + matrixStack.scale(scale, -scale, scale); + matrixStack.translate(0, -1.8, 0); + + SpriteShiftEntry spriteShift = + heatLevel == HeatLevel.SEETHING ? AllSpriteShifts.SUPER_BURNER_FLAME : AllSpriteShifts.BURNER_FLAME; + + float spriteWidth = spriteShift.getTarget() + .getU1() + - spriteShift.getTarget() + .getU0(); + + float spriteHeight = spriteShift.getTarget() + .getV1() + - spriteShift.getTarget() + .getV0(); + + float time = AnimationTickHolder.getRenderTime(Minecraft.getInstance().level); + float speed = 1 / 32f + 1 / 64f * heatLevel.ordinal(); + + double vScroll = speed * time; + vScroll = vScroll - Math.floor(vScroll); + vScroll = vScroll * spriteHeight / 2; + + double uScroll = speed * time / 2; + uScroll = uScroll - Math.floor(uScroll); + uScroll = uScroll * spriteWidth / 2; + + Minecraft mc = Minecraft.getInstance(); + MultiBufferSource.BufferSource buffer = mc.renderBuffers() + .bufferSource(); + VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped()); + CachedBufferer.partial(AllBlockPartials.BLAZE_BURNER_FLAME, Blocks.AIR.defaultBlockState()) + .shiftUVScrolling(spriteShift, (float) uScroll, (float) vScroll) + .light(LightTexture.FULL_BRIGHT) + .renderInto(matrixStack, vb); matrixStack.popPose(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlock.java index 333458216..073850685 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlock.java @@ -35,6 +35,7 @@ import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.HorizontalDirectionalBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; @@ -57,7 +58,7 @@ import net.minecraftforge.common.util.FakePlayer; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class BlazeBurnerBlock extends Block implements ITE, IWrenchable { +public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements ITE, IWrenchable { public static final EnumProperty HEAT_LEVEL = EnumProperty.create("blaze", HeatLevel.class); @@ -69,7 +70,7 @@ public class BlazeBurnerBlock extends Block implements ITE builder) { super.createBlockStateDefinition(builder); - builder.add(HEAT_LEVEL); + builder.add(HEAT_LEVEL, FACING); } @Override @@ -111,8 +112,27 @@ public class BlazeBurnerBlock extends Block implements ITE { + if (bbte.goggles) + return InteractionResult.PASS; + bbte.goggles = true; + bbte.notifyUpdate(); + return InteractionResult.SUCCESS; + }); + + if (heldItem.isEmpty() && heat != HeatLevel.NONE) + return onTileEntityUse(world, pos, bbte -> { + if (!bbte.goggles) + return InteractionResult.PASS; + bbte.goggles = false; + bbte.notifyUpdate(); + return InteractionResult.SUCCESS; + }); + + if (heat == HeatLevel.NONE) { if (heldItem.getItem() instanceof FlintAndSteelItem) { world.playSound(player, pos, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, world.random.nextFloat() * 0.4F + 0.8F); @@ -180,7 +200,9 @@ public class BlazeBurnerBlock extends Block implements ITE { - public BlazeBurnerRenderer(BlockEntityRendererProvider.Context context) { - } + public BlazeBurnerRenderer(BlockEntityRendererProvider.Context context) {} @Override protected void renderSafe(BlazeBurnerTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, @@ -29,14 +39,112 @@ public class BlazeBurnerRenderer extends SafeTileEntityRenderer type, BlockPos pos, BlockState state) { super(type, pos, state); activeFuel = FuelType.NONE; remainingBurnTime = 0; + headAnimation = LerpedFloat.linear(); headAngle = LerpedFloat.angular(); isCreative = false; + goggles = false; + + headAngle.startWithValue((AngleHelper.horizontalAngle(state.getOptionalValue(BlazeBurnerBlock.FACING) + .orElse(Direction.SOUTH)) + 180) % 360); } public FuelType getActiveFuel() { @@ -74,7 +71,7 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { super.tick(); if (level.isClientSide) { - tickRotation(); + tickAnimation(); spawnParticles(getHeatLevelFromBlock(), 1); return; } @@ -99,26 +96,38 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { updateBlockState(); } - private void tickRotation() { - float target = 0; - LocalPlayer player = Minecraft.getInstance().player; - if (player != null) { - double x; - double z; - if (isVirtual()) { - x = -4; - z = -10; - } else { - x = player.getX(); - z = player.getZ(); + @OnlyIn(Dist.CLIENT) + private void tickAnimation() { + boolean active = getHeatLevelFromBlock().isAtLeast(HeatLevel.FADING); + + if (!active) { + float target = 0; + LocalPlayer player = Minecraft.getInstance().player; + if (player != null) { + double x; + double z; + if (isVirtual()) { + x = -4; + z = -10; + } else { + x = player.getX(); + z = player.getZ(); + } + double dx = x - (getBlockPos().getX() + 0.5); + double dz = z - (getBlockPos().getZ() + 0.5); + target = AngleHelper.deg(-Mth.atan2(dz, dx)) - 90; } - double dx = x - (getBlockPos().getX() + 0.5); - double dz = z - (getBlockPos().getZ() + 0.5); - target = AngleHelper.deg(-Mth.atan2(dz, dx)) - 90; + target = headAngle.getValue() + AngleHelper.getShortestAngleDiff(headAngle.getValue(), target); + headAngle.chase(target, .25f, Chaser.exp(5)); + headAngle.tickChaser(); + } else { + headAngle.chase((AngleHelper.horizontalAngle(getBlockState().getOptionalValue(BlazeBurnerBlock.FACING) + .orElse(Direction.SOUTH)) + 180) % 360, .125f, Chaser.EXP); + headAngle.tickChaser(); } - target = headAngle.getValue() + AngleHelper.getShortestAngleDiff(headAngle.getValue(), target); - headAngle.chase(target, .25f, Chaser.exp(5)); - headAngle.tickChaser(); + + headAnimation.chase(active ? 1 : 0, .25f, Chaser.exp(.25f)); + headAnimation.tickChaser(); } @Override @@ -129,9 +138,10 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { if (!isCreative) { compound.putInt("fuelLevel", activeFuel.ordinal()); compound.putInt("burnTimeRemaining", remainingBurnTime); - } else { + } else compound.putBoolean("isCreative", true); - } + if (goggles) + compound.putBoolean("Goggles", true); super.write(compound, clientPacket); } @@ -140,6 +150,7 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { activeFuel = FuelType.values()[compound.getInt("fuelLevel")]; remainingBurnTime = compound.getInt("burnTimeRemaining"); isCreative = compound.getBoolean("isCreative"); + goggles = compound.contains("Goggles"); super.read(compound, clientPacket); } @@ -203,34 +214,37 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { remainingBurnTime = newBurnTime; if (level.isClientSide) { - HeatLevel level = getHeatLevelFromFuelType(activeFuel); - for (int i = 0; i < 20; i++) - spawnParticles(level, 1 + (.25 * (i / 4))); - } else { - playSound(); - updateBlockState(); + spawnParticleBurst(activeFuel == FuelType.SPECIAL); + return true; } + HeatLevel prev = getHeatLevelFromBlock(); + playSound(); + updateBlockState(); + + if (prev != getHeatLevelFromBlock()) + level.playSound(null, worldPosition, SoundEvents.BLAZE_AMBIENT, SoundSource.BLOCKS, + .125f + level.random.nextFloat() * .125f, 1.15f - level.random.nextFloat() * .25f); + return true; } protected void applyCreativeFuel() { - boolean wasCreative = isCreative; - activeFuel = FuelType.NONE; remainingBurnTime = 0; isCreative = true; + HeatLevel next = getHeatLevelFromBlock().nextActiveLevel(); + if (level.isClientSide) { - for (int i = 0; i < 30; i++) { - double burstMult = 1 + (.25 * (i / 4)); - spawnParticle(CREATIVE_PARTICLE_COLORS, 0.04F, 35, false, 0.03 * burstMult, 0.15 * burstMult); - } - } else { - playSound(); - if (wasCreative) - setBlockHeat(getHeatLevelFromBlock().nextActiveLevel()); + spawnParticleBurst(next.isAtLeast(HeatLevel.SEETHING)); + return; } + + playSound(); + if (next == HeatLevel.FADING) + next = next.nextActiveLevel(); + setBlockHeat(next); } public boolean isCreativeFuel(ItemStack stack) { @@ -266,50 +280,49 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { return; Random r = level.getRandom(); - switch (heatLevel) { - case SMOULDERING: - if (r.nextDouble() > 0.25) - return; - spawnParticle(heatLevel, 0.03F, 15, false, 0.015 * burstMult, 0.1 * burstMult); - break; - case FADING: - if (r.nextDouble() > 0.5) - return; - spawnParticle(heatLevel, 0.035F, 18, false, 0.03 * burstMult, 0.15 * burstMult); - break; - case KINDLED: - spawnParticle(heatLevel, 0.04F, 35, true, 0.05 * burstMult, 0.2 * burstMult); - break; - case SEETHING: - for (int i = 0; i < 2; i++) { - if (r.nextDouble() > 0.6) - return; - spawnParticle(heatLevel, 0.045F, 35, true, 0.06 * burstMult, 0.22 * burstMult); - } - break; - default: - break; - } - } - protected void spawnParticle(Color color, float scale, int avgAge, boolean hot, double speed, double spread) { - Random random = level.getRandom(); - level.addAlwaysVisibleParticle( - new CubeParticleData(color.getRedAsFloat(), color.getGreenAsFloat(), color.getBlueAsFloat(), scale, avgAge, hot), - (double) worldPosition.getX() + 0.5D + (random.nextDouble() * 2.0 - 1D) * spread, - (double) worldPosition.getY() + 0.6D + (random.nextDouble() / 4.0), - (double) worldPosition.getZ() + 0.5D + (random.nextDouble() * 2.0 - 1D) * spread, 0.0D, speed, 0.0D); - } + Vec3 c = VecHelper.getCenterOf(worldPosition); + Vec3 v = c.add(VecHelper.offsetRandomly(Vec3.ZERO, r, .125f) + .multiply(1, 0, 1)); - protected void spawnParticle(Color[] colors, float scale, int avgAge, boolean hot, double speed, double spread) { - if (colors.length == 0) + if (r.nextInt(3) == 0) + level.addParticle(ParticleTypes.LARGE_SMOKE, v.x, v.y, v.z, 0, 0, 0); + if (r.nextInt(2) != 0) return; - spawnParticle(colors[(int) (Math.random() * colors.length)], scale, avgAge, hot, speed, spread); + boolean empty = level.getBlockState(worldPosition.above()) + .getCollisionShape(level, worldPosition.above()) + .isEmpty(); + + double yMotion = empty ? .0625f : r.nextDouble() * .0125f; + Vec3 v2 = c.add(VecHelper.offsetRandomly(Vec3.ZERO, r, .5f) + .multiply(1, .25f, 1) + .normalize() + .scale((empty ? .25f : .5) + r.nextDouble() * .125f)) + .add(0, .5, 0); + + if (heatLevel.isAtLeast(HeatLevel.SEETHING)) { + level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, v2.x, v2.y, v2.z, 0, yMotion, 0); + } else if (heatLevel.isAtLeast(HeatLevel.FADING)) { + level.addParticle(ParticleTypes.FLAME, v2.x, v2.y, v2.z, 0, yMotion, 0); + } + return; } - protected void spawnParticle(HeatLevel heatLevel, float scale, int avgAge, boolean hot, double speed, double spread) { - spawnParticle(PARTICLE_COLORS[heatLevel.ordinal()], scale, avgAge, hot, speed, spread); + public void spawnParticleBurst(boolean soulFlame) { + Vec3 c = VecHelper.getCenterOf(worldPosition); + Random r = level.random; + for (int i = 0; i < 20; i++) { + Vec3 offset = VecHelper.offsetRandomly(Vec3.ZERO, r, .5f) + .multiply(1, .25f, 1) + .normalize(); + Vec3 v = c.add(offset.scale(.5 + r.nextDouble() * .125f)) + .add(0, .125, 0); + Vec3 m = offset.scale(1 / 32f); + + level.addParticle(soulFlame ? ParticleTypes.SOUL_FIRE_FLAME : ParticleTypes.FLAME, v.x, v.y, v.z, m.x, m.y, + m.z); + } } public enum FuelType { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java index b025763ee..2b61e850a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java @@ -130,7 +130,7 @@ public class TrackGraphSync { Couple key = Couple.create(node.getNetId(), node2.getNetId()); currentPacket.addedEdges.add(Pair.of(key, edge.getTurn())); currentPacket.syncEdgeData(node, node2, edge); - }); + });//FIXME these edges will have missing nodes if (sent++ < 1000) continue; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java index f01e7e400..22016bb5e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java @@ -567,7 +567,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { carriage.train.targetSpeed = topSpeed * targetSpeed; if (slow) carriage.train.targetSpeed /= 6; - + boolean counteringAcceleration = Math.abs(Math.signum(targetSpeed) - Math.signum(carriage.train.speed)) > 1.5f; carriage.train.manualTick = true; carriage.train.approachTargetSpeed(counteringAcceleration ? 2 : 1); diff --git a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java index f2b27a76a..d748cc258 100644 --- a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java +++ b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java @@ -153,6 +153,7 @@ public class BuilderTransformers { public static NonNullUnaryOperator> casing( Supplier ct) { return b -> b.initialProperties(SharedProperties::stone) + .properties(p -> p.sound(SoundType.WOOD)) .transform(axeOrPickaxe()) .blockstate((c, p) -> p.simpleBlock(c.get())) .onRegister(connectedTextures(() -> new EncasedCTBehaviour(ct.get()))) diff --git a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java index 19966d5dd..76bb4cd4f 100644 --- a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java @@ -85,19 +85,24 @@ public class SuperByteBuffer implements Transform, TStack, TStack, TStack, TStack, TStack { float targetU = u - entry.getOriginal() .getU0() + entry.getTarget() - .getU0(); + .getU0() + + scrollU; float targetV = v - entry.getOriginal() .getV0() + entry.getTarget() .getV0() @@ -412,8 +424,9 @@ public class SuperByteBuffer implements Transform, TStack, TStackNS%G|;0G|-o|3BRS|8M#K-Tm)p*T26S|6kR(Si$h`vc{ij4BaM-Ife}JOpL2b z8M6hMGx?eSUefsY)$QM(=D)w2{(f=eezH6RXbxwAM`SSr1K(i~W;~w1A_XYe>*?Yc zq7iJ`$0&BlfW!Imlqiq8tM2_@r*?Nq>vxV1j5|)sDBOO>-!f@gh3LE&y1VYOer1Vz ze>2FCX_EDn(6nuC+Z_2)Ha@Xj)9)3~6hCbrQ{3;kC-G{E(;h1JxvN&p6}$3Ez*#oz z(V3aM46gM);yik&jJGnb^5G0=o=EK%6ThdQ+kE&A>)g-M7s3>~?Hw+%z0NS%G~10G|-o|5r8s%w)b?%RI@21t@lUrdbV;Vl4^s3;quT48OPWfehj-@Q5sC zVBk9p!i>lBSEK+1ojhF}Lo|Yy_8Rgr7;+p|c=A7gUxe(cvNx`7Gjyh`-y>SGhG~tm ztQ5zl$8eR=R!6Z)?#}Etux04QX9Z=wLzJ2Te|7Uvxj+Hdc+cx>3=j2JvP1B_R z1_!twcKNB-oGcULBYDzh)~0F$3&BM-(=|5*p3ro4hOcA!{;%h%E(a|S lShS$;*iU}#+PD*Y7|u!a9Bh8ELj!0VgQu&X%Q~loCIA=&Srh;O literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/create/textures/block/blaze_burner_flame_superheated_scroll.png b/src/main/resources/assets/create/textures/block/blaze_burner_flame_superheated_scroll.png new file mode 100644 index 0000000000000000000000000000000000000000..c681893fb357a93678efbaade8eebd9057049042 GIT binary patch literal 255 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCikt0(?STC%^uma`LaqlAqB*`|S*Kfx?e?=N$r4Y$ZW{!T&*kVe|ea`+*{y z1s;*b3=DjSL74G){)!Z!V2Y=UV~B$SPLbt?GvxJWn_} zuI~LOnX&k=%lCeszQTf!r!)*06;~{KGjB$VNJ#Rwj<(DTELUgfZZ=?5U2!ajYuE3! rmal!i=Q@fr=a$U*zv0sJ=2hH}as(W$qrGbP0l+XkKY;9g* literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/create/textures/block/blaze_burner_inner.png b/src/main/resources/assets/create/textures/block/blaze_burner_inner.png deleted file mode 100644 index ed289f2071dcde1a5cae744730777d5cce51dcc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 423 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU&&p0G|+7 zH#hfSd)pv;+dz9;KYKf0dpmmv$3Qb9KT{)LQzLIvBWr6LPg7%OQ{zB=O$QTWZ+$IW z6BAE8ElU#<4?QhYQ&TrREmu8lXFY8rBV#*VZChP!8(nQnT^(;#Su-6SH#K=f9UTW% z1sxq-dldz3ZEZVcIWuJiI|V5%H8mqeIXxvsb2%v;B}FX-c{N2v16e5*d3kjiX?bbs zFIgO`fbQJp>Eakt!N_{>qF=LvfWyVxg$~x;&C7CqdOrTQ_mjI(Ccew(K(U{BK!Zc0 z!%Y3144K&~^WCqWHh6PYYX-x@CytU)2_L?lSSJ!8zf&$=+rGN6b?)0b`*WM?w{Z#8 zUVZ&}vHH!%#tRp9*Ly+0;c+xCORE>l>b(B-uu(s(o9q1LZYqvQhY^y z?rwkhyYQbVqbldU8@eaCIC;}k*C$+Mai4jjb)UAwr%ao>0SW;P4fT)D1es_jfg^yy M)78&qol`;+09UMr3;+NC diff --git a/src/main/resources/assets/create/textures/block/blaze_burner_side.png b/src/main/resources/assets/create/textures/block/blaze_burner_side.png deleted file mode 100644 index f1fcf05bb6286f1036b52a4745ed7d150ca8049e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 262 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF6I=VqYpkh>GZx^prwCn^fp+XVQ8xTPnp!zHyLkHqgoQ=L$5qtUq-ACLhlMdPFx)W_FaS~_B|(0{|1klB zzyEVVpgd=RM`SSr1K(i~W;~w1B87p0QNXj_#WBRff9}Lap(X>4wnXXMTGLj(|G)0< z1+DX8_rA_;SG~_L@f!0#!43-p4xbZ!Ei+s;EeU!Q@jzwgJindSj_A4UzxRCt*Qc$E zJPaDorA%+%Ec#@MR$sd2UZ(gra|#bO-&2~-bd)vB-ztl3xlYg~(aMk;Tw)Pf-<13p zR-XGf|6qM`)!xtKMeiM|QSsRyWx{dV<3jI+zP2lgs;t+p%k`Oc+W&po_D^w+ b={?4|d8T(S<}^(Qh8csWtDnm{r-UW|$n?OL delta 687 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 JPDHLkV1k;5W|{y1 literal 0 HcmV?d00001