Riveting Development

- Valve handles no longer create stress config entries for each dyed variant
- Place near initial angle mode on bearings now has a smaller interval considered 'near'
- Rollers are now a little easier to place and expand
- Players can now take items from saws via right-click
- Item Drains now accept dropped items as input
- Train track placement overlay now explicitly mentions the ctrl key
This commit is contained in:
simibubi 2023-03-27 14:29:08 +02:00
parent ef07383a74
commit fc91b63d12
17 changed files with 279 additions and 67 deletions

View file

@ -567,7 +567,7 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
0f4e5a2fc58580df5b156fdac438ddeb6b57e386 assets/create/lang/en_ud.json
2502e2934b3e39763f5619e1522b0b6f98bc26d7 assets/create/lang/en_us.json
aa858245829503947285d0a41b41ec7119de4219 assets/create/lang/en_us.json
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
@ -2263,8 +2263,7 @@ eff2f22dfdf7ed94f868bfdf960fd6a6c8f6a567 data/create/advancements/hose_pulley.js
c119d8187e57286836579cf33d4bcdced2406932 data/create/advancements/hose_pulley_lava.json
ce5a2e1e2ac7049f03c6c8f15130112500bbae2f data/create/advancements/lava_wheel_00000.json
63d86087604035e4e70c203d9b73a7d567a173c1 data/create/advancements/linked_controller.json
f81d3e42370e8429bcd165d745dfc19fdcf6dedd data/create/advancements/long_bend.json
22d19a986e27169ad170792ef5dcbcdf2ea4d214 data/create/advancements/long_train.json
5678c0e3fae7a7cd45a5c5b60f651350d314b8a8 data/create/advancements/long_train.json
648e40cace7bd3d2cb1375ae89fd2ee0e0ad561e data/create/advancements/long_travel.json
258a8c893b8a0265fb1c80f6fa528e80157884e8 data/create/advancements/mechanical_arm.json
418feaeabccc9bfa6ed89fa36de9d6991ce2c7c2 data/create/advancements/mechanical_crafter.json

View file

@ -852,8 +852,6 @@
"advancement.create.train_portal.desc": "Ride a Train through a Nether portal",
"advancement.create.track_crafting_factory": "Track Factory",
"advancement.create.track_crafting_factory.desc": "Produce more than 1000 Train Tracks with the same Mechanical Press",
"advancement.create.long_bend": "The Longest Bend",
"advancement.create.long_bend.desc": "Create a curved track section that spans more than 30 blocks in length",
"advancement.create.long_train": "Ambitious Endeavours",
"advancement.create.long_train.desc": "Create a Train with at least 6 carriages",
"advancement.create.long_travel": "Field Trip",
@ -1576,6 +1574,7 @@
"create.track.turn_start": "Cannot start connection from a Turn",
"create.track.not_enough_tracks": "Not holding enough tracks",
"create.track.not_enough_pavement": "Not holding enough pavement blocks",
"create.track.hold_for_smooth_curve": "Hold %1$s for maximized turn",
"create.portal_track.failed": "Cannot place portal track:",
"create.portal_track.missing": "Target portal not generated yet",

View file

@ -1,30 +0,0 @@
{
"parent": "create:track_crafting_factory",
"display": {
"icon": {
"item": "create:track"
},
"title": {
"translate": "advancement.create.long_bend"
},
"description": {
"color": "#DBA213",
"translate": "advancement.create.long_bend.desc"
},
"frame": "goal",
"show_toast": true,
"announce_to_chat": true,
"hidden": false
},
"criteria": {
"0": {
"trigger": "create:long_bend_builtin",
"conditions": {}
}
},
"requirements": [
[
"0"
]
]
}

View file

@ -1,5 +1,5 @@
{
"parent": "create:long_bend",
"parent": "create:track_crafting_factory",
"display": {
"icon": {
"item": "minecraft:minecart"

View file

@ -27,6 +27,7 @@ import com.simibubi.create.content.contraptions.components.actors.PloughMovement
import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceBlock;
import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceMovement;
import com.simibubi.create.content.contraptions.components.actors.RollerBlock;
import com.simibubi.create.content.contraptions.components.actors.RollerBlockItem;
import com.simibubi.create.content.contraptions.components.actors.RollerMovementBehaviour;
import com.simibubi.create.content.contraptions.components.actors.SawMovementBehaviour;
import com.simibubi.create.content.contraptions.components.actors.SeatBlock;
@ -904,6 +905,7 @@ public class AllBlocks {
REGISTRATE.block("copper_valve_handle", ValveHandleBlock::copper)
.transform(pickaxeOnly())
.transform(BuilderTransformers.valveHandle(null))
.transform(BlockStressDefaults.setCapacity(8.0))
.register();
public static final DyedBlockList<ValveHandleBlock> DYED_VALVE_HANDLES = new DyedBlockList<>(colour -> {
@ -1375,7 +1377,7 @@ public class AllBlocks {
.onRegister(movementBehaviour(new RollerMovementBehaviour()))
.blockstate(BlockStateGen.horizontalBlockProvider(true))
.addLayer(() -> RenderType::cutoutMipped)
.item()
.item(RollerBlockItem::new)
.transform(customItemModel())
.register();

View file

@ -15,6 +15,7 @@ import com.simibubi.create.content.curiosities.weapons.PotatoCannonRenderHandler
import com.simibubi.create.content.curiosities.zapper.ZapperRenderHandler;
import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler;
import com.simibubi.create.content.logistics.trains.GlobalRailwayManager;
import com.simibubi.create.content.logistics.trains.track.TrackPlacement;
import com.simibubi.create.content.schematics.ClientSchematicLoader;
import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler;
import com.simibubi.create.content.schematics.client.SchematicHandler;
@ -104,6 +105,7 @@ public class CreateClient {
OverlayRegistry.registerOverlayAbove(ForgeIngameGui.HOTBAR_ELEMENT, "Create's Linked Controller", LinkedControllerClientHandler.OVERLAY);
OverlayRegistry.registerOverlayAbove(ForgeIngameGui.HOTBAR_ELEMENT, "Create's Schematics", SCHEMATIC_HANDLER.getOverlayRenderer());
OverlayRegistry.registerOverlayAbove(ForgeIngameGui.HOTBAR_ELEMENT, "Create's Toolboxes", ToolboxHandlerClient.OVERLAY);
OverlayRegistry.registerOverlayAbove(ForgeIngameGui.HOTBAR_ELEMENT, "Create's Track Placement", TrackPlacement.OVERLAY);
}
public static void invalidateRenderers() {

View file

@ -1,24 +1,43 @@
package com.simibubi.create.content.contraptions.components.actors;
import java.util.function.Predicate;
import com.simibubi.create.AllBlockEntityTypes;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.content.curiosities.tools.ExtendoGripItem;
import com.simibubi.create.foundation.block.IBE;
import com.simibubi.create.foundation.config.AllConfigs;
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.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
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.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.common.ForgeMod;
public class RollerBlock extends AttachedActorBlock implements IBE<RollerBlockEntity> {
public static DamageSource damageSourceRoller = new DamageSource("create.mechanical_roller");
private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper());
public RollerBlock(Properties p_i48377_1_) {
super(p_i48377_1_);
}
@ -50,4 +69,85 @@ public class RollerBlock extends AttachedActorBlock implements IBE<RollerBlockEn
return true;
}
@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 (!player.isShiftKeyDown() && player.mayBuild()) {
if (placementHelper.matchesItem(heldItem)) {
placementHelper.getOffset(player, world, state, pos, ray)
.placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
return InteractionResult.SUCCESS;
}
}
return InteractionResult.PASS;
}
private static class PlacementHelper implements IPlacementHelper {
@Override
public Predicate<ItemStack> getItemPredicate() {
return AllBlocks.MECHANICAL_ROLLER::isIn;
}
@Override
public Predicate<BlockState> getStatePredicate() {
return AllBlocks.MECHANICAL_ROLLER::has;
}
public int attachedSteps(Level world, BlockPos pos, Direction direction) {
BlockPos checkPos = pos.relative(direction);
BlockState state = world.getBlockState(checkPos);
int count = 0;
while (getStatePredicate().test(state)) {
count++;
checkPos = checkPos.relative(direction);
state = world.getBlockState(checkPos);
}
return count;
}
@Override
public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos,
BlockHitResult ray) {
Direction dir = null;
Direction facing = state.getValue(FACING);
for (Direction nearest : Direction.orderedByNearest(player)) {
if (nearest.getAxis() != facing.getClockWise()
.getAxis())
continue;
dir = nearest;
break;
}
int range = AllConfigs.server().curiosities.placementAssistRange.get();
if (player != null) {
AttributeInstance reach = player.getAttribute(ForgeMod.REACH_DISTANCE.get());
if (reach != null && reach.hasModifier(ExtendoGripItem.singleRangeAttributeModifier))
range += 4;
}
int row = attachedSteps(world, pos, dir);
if (row >= range)
return PlacementOffset.fail();
BlockPos newPos = pos.relative(dir, row + 1);
BlockState newState = world.getBlockState(newPos);
if (!state.canSurvive(world, newPos))
return PlacementOffset.fail();
if (newState.getMaterial()
.isReplaceable())
return PlacementOffset.success(newPos, bState -> bState.setValue(FACING, facing));
return PlacementOffset.fail();
}
}
}

View file

@ -0,0 +1,29 @@
package com.simibubi.create.content.contraptions.components.actors;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
public class RollerBlockItem extends BlockItem {
public RollerBlockItem(Block pBlock, Properties pProperties) {
super(pBlock, pProperties);
}
@Override
public InteractionResult place(BlockPlaceContext ctx) {
BlockPos clickedPos = ctx.getClickedPos();
Level level = ctx.getLevel();
BlockState blockStateBelow = level.getBlockState(clickedPos.below());
if (!Block.isFaceFull(blockStateBelow.getCollisionShape(level, clickedPos.below()), Direction.UP))
return super.place(ctx);
Direction clickedFace = ctx.getClickedFace();
return super.place(BlockPlaceContext.at(ctx, clickedPos.relative(Direction.UP), clickedFace));
}
}

View file

@ -76,7 +76,8 @@ public class HandCrankBlockEntity extends GeneratingKineticBlockEntity {
@Override
protected Block getStressConfigKey() {
return AllBlocks.HAND_CRANK.get();
return AllBlocks.HAND_CRANK.has(getBlockState()) ? AllBlocks.HAND_CRANK.get()
: AllBlocks.COPPER_VALVE_HANDLE.get();
}
@Override

View file

@ -12,9 +12,13 @@ import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos;
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.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
@ -24,6 +28,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
@ -40,7 +45,8 @@ public class SawBlock extends DirectionalAxisKineticBlock implements IBE<SawBloc
public BlockState getStateForPlacement(BlockPlaceContext context) {
BlockState stateForPlacement = super.getStateForPlacement(context);
Direction facing = stateForPlacement.getValue(FACING);
if (facing.getAxis().isVertical())
if (facing.getAxis()
.isVertical())
return stateForPlacement;
return stateForPlacement.setValue(AXIS_ALONG_FIRST_COORDINATE, facing.getAxis() == Axis.X);
}
@ -50,11 +56,34 @@ public class SawBlock extends DirectionalAxisKineticBlock implements IBE<SawBloc
return AllShapes.CASING_12PX.get(state.getValue(FACING));
}
@Override
public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn,
BlockHitResult hit) {
if (player.isSpectator() || !player.getItemInHand(handIn)
.isEmpty())
return InteractionResult.PASS;
if (state.getOptionalValue(FACING)
.orElse(Direction.WEST) != Direction.UP)
return InteractionResult.PASS;
return onBlockEntityUse(worldIn, pos, be -> {
for (int i = 0; i < be.inventory.getSlots(); i++) {
ItemStack heldItemStack = be.inventory.getStackInSlot(i);
if (!worldIn.isClientSide && !heldItemStack.isEmpty())
player.getInventory()
.placeItemBackInInventory(heldItemStack);
}
be.inventory.clear();
be.notifyUpdate();
return InteractionResult.SUCCESS;
});
}
@Override
public void entityInside(BlockState state, Level worldIn, BlockPos pos, Entity entityIn) {
if (entityIn instanceof ItemEntity)
return;
if (!new AABB(pos).deflate(.1f).intersects(entityIn.getBoundingBox()))
if (!new AABB(pos).deflate(.1f)
.intersects(entityIn.getBoundingBox()))
return;
withBlockEntityDo(worldIn, pos, be -> {
if (be.getSpeed() == 0)
@ -85,18 +114,21 @@ public class SawBlock extends DirectionalAxisKineticBlock implements IBE<SawBloc
}
public static boolean isHorizontal(BlockState state) {
return state.getValue(FACING).getAxis().isHorizontal();
return state.getValue(FACING)
.getAxis()
.isHorizontal();
}
@Override
public Axis getRotationAxis(BlockState state) {
return isHorizontal(state) ? state.getValue(FACING).getAxis() : super.getRotationAxis(state);
return isHorizontal(state) ? state.getValue(FACING)
.getAxis() : super.getRotationAxis(state);
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
return isHorizontal(state) ? face == state.getValue(FACING).getOpposite()
: super.hasShaftTowards(world, pos, state, face);
return isHorizontal(state) ? face == state.getValue(FACING)
.getOpposite() : super.hasShaftTowards(world, pos, state, face);
}
@Override

View file

@ -242,7 +242,7 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
}
public boolean isNearInitialAngle() {
return Math.abs(angle) < 45 || Math.abs(angle) > 7 * 45;
return Math.abs(angle) < 22.5 || Math.abs(angle) > 360 - 22.5;
}
@Override

View file

@ -6,7 +6,9 @@ import com.simibubi.create.content.contraptions.processing.EmptyingByBasin;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.advancement.AdvancementBehaviour;
import com.simibubi.create.foundation.block.IBE;
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.ComparatorUtil;
import com.simibubi.create.foundation.blockEntity.behaviour.belt.DirectBeltInputBehaviour;
import com.simibubi.create.foundation.fluid.FluidHelper;
import net.minecraft.core.BlockPos;
@ -14,7 +16,9 @@ import net.minecraft.core.Direction;
import net.minecraft.world.Containers;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
@ -25,6 +29,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
@ -56,7 +61,8 @@ public class ItemDrainBlock extends Block implements IWrenchable, IBE<ItemDrainB
ItemStack heldItemStack = be.getHeldItemStack();
if (!worldIn.isClientSide && !heldItemStack.isEmpty()) {
player.getInventory().placeItemBackInInventory(heldItemStack);
player.getInventory()
.placeItemBackInInventory(heldItemStack);
be.heldItem = null;
be.notifyUpdate();
}
@ -64,6 +70,31 @@ public class ItemDrainBlock extends Block implements IWrenchable, IBE<ItemDrainB
});
}
@Override
public void updateEntityAfterFallOn(BlockGetter worldIn, Entity entityIn) {
super.updateEntityAfterFallOn(worldIn, entityIn);
if (!(entityIn instanceof ItemEntity))
return;
if (!entityIn.isAlive())
return;
if (entityIn.level.isClientSide)
return;
ItemEntity itemEntity = (ItemEntity) entityIn;
DirectBeltInputBehaviour inputBehaviour =
BlockEntityBehaviour.get(worldIn, entityIn.blockPosition(), DirectBeltInputBehaviour.TYPE);
if (inputBehaviour == null)
return;
Vec3 deltaMovement = entityIn.getDeltaMovement()
.multiply(1, 0, 1)
.normalize();
Direction nearest = Direction.getNearest(deltaMovement.x, deltaMovement.y, deltaMovement.z);
ItemStack remainder = inputBehaviour.handleInsertion(itemEntity.getItem(), nearest, false);
itemEntity.setItem(remainder);
if (remainder.isEmpty())
itemEntity.discard();
}
protected InteractionResult tryExchange(Level worldIn, Player player, InteractionHand handIn, ItemStack heldItem,
ItemDrainBlockEntity be) {
if (FluidHelper.tryEmptyItemIntoTE(worldIn, player, handIn, heldItem, be))

View file

@ -6,17 +6,19 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.jozufozu.flywheel.util.Color;
import com.mojang.blaze3d.platform.Window;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllSpecialTextures;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.curiosities.tools.BlueprintOverlayRenderer;
import com.simibubi.create.content.logistics.trains.BezierConnection;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Color;
import com.simibubi.create.foundation.utility.Components;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
@ -27,6 +29,7 @@ import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@ -35,6 +38,7 @@ import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Inventory;
@ -42,6 +46,7 @@ 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.UseOnContext;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
@ -53,6 +58,9 @@ import net.minecraft.world.phys.HitResult.Type;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.gui.ForgeIngameGui;
import net.minecraftforge.client.gui.IIngameOverlay;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import net.minecraftforge.items.ItemHandlerHelper;
public class TrackPlacement {
@ -98,6 +106,8 @@ public class TrackPlacement {
static int hoveringAngle;
static ItemStack lastItem;
static int extraTipWarmup;
public static PlacementInfo tryConnect(Level level, Player player, BlockPos pos2, BlockState state2,
ItemStack stack, boolean girder, boolean maximiseTurn) {
Vec3 lookVec = player.getLookAngle();
@ -447,10 +457,6 @@ public class TrackPlacement {
BlockItem paveItem = (BlockItem) offhandItem.getItem();
paveTracks(level, info, paveItem, false);
}
if (info.curve != null && info.curve.getLength() > 29)
AllAdvancements.LONG_BEND.awardTo(player);
return placeTracks(level, info, state1, state2, targetPos1, targetPos2, false);
}
@ -576,6 +582,8 @@ public class TrackPlacement {
LocalPlayer player = Minecraft.getInstance().player;
ItemStack stack = player.getMainHandItem();
HitResult hitResult = Minecraft.getInstance().hitResult;
int restoreWarmup = extraTipWarmup;
extraTipWarmup = 0;
if (hitResult == null)
return;
@ -609,8 +617,14 @@ public class TrackPlacement {
if (!(hitState.getBlock() instanceof TrackBlock))
return;
extraTipWarmup = restoreWarmup;
boolean maxTurns = Minecraft.getInstance().options.keySprint.isDown();
PlacementInfo info = tryConnect(level, player, pos, hitState, stack, false, maxTurns);
if (extraTipWarmup < 20)
extraTipWarmup++;
if (!info.valid || !hoveringMaxed && (info.end1Extent == 0 || info.end2Extent == 0))
extraTipWarmup = 0;
if (!player.isCreative() && (info.valid || !info.hasRequiredTracks || !info.hasRequiredPavement))
BlueprintOverlayRenderer.displayTrackRequirements(info, player.getOffhandItem());
@ -761,4 +775,38 @@ public class TrackPlacement {
.colored(color);
}
@OnlyIn(Dist.CLIENT)
public static final IIngameOverlay OVERLAY = TrackPlacement::renderOverlay;
@OnlyIn(Dist.CLIENT)
public static void renderOverlay(ForgeIngameGui gui, PoseStack poseStack, float partialTicks, int width,
int height) {
Minecraft mc = Minecraft.getInstance();
if (mc.options.hideGui || mc.gameMode.getPlayerMode() == GameType.SPECTATOR)
return;
if (hoveringPos == null)
return;
if (cached == null || cached.curve == null || !cached.valid)
return;
if (extraTipWarmup < 4)
return;
if (ObfuscationReflectionHelper.getPrivateValue(Gui.class, gui,
"toolHighlightTimer") instanceof Integer toolHighlightTimer && toolHighlightTimer > 0)
return;
boolean active = mc.options.keySprint.isDown();
MutableComponent text = Lang.translateDirect("track.hold_for_smooth_curve", Components.keybind("key.sprint")
.withStyle(active ? ChatFormatting.WHITE : ChatFormatting.GRAY));
Window window = mc.getWindow();
int x = (window.getGuiScaledWidth() - gui.getFont()
.width(text)) / 2;
int y = window.getGuiScaledHeight() - 61;
Color color = new Color(0x4ADB4A).setAlpha(Mth.clamp((extraTipWarmup - 4) / 3f, 0.1f, 1));
gui.getFont()
.draw(poseStack, text, x, y, color.getRGB());
}
}

View file

@ -565,16 +565,10 @@ public class AllAdvancements implements DataProvider {
.after(STURDY_SHEET)
.special(EXPERT)),
LONG_BEND = create("long_bend", b -> b.icon(AllBlocks.TRACK)
.title("The Longest Bend")
.description("Create a curved track section that spans more than 30 blocks in length")
.after(TRACK_CRAFTING)
.special(EXPERT)),
LONG_TRAIN = create("long_train", b -> b.icon(Items.MINECART)
.title("Ambitious Endeavours")
.description("Create a Train with at least 6 carriages")
.after(LONG_BEND)
.after(TRACK_CRAFTING)
.special(EXPERT)),
LONG_TRAVEL = create("long_travel", b -> b.icon(AllBlocks.SEATS.get(DyeColor.GREEN))

View file

@ -250,7 +250,6 @@ public class BuilderTransformers {
.texture("3", p.modLoc("block/valve_handle/valve_handle_" + variant)));
})
.tag(AllBlockTags.BRITTLE.tag, AllBlockTags.VALVE_HANDLES.tag)
.transform(BlockStressDefaults.setCapacity(8.0))
.transform(BlockStressDefaults.setGeneratorSpeed(ValveHandleBlock::getSpeedRange))
.onRegister(ItemUseOverrides::addBlock)
.item()

View file

@ -8,8 +8,10 @@ import java.util.List;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.IRotate.StressImpact;
import com.simibubi.create.content.contraptions.components.crank.ValveHandleBlock;
import com.simibubi.create.content.contraptions.components.steam.SteamEngineBlock;
import com.simibubi.create.content.contraptions.goggles.GogglesItem;
import com.simibubi.create.foundation.block.BlockStressValues;
@ -71,6 +73,9 @@ public class KineticStats implements TooltipModifier {
showStressImpact = true;
}
if (block instanceof ValveHandleBlock)
block = AllBlocks.COPPER_VALVE_HANDLE.get();
boolean hasStressImpact =
StressImpact.isEnabled() && showStressImpact && BlockStressValues.getImpact(block) > 0;
boolean hasStressCapacity = StressImpact.isEnabled() && BlockStressValues.hasCapacity(block);

View file

@ -734,6 +734,7 @@
"create.track.turn_start": "Cannot start connection from a Turn",
"create.track.not_enough_tracks": "Not holding enough tracks",
"create.track.not_enough_pavement": "Not holding enough pavement blocks",
"create.track.hold_for_smooth_curve": "Hold %1$s for maximized turn",
"create.portal_track.failed": "Cannot place portal track:",
"create.portal_track.missing": "Target portal not generated yet",