Boiling it down

- Implemented new power dynamics of the steam engine
This commit is contained in:
simibubi 2022-05-02 17:14:51 +02:00
parent 147c2ff9fa
commit 1da8b6e538
14 changed files with 362 additions and 169 deletions

View file

@ -131,6 +131,7 @@ public class AllBlockPartials {
ENGINE_PISTON = block("steam_engine/piston"), ENGINE_LINKAGE = block("steam_engine/linkage"), ENGINE_PISTON = block("steam_engine/piston"), ENGINE_LINKAGE = block("steam_engine/linkage"),
ENGINE_CONNECTOR = block("steam_engine/shaft_connector"), BOILER_GAUGE = block("steam_engine/gauge"), ENGINE_CONNECTOR = block("steam_engine/shaft_connector"), BOILER_GAUGE = block("steam_engine/gauge"),
BOILER_GAUGE_DIAL = block("steam_engine/gauge_dial"),
SIGNAL_ON = block("track_signal/indicator_on"), SIGNAL_OFF = block("track_signal/indicator_off"), SIGNAL_ON = block("track_signal/indicator_on"), SIGNAL_OFF = block("track_signal/indicator_off"),
DATA_GATHERER_TUBE = block("data_gatherer/tube"), DATA_GATHERER_GLOW = block("data_gatherer/glow"), DATA_GATHERER_TUBE = block("data_gatherer/tube"), DATA_GATHERER_GLOW = block("data_gatherer/glow"),

View file

@ -875,6 +875,7 @@ public class AllBlocks {
.initialProperties(SharedProperties::copperMetal) .initialProperties(SharedProperties::copperMetal)
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate((c, p) -> p.horizontalFaceBlock(c.get(), AssetLookup.partialBaseModel(c, p))) .blockstate((c, p) -> p.horizontalFaceBlock(c.get(), AssetLookup.partialBaseModel(c, p)))
.transform(BlockStressDefaults.setCapacity(1024.0))
.item() .item()
.transform(customItemModel()) .transform(customItemModel())
.register(); .register();
@ -883,7 +884,6 @@ public class AllBlocks {
REGISTRATE.block("powered_shaft", PoweredShaftBlock::new) REGISTRATE.block("powered_shaft", PoweredShaftBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.transform(BlockStressDefaults.setCapacity(64.0))
.blockstate(BlockStateGen.axisBlockProvider(false)) .blockstate(BlockStateGen.axisBlockProvider(false))
.loot((lt, block) -> lt.dropOther(block, AllBlocks.SHAFT.get())) .loot((lt, block) -> lt.dropOther(block, AllBlocks.SHAFT.get()))
.register(); .register();

View file

@ -122,8 +122,7 @@ public class AllTags {
WRENCH_PICKUP, WRENCH_PICKUP,
PASSIVE_BOILER_HEATERS, PASSIVE_BOILER_HEATERS,
ACTIVE_BOILER_HEATERS,
RELOCATION_NOT_SUPPORTED(FORGE), RELOCATION_NOT_SUPPORTED(FORGE),
WG_STONE(FORGE), WG_STONE(FORGE),
@ -358,7 +357,6 @@ public class AllTags {
AllBlockTags.FAN_HEATERS.add(Blocks.MAGMA_BLOCK, Blocks.CAMPFIRE, Blocks.LAVA, Blocks.FIRE, Blocks.SOUL_FIRE, AllBlockTags.FAN_HEATERS.add(Blocks.MAGMA_BLOCK, Blocks.CAMPFIRE, Blocks.LAVA, Blocks.FIRE, Blocks.SOUL_FIRE,
Blocks.SOUL_CAMPFIRE); Blocks.SOUL_CAMPFIRE);
AllBlockTags.FAN_HEATERS.includeIn(AllBlockTags.PASSIVE_BOILER_HEATERS); AllBlockTags.FAN_HEATERS.includeIn(AllBlockTags.PASSIVE_BOILER_HEATERS);
AllBlockTags.ACTIVE_BOILER_HEATERS.add(Blocks.FURNACE, Blocks.BLAST_FURNACE, Blocks.SMOKER);
AllBlockTags.SAFE_NBT.includeAll(BlockTags.SIGNS); AllBlockTags.SAFE_NBT.includeAll(BlockTags.SIGNS);
AllBlockTags.WRENCH_PICKUP.includeAll(BlockTags.RAILS); AllBlockTags.WRENCH_PICKUP.includeAll(BlockTags.RAILS);

View file

@ -1,71 +1,111 @@
package com.simibubi.create.content.contraptions.components.steam; package com.simibubi.create.content.contraptions.components.steam;
import java.util.HashMap; import java.util.List;
import java.util.Map;
import com.jozufozu.flywheel.repack.joml.Math;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.block.BlockStressValues;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.Axis;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.registries.ForgeRegistries;
public class PoweredShaftTileEntity extends GeneratingKineticTileEntity { public class PoweredShaftTileEntity extends GeneratingKineticTileEntity {
public Map<BlockPos, Integer> sources; public BlockPos enginePos;
public float engineEfficiency;
public int movementDirection;
public Block capacityKey;
public PoweredShaftTileEntity(BlockEntityType<?> typeIn, BlockPos pos, BlockState state) { public PoweredShaftTileEntity(BlockEntityType<?> typeIn, BlockPos pos, BlockState state) {
super(typeIn, pos, state); super(typeIn, pos, state);
sources = new HashMap<>(); movementDirection = 1;
} }
public void update(BlockPos sourcePos, int score) { public void update(BlockPos sourcePos, int direction, float efficiency) {
BlockPos key = worldPosition.subtract(sourcePos); BlockPos key = worldPosition.subtract(sourcePos);
Integer prev = sources.put(key, score); enginePos = key;
if (prev != null && prev.intValue() == score) float prev = engineEfficiency;
engineEfficiency = efficiency;
int prevDirection = this.movementDirection;
if (Mth.equal(efficiency, prev) && prevDirection == direction)
return; return;
capacityKey = level.getBlockState(sourcePos)
.getBlock();
this.movementDirection = direction;
updateGeneratedRotation(); updateGeneratedRotation();
} }
public void remove(BlockPos sourcePos) { public void remove(BlockPos sourcePos) {
BlockPos key = worldPosition.subtract(sourcePos); if (!isPoweredBy(sourcePos))
Integer prev = sources.remove(key);
if (prev == null)
return; return;
enginePos = null;
engineEfficiency = 0;
movementDirection = 0;
capacityKey = null;
updateGeneratedRotation(); updateGeneratedRotation();
} }
public boolean canBePoweredBy(BlockPos globalPos) {
return enginePos == null || isPoweredBy(globalPos);
}
public boolean isPoweredBy(BlockPos globalPos) {
BlockPos key = worldPosition.subtract(globalPos);
return key.equals(enginePos);
}
@Override @Override
protected void write(CompoundTag compound, boolean clientPacket) { protected void write(CompoundTag compound, boolean clientPacket) {
compound.put("Sources", NBTHelper.writeCompoundList(sources.entrySet(), e -> { compound.putInt("Direction", movementDirection);
CompoundTag nbt = new CompoundTag(); if (enginePos != null) {
nbt.put("Pos", NbtUtils.writeBlockPos(e.getKey())); compound.put("EnginePos", NbtUtils.writeBlockPos(enginePos));
nbt.putInt("Value", e.getValue()); compound.putFloat("EnginePower", engineEfficiency);
return nbt; compound.putString("EngineType", capacityKey.getRegistryName().toString());
})); }
super.write(compound, clientPacket); super.write(compound, clientPacket);
} }
@Override @Override
protected void read(CompoundTag compound, boolean clientPacket) { protected void read(CompoundTag compound, boolean clientPacket) {
super.read(compound, clientPacket); super.read(compound, clientPacket);
sources.clear(); movementDirection = compound.getInt("Direction");
NBTHelper.iterateCompoundList(compound.getList("Sources", Tag.TAG_COMPOUND), enginePos = null;
c -> sources.put(NbtUtils.readBlockPos(c.getCompound("Pos")), c.getInt("Value"))); engineEfficiency = 0;
if (compound.contains("EnginePos")) {
enginePos = NbtUtils.readBlockPos(compound.getCompound("EnginePos"));
engineEfficiency = compound.getFloat("EnginePower");
capacityKey = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(compound.getString("EngineType")));
}
} }
@Override @Override
public float getGeneratedSpeed() { public float getGeneratedSpeed() {
int max = 0; return getCombinedCapacity() > 0 ? movementDirection * 16 * getSpeedModifier() : 0;
for (Integer integer : sources.values()) }
if (Math.abs(integer) > max)
max = integer; private float getCombinedCapacity() {
return 8 * max; return capacityKey == null ? 0 : (float) (engineEfficiency * BlockStressValues.getCapacity(capacityKey));
}
private int getSpeedModifier() {
return (int) (1 + (engineEfficiency >= 1 ? 3 : Math.min(2, Math.floor(engineEfficiency * 4))));
}
@Override
public float calculateAddedStressCapacity() {
float capacity = getCombinedCapacity() / getSpeedModifier();
this.lastCapacityProvided = capacity;
return capacity;
} }
@Override @Override
@ -73,5 +113,14 @@ public class PoweredShaftTileEntity extends GeneratingKineticTileEntity {
int combinedCoords = axis.choose(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); int combinedCoords = axis.choose(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ());
return super.getRotationAngleOffset(axis) + (combinedCoords % 2 == 0 ? 180 : 0); return super.getRotationAngleOffset(axis) + (combinedCoords % 2 == 0 ? 180 : 0);
} }
@Override
public boolean addToGoggleTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
return false;
}
public boolean addToEngineTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
return super.addToGoggleTooltip(tooltip, isPlayerSneaking);
}
} }

View file

@ -2,6 +2,8 @@ package com.simibubi.create.content.contraptions.components.steam;
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED;
import java.util.function.Predicate;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
@ -11,9 +13,20 @@ import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity;
import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock;
import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
@ -29,12 +42,15 @@ import net.minecraft.world.level.block.state.properties.AttachFace;
import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
public class SteamEngineBlock extends FaceAttachedHorizontalDirectionalBlock public class SteamEngineBlock extends FaceAttachedHorizontalDirectionalBlock
implements SimpleWaterloggedBlock, IWrenchable, ITE<SteamEngineTileEntity> { implements SimpleWaterloggedBlock, IWrenchable, ITE<SteamEngineTileEntity> {
private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper());
public SteamEngineBlock(Properties p_53182_) { public SteamEngineBlock(Properties p_53182_) {
super(p_53182_); super(p_53182_);
} }
@ -60,6 +76,18 @@ public class SteamEngineBlock extends FaceAttachedHorizontalDirectionalBlock
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState(); return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState();
} }
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand,
BlockHitResult ray) {
ItemStack heldItem = player.getItemInHand(hand);
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
if (placementHelper.matchesItem(heldItem))
return placementHelper.getOffset(player, world, state, pos, ray)
.placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
return InteractionResult.PASS;
}
@Override @Override
public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, LevelAccessor world, public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, LevelAccessor world,
BlockPos pos, BlockPos neighbourPos) { BlockPos pos, BlockPos neighbourPos) {
@ -137,7 +165,8 @@ public class SteamEngineBlock extends FaceAttachedHorizontalDirectionalBlock
} }
public static boolean isShaftValid(BlockState state, BlockState shaft) { public static boolean isShaftValid(BlockState state, BlockState shaft) {
return AllBlocks.SHAFT.has(shaft) && shaft.getValue(ShaftBlock.AXIS) != getFacing(state).getAxis(); return (AllBlocks.SHAFT.has(shaft) || AllBlocks.POWERED_SHAFT.has(shaft))
&& shaft.getValue(ShaftBlock.AXIS) != getFacing(state).getAxis();
} }
@Override @Override
@ -150,4 +179,38 @@ public class SteamEngineBlock extends FaceAttachedHorizontalDirectionalBlock
return AllTileEntities.STEAM_ENGINE.get(); return AllTileEntities.STEAM_ENGINE.get();
} }
@MethodsReturnNonnullByDefault
private static class PlacementHelper implements IPlacementHelper {
@Override
public Predicate<ItemStack> getItemPredicate() {
return AllBlocks.SHAFT::isIn;
}
@Override
public Predicate<BlockState> getStatePredicate() {
return s -> s.getBlock() instanceof SteamEngineBlock;
}
@Override
public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos,
BlockHitResult ray) {
BlockPos shaftPos = SteamEngineBlock.getShaftPos(state, pos);
BlockState shaft = AllBlocks.SHAFT.getDefaultState();
for (Direction direction : Direction.orderedByNearest(player)) {
shaft = shaft.setValue(ShaftBlock.AXIS, direction.getAxis());
if (isShaftValid(state, shaft))
break;
}
BlockState newState = world.getBlockState(shaftPos);
if (!newState.getMaterial().isReplaceable())
return PlacementOffset.fail();
Axis axis = shaft.getValue(ShaftBlock.AXIS);
return PlacementOffset.success(shaftPos,
s -> BlockHelper.copyProperties(s, AllBlocks.POWERED_SHAFT.getDefaultState())
.setValue(PoweredShaftBlock.AXIS, axis));
}
}
} }

View file

@ -11,16 +11,17 @@ import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankConnectivityHandler; import com.simibubi.create.content.contraptions.fluids.tank.FluidTankConnectivityHandler;
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity;
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Debug;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.Axis;
import net.minecraft.core.Direction.AxisDirection; import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.network.chat.Component;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
@ -31,7 +32,7 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
public class SteamEngineTileEntity extends SmartTileEntity { public class SteamEngineTileEntity extends SmartTileEntity implements IHaveGoggleInformation {
public WeakReference<PoweredShaftTileEntity> target; public WeakReference<PoweredShaftTileEntity> target;
public WeakReference<FluidTankTileEntity> source; public WeakReference<FluidTankTileEntity> source;
@ -67,12 +68,12 @@ public class SteamEngineTileEntity extends SmartTileEntity {
if (facing.getAxis() == Axis.Y) if (facing.getAxis() == Axis.Y)
facing = blockState.getValue(SteamEngineBlock.FACING); facing = blockState.getValue(SteamEngineBlock.FACING);
int score = Math.max(0, tank.boiler.engineScore); float efficiency = Mth.clamp(tank.boiler.getEngineEfficiency(tank.getTotalTankSize()), 0, 1);
int conveyedSpeedLevel = int conveyedSpeedLevel =
verticalTarget ? score : (int) GeneratingKineticTileEntity.convertToDirection(score, facing); efficiency == 0 ? 1 : verticalTarget ? 1 : (int) GeneratingKineticTileEntity.convertToDirection(1, facing);
if (targetAxis == Axis.Z) if (targetAxis == Axis.Z)
conveyedSpeedLevel *= -1; conveyedSpeedLevel *= -1;
shaft.update(worldPosition, conveyedSpeedLevel); shaft.update(worldPosition, conveyedSpeedLevel, efficiency);
if (!level.isClientSide) if (!level.isClientSide)
return; return;
@ -89,18 +90,19 @@ public class SteamEngineTileEntity extends SmartTileEntity {
} }
@Override @Override
@OnlyIn(Dist.CLIENT)
public AABB getRenderBoundingBox() { public AABB getRenderBoundingBox() {
return super.getRenderBoundingBox().inflate(2); return super.getRenderBoundingBox().inflate(2);
} }
public PoweredShaftTileEntity getShaft() { public PoweredShaftTileEntity getShaft() {
PoweredShaftTileEntity shaft = target.get(); PoweredShaftTileEntity shaft = target.get();
if (shaft == null || shaft.isRemoved()) { if (shaft == null || shaft.isRemoved() || !shaft.canBePoweredBy(worldPosition)) {
if (shaft != null) if (shaft != null)
target = new WeakReference<>(null); target = new WeakReference<>(null);
Direction facing = SteamEngineBlock.getFacing(getBlockState()); Direction facing = SteamEngineBlock.getFacing(getBlockState());
BlockEntity anyShaftAt = level.getBlockEntity(worldPosition.relative(facing, 2)); BlockEntity anyShaftAt = level.getBlockEntity(worldPosition.relative(facing, 2));
if (anyShaftAt instanceof PoweredShaftTileEntity ps) if (anyShaftAt instanceof PoweredShaftTileEntity ps && ps.canBePoweredBy(worldPosition))
target = new WeakReference<>(shaft = ps); target = new WeakReference<>(shaft = ps);
} }
return shaft; return shaft;
@ -127,6 +129,11 @@ public class SteamEngineTileEntity extends SmartTileEntity {
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
private void spawnParticles() { private void spawnParticles() {
Float targetAngle = getTargetAngle(); Float targetAngle = getTargetAngle();
PoweredShaftTileEntity ste = target.get();
if (ste == null)
return;
if (!ste.isPoweredBy(worldPosition) || ste.engineEfficiency == 0)
return;
if (targetAngle == null) if (targetAngle == null)
return; return;
@ -192,5 +199,11 @@ public class SteamEngineTileEntity extends SmartTileEntity {
angle *= -1; angle *= -1;
return angle; return angle;
} }
@Override
public boolean addToGoggleTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
PoweredShaftTileEntity shaft = getShaft();
return shaft == null ? false : shaft.addToEngineTooltip(tooltip, isPlayerSneaking);
}
} }

View file

@ -28,10 +28,12 @@ import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllInteractionBehaviours; import com.simibubi.create.AllInteractionBehaviours;
import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.actors.SeatBlock; import com.simibubi.create.content.contraptions.components.actors.SeatBlock;
import com.simibubi.create.content.contraptions.components.actors.SeatEntity; import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
import com.simibubi.create.content.contraptions.components.steam.PoweredShaftTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedContraption; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedContraption;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingBlock; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingBlock;
@ -55,6 +57,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.ren
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity;
import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock; import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock;
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock;
import com.simibubi.create.content.logistics.block.inventories.CreativeCrateTileEntity; import com.simibubi.create.content.logistics.block.inventories.CreativeCrateTileEntity;
import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock; import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock;
import com.simibubi.create.content.logistics.block.vault.ItemVaultTileEntity; import com.simibubi.create.content.logistics.block.vault.ItemVaultTileEntity;
@ -64,6 +67,7 @@ import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
import com.simibubi.create.foundation.tileEntity.IMultiTileContainer; import com.simibubi.create.foundation.tileEntity.IMultiTileContainer;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.utility.BlockFace; import com.simibubi.create.foundation.utility.BlockFace;
import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.ICoordinate; import com.simibubi.create.foundation.utility.ICoordinate;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTHelper;
@ -612,6 +616,8 @@ public abstract class Contraption {
BlockState blockstate = world.getBlockState(pos); BlockState blockstate = world.getBlockState(pos);
if (AllBlocks.REDSTONE_CONTACT.has(blockstate)) if (AllBlocks.REDSTONE_CONTACT.has(blockstate))
blockstate = blockstate.setValue(RedstoneContactBlock.POWERED, true); blockstate = blockstate.setValue(RedstoneContactBlock.POWERED, true);
if (AllBlocks.POWERED_SHAFT.has(blockstate))
blockstate = BlockHelper.copyProperties(blockstate, AllBlocks.SHAFT.getDefaultState());
if (AllBlocks.CONTROLS.has(blockstate)) if (AllBlocks.CONTROLS.has(blockstate))
blockstate = blockstate.setValue(ControlsBlock.OPEN, true); blockstate = blockstate.setValue(ControlsBlock.OPEN, true);
if (blockstate.getBlock() instanceof ButtonBlock) { if (blockstate.getBlock() instanceof ButtonBlock) {
@ -624,6 +630,8 @@ public abstract class Contraption {
} }
CompoundTag compoundnbt = getTileEntityNBT(world, pos); CompoundTag compoundnbt = getTileEntityNBT(world, pos);
BlockEntity tileentity = world.getBlockEntity(pos); BlockEntity tileentity = world.getBlockEntity(pos);
if (tileentity instanceof PoweredShaftTileEntity)
tileentity = AllTileEntities.BRACKETED_KINETIC.create(pos, blockstate);
return Pair.of(new StructureBlockInfo(pos, blockstate, compoundnbt), tileentity); return Pair.of(new StructureBlockInfo(pos, blockstate, compoundnbt), tileentity);
} }
@ -985,7 +993,9 @@ public abstract class Contraption {
continue; continue;
BlockState oldState = world.getBlockState(add); BlockState oldState = world.getBlockState(add);
Block blockIn = oldState.getBlock(); Block blockIn = oldState.getBlock();
if (block.state.getBlock() != blockIn) boolean blockMismatch = block.state.getBlock() != blockIn;
blockMismatch &= !AllBlocks.POWERED_SHAFT.is(blockIn) || !AllBlocks.SHAFT.has(block.state);
if (blockMismatch)
iterator.remove(); iterator.remove();
world.removeBlockEntity(add); world.removeBlockEntity(add);
int flags = Block.UPDATE_MOVE_BY_PISTON | Block.UPDATE_SUPPRESS_DROPS | Block.UPDATE_KNOWN_SHAPE int flags = Block.UPDATE_MOVE_BY_PISTON | Block.UPDATE_SUPPRESS_DROPS | Block.UPDATE_KNOWN_SHAPE
@ -1064,6 +1074,10 @@ public abstract class Contraption {
} }
world.destroyBlock(targetPos, true); world.destroyBlock(targetPos, true);
if (AllBlocks.SHAFT.has(state))
state = ShaftBlock.pickCorrectShaftType(state, world, targetPos);
world.setBlock(targetPos, state, Block.UPDATE_MOVE_BY_PISTON | Block.UPDATE_ALL); world.setBlock(targetPos, state, Block.UPDATE_MOVE_BY_PISTON | Block.UPDATE_ALL);
boolean verticalRotation = transform.rotationAxis == null || transform.rotationAxis.isHorizontal(); boolean verticalRotation = transform.rotationAxis == null || transform.rotationAxis.isHorizontal();

View file

@ -7,8 +7,8 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.steam.SteamEngineBlock; import com.simibubi.create.content.contraptions.components.steam.SteamEngineBlock;
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
import com.simibubi.create.foundation.block.BlockStressValues;
import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.fluid.FluidHelper;
import com.simibubi.create.foundation.utility.Debug;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat;
@ -21,7 +21,6 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
@ -31,34 +30,34 @@ import net.minecraftforge.fluids.capability.IFluidHandler;
public class BoilerData { public class BoilerData {
static final int SAMPLE_RATE = 5; static final int SAMPLE_RATE = 5;
public int gatheredSupply;
public float[] supplyOverTime = new float[10]; // pooled water supply
int gatheredSupply;
float[] supplyOverTime = new float[10];
int ticksUntilNextSample; int ticksUntilNextSample;
int currentIndex; int currentIndex;
boolean needsTemperatureUpdate;
public float currentTemperature; // heat score
public float targetTemperature; public boolean needsHeatLevelUpdate;
public boolean passiveHeat;
public int activeHeat;
public float waterSupply; public float waterSupply;
public float steamUnits;
public int attachedEngines; public int attachedEngines;
public int engineScore;
public LerpedFloat pressure = LerpedFloat.linear(); public LerpedFloat gauge = LerpedFloat.linear();
static final float MAX_ENGINE_USAGE = 32;
public void tick(FluidTankTileEntity controller) { public void tick(FluidTankTileEntity controller) {
if (!isActive()) if (!isActive())
return; return;
if (controller.getLevel().isClientSide) { if (controller.getLevel().isClientSide) {
pressure.tickChaser(); gauge.tickChaser();
float current = pressure.getValue(1); float current = gauge.getValue(1);
if (current > 1 && Create.RANDOM.nextFloat() < 1 / 2f) if (current > 1 && Create.RANDOM.nextFloat() < 1 / 2f)
pressure.setValueNoUpdate(current + Math.min(-(current - 1) * Create.RANDOM.nextFloat(), 0)); gauge.setValueNoUpdate(current + Math.min(-(current - 1) * Create.RANDOM.nextFloat(), 0));
return; return;
} }
if (needsTemperatureUpdate && updateTemperature(controller)) if (needsHeatLevelUpdate && updateTemperature(controller))
controller.notifyUpdate(); controller.notifyUpdate();
ticksUntilNextSample--; ticksUntilNextSample--;
if (ticksUntilNextSample > 0) if (ticksUntilNextSample > 0)
@ -68,98 +67,107 @@ public class BoilerData {
return; return;
ticksUntilNextSample = SAMPLE_RATE; ticksUntilNextSample = SAMPLE_RATE;
waterSupply -= supplyOverTime[currentIndex]; // waterSupply -= supplyOverTime[currentIndex] / supplyOverTime.length;
supplyOverTime[currentIndex] = gatheredSupply / (float) SAMPLE_RATE; supplyOverTime[currentIndex] = gatheredSupply / (float) SAMPLE_RATE;
waterSupply += supplyOverTime[currentIndex]; waterSupply = Math.max(waterSupply, supplyOverTime[currentIndex]);
currentIndex = (currentIndex + 1) % supplyOverTime.length; currentIndex = (currentIndex + 1) % supplyOverTime.length;
gatheredSupply = 0; gatheredSupply = 0;
if (currentIndex == 0) { if (currentIndex == 0) {
waterSupply = 0; waterSupply = 0;
for (float i : supplyOverTime) for (float i : supplyOverTime)
waterSupply += i; // waterSupply += i;
} waterSupply = Math.max(i, waterSupply);
currentTemperature = Mth.clamp(currentTemperature + Math.signum(targetTemperature - currentTemperature)
* (0.5f + (targetTemperature - currentTemperature) * .125f), 0, targetTemperature);
float steamPerTick = Math.min(waterSupply / 2, currentTemperature - 100);
steamUnits += steamPerTick;
float pressure = steamUnits / capacity;
float engineEfficiency = (float) (Math.max(0, pressure - 0.5) * 2);
float usagePerEngine = engineEfficiency * MAX_ENGINE_USAGE;
float consumedSteam = Math.min(steamUnits, attachedEngines * usagePerEngine);
float equilibrium = steamPerTick / (attachedEngines * MAX_ENGINE_USAGE * 2) + .5f;
// if (Math.abs(engineEfficiency - equilibrium) < 1 / 8f) // Anti-flicker at balance point
// engineEfficiency = equilibrium;
engineScore = Mth.floor(engineEfficiency * 8);
steamUnits -= consumedSteam;
if (steamUnits > capacity * 1.25f) {
Debug.debugChat("Boiler exploding: Bang. " + controller.getBlockPos());
steamUnits = 0;
} }
controller.notifyUpdate(); controller.notifyUpdate();
} }
public int getTheoreticalHeatLevel() {
return activeHeat;
}
public int getMaxHeatLevelForBoilerSize(int boilerSize) {
return boilerSize / 4;
}
public int getMaxHeatLevelForWaterSupply() {
return Math.min(activeHeat, (int) Math.min(18, Mth.ceil(waterSupply) / 20));
}
public boolean isPassive(int boilerSize) {
return passiveHeat || activeHeat != 0 && getActualHeat(boilerSize) == 0;
}
public float getEngineEfficiency(int boilerSize) {
if (isPassive(boilerSize))
return 1 / 16f / attachedEngines;
if (activeHeat == 0)
return 0;
int actualHeat = getActualHeat(boilerSize);
return attachedEngines <= actualHeat ? 1 : (float) actualHeat / attachedEngines;
}
private int getActualHeat(int boilerSize) {
int forBoilerSize = getMaxHeatLevelForBoilerSize(boilerSize);
int forWaterSupply = getMaxHeatLevelForWaterSupply();
int actualHeat = Math.min(activeHeat, Math.min(forWaterSupply, forBoilerSize));
return actualHeat;
}
String spacing = " "; String spacing = " ";
Component componentSpacing = new TextComponent(spacing); Component componentSpacing = new TextComponent(spacing);
public boolean addToGoggleTooltip(List<Component> tooltip, boolean isPlayerSneaking) { public boolean addToGoggleTooltip(List<Component> tooltip, boolean isPlayerSneaking, int boilerSize) {
if (!isActive()) if (!isActive())
return false; return false;
float steamPerTick = Math.min(waterSupply / 2, currentTemperature - 100); int forBoilerSize = getMaxHeatLevelForBoilerSize(boilerSize);
float equilibrium = steamPerTick / (attachedEngines * MAX_ENGINE_USAGE * 2) + .5f; int forWaterSupply = getMaxHeatLevelForWaterSupply();
int actualHeat = Math.min(activeHeat, Math.min(forWaterSupply, forBoilerSize));
tooltip.add(componentSpacing.plainCopy() tooltip.add(componentSpacing.plainCopy()
.append(Lang.translate("gui.goggles.fluid_container"))); .append(new TextComponent("Boiler Information:")));
TranslatableComponent mb = Lang.translate("generic.unit.millibuckets");
Component engines = new TextComponent("Engines: ").withStyle(ChatFormatting.GRAY) Component h = new TextComponent("Heat: ").withStyle(ChatFormatting.GRAY)
.append(new TextComponent(attachedEngines + "").withStyle(ChatFormatting.GOLD)); .append(new TextComponent(IHaveGoggleInformation.format(activeHeat)).withStyle(ChatFormatting.GOLD));
Component power = new TextComponent("Temperature: ").withStyle(ChatFormatting.GRAY) Component w = new TextComponent(", Water: ").withStyle(ChatFormatting.GRAY)
.append(new TextComponent(IHaveGoggleInformation.format(currentTemperature) + "") .append(new TextComponent(IHaveGoggleInformation.format(forWaterSupply)).withStyle(ChatFormatting.GOLD));
.withStyle(ChatFormatting.GOLD)); Component s = new TextComponent(", Size: ").withStyle(ChatFormatting.GRAY)
Component score = new TextComponent("Engine Efficiency: ").withStyle(ChatFormatting.GRAY) .append(new TextComponent(IHaveGoggleInformation.format(forBoilerSize)).withStyle(ChatFormatting.GOLD));
.append(new TextComponent(engineScore + "").withStyle(ChatFormatting.GOLD));
Component supply = new TextComponent("Water Supply: ").withStyle(ChatFormatting.GRAY)
.append(new TextComponent(IHaveGoggleInformation.format(waterSupply)).append(mb)
.withStyle(ChatFormatting.GOLD));
Component steam = new TextComponent("Steam Volume: ").withStyle(ChatFormatting.GRAY)
.append(new TextComponent(IHaveGoggleInformation.format(steamUnits)).append(mb)
.withStyle(ChatFormatting.GOLD));
int approachingPressure = (int) (equilibrium * 100); TextComponent heatLevel = isPassive(boilerSize) ? new TextComponent("Passive")
int actualPressure = : (activeHeat == 0 ? new TextComponent("No Heat")
(int) ((this.pressure.getChaseTarget() > 1 ? this.pressure.getChaseTarget() : this.pressure.getValue()) : new TextComponent(IHaveGoggleInformation.format(actualHeat)));
* 100); MutableComponent heatLabel = heatLevel.withStyle(ChatFormatting.GREEN);
MutableComponent pressure = new TextComponent("Pressure: ").withStyle(ChatFormatting.GRAY) Component level = new TextComponent("Boiler Level: ").append(heatLabel);
.append(new TextComponent(IHaveGoggleInformation.format(actualPressure)).append(new TextComponent("%"))
.withStyle(ChatFormatting.GOLD));
if (actualPressure != approachingPressure)
pressure.append(new TextComponent(" >> ").append(
new TextComponent(IHaveGoggleInformation.format(approachingPressure)).append(new TextComponent("%"))
.withStyle(ChatFormatting.GREEN)));
Component indent = new TextComponent(spacing + " "); double totalSU = getEngineEfficiency(boilerSize) * 16 * Math.max(actualHeat, attachedEngines)
* BlockStressValues.getCapacity(AllBlocks.STEAM_ENGINE.get());
Component capacity =
new TextComponent(IHaveGoggleInformation.format(totalSU)).append(Lang.translate("generic.unit.stress"))
.withStyle(ChatFormatting.AQUA);
Component engines =
new TextComponent(" via " + attachedEngines + " engine(s)").withStyle(ChatFormatting.DARK_GRAY);
Component indent = new TextComponent(spacing);
Component indent2 = new TextComponent(spacing + " ");
Component stats = indent.plainCopy()
.append(h)
.append(w)
.append(s);
if (activeHeat > 0)
tooltip.add(stats);
tooltip.add(new TextComponent(" -> ").append(level));
tooltip.add(indent.plainCopy() tooltip.add(indent.plainCopy()
.append(Lang.translate("tooltip.capacityProvided")
.withStyle(ChatFormatting.GRAY)));
tooltip.add(indent2.plainCopy()
.append(capacity)
.append(engines)); .append(engines));
tooltip.add(indent.plainCopy()
.append(score));
tooltip.add(indent.plainCopy()
.append(power));
tooltip.add(indent.plainCopy()
.append(supply));
tooltip.add(indent.plainCopy()
.append(steam));
tooltip.add(indent.plainCopy()
.append(pressure));
return true; return true;
} }
@ -190,29 +198,36 @@ public class BoilerData {
} }
} }
needsTemperatureUpdate = true; needsHeatLevelUpdate = true;
return prev != attachedEngines; return prev != attachedEngines;
} }
public boolean updateTemperature(FluidTankTileEntity controller) { public boolean updateTemperature(FluidTankTileEntity controller) {
BlockPos controllerPos = controller.getBlockPos(); BlockPos controllerPos = controller.getBlockPos();
Level level = controller.getLevel(); Level level = controller.getLevel();
float prev = targetTemperature; needsHeatLevelUpdate = false;
targetTemperature = 0;
needsTemperatureUpdate = false; boolean prevPassive = passiveHeat;
int prevActive = activeHeat;
passiveHeat = false;
activeHeat = 0;
for (int xOffset = 0; xOffset < controller.width; xOffset++) { for (int xOffset = 0; xOffset < controller.width; xOffset++) {
for (int zOffset = 0; zOffset < controller.width; zOffset++) { for (int zOffset = 0; zOffset < controller.width; zOffset++) {
BlockPos pos = controllerPos.offset(xOffset, -1, zOffset); BlockPos pos = controllerPos.offset(xOffset, -1, zOffset);
BlockState blockState = level.getBlockState(pos); BlockState blockState = level.getBlockState(pos);
targetTemperature += BoilerHeaters.getAddedHeatOf(blockState); float heat = BoilerHeaters.getActiveHeatOf(blockState);
if (heat == 0) {
passiveHeat |= BoilerHeaters.canHeatPassively(blockState);
continue;
}
activeHeat += heat;
} }
} }
if (targetTemperature != 0) passiveHeat &= activeHeat == 0;
targetTemperature += 100;
return prev != attachedEngines; return prevActive != activeHeat || prevPassive != passiveHeat;
} }
public boolean isActive() { public boolean isActive() {
@ -221,36 +236,35 @@ public class BoilerData {
public void clear() { public void clear() {
waterSupply = 0; waterSupply = 0;
targetTemperature = 0; activeHeat = 0;
passiveHeat = false;
attachedEngines = 0; attachedEngines = 0;
steamUnits = 0;
engineScore = 0;
Arrays.fill(supplyOverTime, 0); Arrays.fill(supplyOverTime, 0);
} }
public CompoundTag write() { public CompoundTag write() {
CompoundTag nbt = new CompoundTag(); CompoundTag nbt = new CompoundTag();
nbt.putFloat("Supply", waterSupply); nbt.putFloat("Supply", waterSupply);
nbt.putFloat("Temperature", currentTemperature); nbt.putInt("ActiveHeat", activeHeat);
nbt.putFloat("Power", targetTemperature); nbt.putBoolean("PassiveHeat", passiveHeat);
nbt.putFloat("Pressure", steamUnits);
nbt.putInt("Engines", attachedEngines); nbt.putInt("Engines", attachedEngines);
nbt.putBoolean("Update", needsTemperatureUpdate); nbt.putBoolean("Update", needsHeatLevelUpdate);
nbt.putInt("Score", engineScore);
return nbt; return nbt;
} }
public void read(CompoundTag nbt, int capacity) { public void read(CompoundTag nbt, int boilerSize) {
waterSupply = nbt.getFloat("Supply"); waterSupply = nbt.getFloat("Supply");
currentTemperature = nbt.getFloat("Temperature"); activeHeat = nbt.getInt("ActiveHeat");
targetTemperature = nbt.getFloat("Power"); passiveHeat = nbt.getBoolean("PassiveHeat");
steamUnits = nbt.getFloat("Pressure");
engineScore = nbt.getInt("Score");
attachedEngines = nbt.getInt("Engines"); attachedEngines = nbt.getInt("Engines");
needsTemperatureUpdate = nbt.getBoolean("Update"); needsHeatLevelUpdate = nbt.getBoolean("Update");
Arrays.fill(supplyOverTime, (int) waterSupply); Arrays.fill(supplyOverTime, (int) waterSupply);
if (capacity > 0)
pressure.chase(steamUnits / capacity, 0.125f, Chaser.EXP); int forBoilerSize = getMaxHeatLevelForBoilerSize(boilerSize);
int forWaterSupply = getMaxHeatLevelForWaterSupply();
int actualHeat = Math.min(activeHeat, Math.min(forWaterSupply, forBoilerSize));
float target = isPassive(boilerSize) ? 1 / 8f : forBoilerSize == 0 ? 0 : actualHeat / (forBoilerSize * 1f);
gauge.chase(target, 0.125f, Chaser.EXP);
} }
public BoilerFluidHandler createHandler() { public BoilerFluidHandler createHandler() {
@ -283,11 +297,14 @@ public class BoilerData {
public int fill(FluidStack resource, FluidAction action) { public int fill(FluidStack resource, FluidAction action) {
if (!isFluidValid(0, resource)) if (!isFluidValid(0, resource))
return 0; return 0;
if (targetTemperature == 0) int maxAccepted = (int) ((passiveHeat ? 1 : activeHeat + 1) * 20) * SAMPLE_RATE;
if (maxAccepted == 0)
return 0; return 0;
int amount = resource.getAmount(); int amount = Math.min(maxAccepted - gatheredSupply, resource.getAmount());
if (action.execute()) if (action.execute())
gatheredSupply += amount; gatheredSupply += amount;
if (action.simulate())
return Math.max(amount, 1);
return amount; return amount;
} }

View file

@ -5,33 +5,33 @@ import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel;
import net.minecraft.world.level.block.AbstractFurnaceBlock;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
public class BoilerHeaters { // API? public class BoilerHeaters { // API?
public static float getAddedHeatOf(BlockState state) { public static boolean canHeatPassively(BlockState state) {
if (AllBlocks.BLAZE_BURNER.has(state) && state.getValue(BlazeBurnerBlock.HEAT_LEVEL) != HeatLevel.NONE)
return true;
if (AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state))
return true;
return false;
}
public static int getActiveHeatOf(BlockState state) {
if (AllBlocks.BLAZE_BURNER.has(state)) { if (AllBlocks.BLAZE_BURNER.has(state)) {
HeatLevel value = state.getValue(BlazeBurnerBlock.HEAT_LEVEL); HeatLevel value = state.getValue(BlazeBurnerBlock.HEAT_LEVEL);
switch (value) { switch (value) {
case SMOULDERING:
return 24;
case FADING: case FADING:
case KINDLED: case KINDLED:
return 96; return 1;
case SEETHING: case SEETHING:
return 32 * 8; return 2;
default: default:
case SMOULDERING:
case NONE: case NONE:
return 0; return 0;
} }
} }
if (state.hasProperty(AbstractFurnaceBlock.LIT) && !state.getValue(AbstractFurnaceBlock.LIT))
return 0;
if (AllBlockTags.ACTIVE_BOILER_HEATERS.matches(state))
return 48;
if (AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state))
return 12;
return 0; return 0;
} }

View file

@ -86,7 +86,7 @@ public class FluidTankRenderer extends SafeTileEntityRenderer<FluidTankTileEntit
msr.translate(te.width / 2f, 0.5, te.width / 2f); msr.translate(te.width / 2f, 0.5, te.width / 2f);
float dialPivot = 5.75f / 16; float dialPivot = 5.75f / 16;
float progress = te.boiler.pressure.getValue(partialTicks); float progress = te.boiler.gauge.getValue(partialTicks);
for (Direction d : Iterate.horizontalDirections) { for (Direction d : Iterate.horizontalDirections) {
ms.pushPose(); ms.pushPose();
@ -96,7 +96,7 @@ public class FluidTankRenderer extends SafeTileEntityRenderer<FluidTankTileEntit
.translate(te.width / 2f - 6 / 16f, 0, 0) .translate(te.width / 2f - 6 / 16f, 0, 0)
.light(light) .light(light)
.renderInto(ms, vb); .renderInto(ms, vb);
CachedBufferer.partial(AllBlockPartials.GAUGE_DIAL, blockState) CachedBufferer.partial(AllBlockPartials.BOILER_GAUGE_DIAL, blockState)
.rotateY(d.toYRot()) .rotateY(d.toYRot())
.unCentre() .unCentre()
.translate(te.width / 2f - 6 / 16f, 0, 0) .translate(te.width / 2f - 6 / 16f, 0, 0)

View file

@ -59,7 +59,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI
// For rendering purposes only // For rendering purposes only
private LerpedFloat fluidLevel; private LerpedFloat fluidLevel;
public FluidTankTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) { public FluidTankTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state); super(type, pos, state);
tankInventory = createInventory(); tankInventory = createInventory();
@ -235,14 +235,14 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI
return; return;
te.setWindows(!te.window); te.setWindows(!te.window);
} }
public void updateBoilerTemperature() { public void updateBoilerTemperature() {
FluidTankTileEntity te = getControllerTE(); FluidTankTileEntity te = getControllerTE();
if (te == null) if (te == null)
return; return;
if (!te.boiler.isActive()) if (!te.boiler.isActive())
return; return;
te.boiler.needsTemperatureUpdate = true; te.boiler.needsHeatLevelUpdate = true;
} }
public void sendDataImmediately() { public void sendDataImmediately() {
@ -361,7 +361,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI
FluidTankTileEntity controllerTE = getControllerTE(); FluidTankTileEntity controllerTE = getControllerTE();
if (controllerTE == null) if (controllerTE == null)
return false; return false;
if (controllerTE.boiler.addToGoggleTooltip(tooltip, isPlayerSneaking)) if (controllerTE.boiler.addToGoggleTooltip(tooltip, isPlayerSneaking, controllerTE.getTotalTankSize()))
return true; return true;
return containedFluidTooltip(tooltip, isPlayerSneaking, return containedFluidTooltip(tooltip, isPlayerSneaking,
controllerTE.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)); controllerTE.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY));
@ -395,8 +395,8 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI
if (tankInventory.getSpace() < 0) if (tankInventory.getSpace() < 0)
tankInventory.drain(-tankInventory.getSpace(), FluidAction.EXECUTE); tankInventory.drain(-tankInventory.getSpace(), FluidAction.EXECUTE);
} }
boiler.read(compound.getCompound("Boiler"), tankInventory.getCapacity()); boiler.read(compound.getCompound("Boiler"), width * width * height);
if (compound.contains("ForceFluidLevel") || fluidLevel == null) if (compound.contains("ForceFluidLevel") || fluidLevel == null)
fluidLevel = LerpedFloat.linear() fluidLevel = LerpedFloat.linear()

View file

@ -13,6 +13,7 @@ import com.simibubi.create.content.curiosities.girder.GirderEncasedShaftBlock;
import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import com.simibubi.create.foundation.utility.placement.util.PoleHelper; import com.simibubi.create.foundation.utility.placement.util.PoleHelper;
import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.MethodsReturnNonnullByDefault;
@ -47,7 +48,11 @@ public class ShaftBlock extends AbstractSimpleShaftBlock {
@Override @Override
public BlockState getStateForPlacement(BlockPlaceContext context) { public BlockState getStateForPlacement(BlockPlaceContext context) {
BlockState stateForPlacement = super.getStateForPlacement(context); BlockState stateForPlacement = super.getStateForPlacement(context);
if (PoweredShaftBlock.stillValid(stateForPlacement, context.getLevel(), context.getClickedPos())) return pickCorrectShaftType(stateForPlacement, context.getLevel(), context.getClickedPos());
}
public static BlockState pickCorrectShaftType(BlockState stateForPlacement, Level level, BlockPos pos) {
if (PoweredShaftBlock.stillValid(stateForPlacement, level, pos))
return PoweredShaftBlock.getEquivalent(stateForPlacement); return PoweredShaftBlock.getEquivalent(stateForPlacement);
return stateForPlacement; return stateForPlacement;
} }
@ -129,5 +134,16 @@ public class ShaftBlock extends AbstractSimpleShaftBlock {
public Predicate<BlockState> getStatePredicate() { public Predicate<BlockState> getStatePredicate() {
return AllBlocks.SHAFT::has; return AllBlocks.SHAFT::has;
} }
@Override
public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos,
BlockHitResult ray) {
PlacementOffset offset = super.getOffset(player, world, state, pos, ray);
if (offset.isSuccessful())
offset.withTransform(offset.getTransform()
.andThen(s -> ShaftBlock.pickCorrectShaftType(s, world, offset.getBlockPos())));
return offset;
}
} }
} }

View file

@ -0,0 +1,22 @@
{
"credit": "Made with Blockbench",
"textures": {
"2": "create:block/boiler_gauge"
},
"elements": [
{
"name": "GaugeDial",
"from": [15.75, 5.25, 5.75],
"to": [16.45, 6.25, 10.75],
"rotation": {"angle": 0, "axis": "x", "origin": [16.1, 5.75, 8.25]},
"faces": {
"north": {"uv": [0, 11, 1, 12], "rotation": 180, "texture": "#2"},
"east": {"uv": [0, 11, 5, 12], "rotation": 180, "texture": "#2"},
"south": {"uv": [4, 11, 5, 12], "rotation": 180, "texture": "#2"},
"west": {"uv": [5, 11, 0, 12], "rotation": 180, "texture": "#2"},
"up": {"uv": [0, 11, 5, 12], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 11, 5, 12], "rotation": 270, "texture": "#2"}
}
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 360 B

After

Width:  |  Height:  |  Size: 363 B