From 99a6836a1db4bc4267a1e67a62ab6be3458d062e Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Wed, 13 Apr 2022 03:06:35 +0200 Subject: [PATCH] In good Shape - Improved selection boundaries of Track blocks --- .../java/com/simibubi/create/AllShapes.java | 48 ++++--- .../logistics/trains/track/TrackBlock.java | 59 ++++++++- .../trains/track/TrackBlockOutline.java | 118 ++++++++++++++++++ .../trains/track/TrackVoxelShapes.java | 56 +++++++++ .../create/foundation/block/BigOutlines.java | 98 +++++++++++++++ .../block/render/ReducedDestroyEffects.java | 43 +++---- .../foundation/mixin/GameRendererMixin.java | 23 ++++ .../foundation/utility/RaycastHelper.java | 9 +- src/main/resources/create.mixins.json | 1 + 9 files changed, 414 insertions(+), 41 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockOutline.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/trains/track/TrackVoxelShapes.java create mode 100644 src/main/java/com/simibubi/create/foundation/block/BigOutlines.java create mode 100644 src/main/java/com/simibubi/create/foundation/mixin/GameRendererMixin.java diff --git a/src/main/java/com/simibubi/create/AllShapes.java b/src/main/java/com/simibubi/create/AllShapes.java index dce8d8766..ee27cd7be 100644 --- a/src/main/java/com/simibubi/create/AllShapes.java +++ b/src/main/java/com/simibubi/create/AllShapes.java @@ -1,5 +1,6 @@ package com.simibubi.create; +import static net.minecraft.core.Direction.EAST; import static net.minecraft.core.Direction.NORTH; import static net.minecraft.core.Direction.SOUTH; import static net.minecraft.core.Direction.UP; @@ -7,6 +8,7 @@ import static net.minecraft.core.Direction.UP; import java.util.function.BiFunction; import com.simibubi.create.content.logistics.block.chute.ChuteShapes; +import com.simibubi.create.content.logistics.trains.track.TrackVoxelShapes; import com.simibubi.create.foundation.utility.VoxelShaper; import net.minecraft.core.Direction; @@ -28,11 +30,12 @@ public class AllShapes { CASING_13PX = shape(0, 0, 0, 16, 13, 16).forDirectional(), CASING_12PX = shape(0, 0, 0, 16, 12, 16).forDirectional(), CASING_11PX = shape(0, 0, 0, 16, 11, 16).forDirectional(), - MOTOR_BLOCK = shape(3, 0, 3, 13, 14, 13).forDirectional(), TRACK = shape(0, 0, 0, 16, 4, 16).forDirectional(), + MOTOR_BLOCK = shape(3, 0, 3, 13, 14, 13).forDirectional(), + FOUR_VOXEL_POLE = shape(6, 0, 6, 10, 16, 10).forAxis(), SIX_VOXEL_POLE = shape(5, 0, 5, 11, 16, 11).forAxis(), EIGHT_VOXEL_POLE = shape(4, 0, 4, 12, 16, 12).forAxis(), TEN_VOXEL_POLE = shape(3, 0, 3, 13, 16, 13).forAxis(), FURNACE_ENGINE = shape(1, 1, 0, 15, 15, 16).add(0, 0, 9, 16, 16, 14) - .forHorizontal(Direction.SOUTH), + .forHorizontal(SOUTH), PORTABLE_STORAGE_INTERFACE = shape(0, 0, 0, 16, 14, 16).forDirectional(), PULLEY = shape(0, 0, 0, 16, 16, 2).add(1, 1, 2, 15, 15, 14) .add(2, 13, 2, 14, 16, 14) @@ -87,19 +90,19 @@ public class AllShapes { .add(5, 14, 4, 11, 15, 10) .add(5, 15, 5, 11, 16, 9) .add(5, 16, 6, 11, 17, 8) - .forHorizontal(Direction.SOUTH), + .forHorizontal(SOUTH), SMART_FLUID_PIPE_WALL = shape(4, 0, 4, 12, 16, 12).add(3, 3, 3, 13, 13, 13) .add(5, 5, 13, 11, 13, 14) .add(5, 6, 14, 11, 12, 15) .add(5, 7, 15, 11, 11, 16) .add(5, 8, 16, 11, 10, 17) - .forHorizontal(Direction.SOUTH), + .forHorizontal(SOUTH), SMART_FLUID_PIPE_CEILING = shape(4, 4, 0, 12, 12, 16).add(3, 3, 3, 13, 13, 13) .add(5, 2, 3, 11, 3, 11) .add(5, 1, 4, 11, 2, 10) .add(5, 0, 5, 11, 1, 9) .add(5, -1, 6, 11, 0, 8) - .forHorizontal(Direction.SOUTH), + .forHorizontal(SOUTH), PUMP = shape(2, 0, 2, 14, 5, 14).add(4, 0, 4, 12, 16, 12) .add(3, 12, 3, 13, 16, 13) .forDirectional(Direction.UP), @@ -125,9 +128,9 @@ public class AllShapes { NIXIE_TUBE_CEILING = shape(9, 4, 5, 15, 16, 11).add(1, 4, 5, 7, 16, 11) .forHorizontalAxis(), NIXIE_TUBE_WALL = shape(5, 9, 0, 11, 15, 12).add(5, 1, 0, 11, 7, 12) - .forHorizontal(Direction.SOUTH), + .forHorizontal(SOUTH), - FLAP_DISPLAY = shape(0, 0, 3, 16, 16, 13).forHorizontal(Direction.SOUTH), + FLAP_DISPLAY = shape(0, 0, 3, 16, 16, 13).forHorizontal(SOUTH), DATA_GATHERER = shape(1, 0, 1, 15, 6, 15).add(3, 5, 3, 13, 9, 13) .forDirectional(), @@ -140,7 +143,11 @@ public class AllShapes { .forHorizontalAxis(), STEAM_ENGINE_WALL = shape(1, 1, 0, 15, 15, 3).add(3, 3, 0, 13, 13, 15) .add(1, 4, 5, 15, 12, 13) - .forHorizontal(Direction.SOUTH) + .forHorizontal(SOUTH), + + TRACK_ORTHO = shape(TrackVoxelShapes.orthogonal()).forHorizontal(NORTH), + TRACK_ASC = shape(TrackVoxelShapes.ascending()).forHorizontal(SOUTH), + TRACK_DIAG = shape(TrackVoxelShapes.diagonal()).forHorizontal(SOUTH) ; @@ -165,11 +172,19 @@ public class AllShapes { // Static Block Shapes public static final VoxelShape - BASIN_BLOCK_SHAPE = shape(0, 2, 0, 16, 16, 16).erase(2, 2, 2, 14, 16, 14) - .add(2, 0, 2, 14, 2, 14) - .build(), BASIN_RAYTRACE_SHAPE = - shape(0, 2, 0, 16, 16, 16).add(2, 0, 2, 14, 2, 14) - .build(), + TRACK_CROSS = shape(TRACK_ORTHO.get(SOUTH)).add(TRACK_ORTHO.get(EAST)) + .build(), + + TRACK_CROSS_DIAG = shape(TRACK_DIAG.get(SOUTH)).add(TRACK_DIAG.get(EAST)) + .build(), + + TRACK_FALLBACK = shape(0, 0, 0, 16, 4, 16).build(), + + BASIN_BLOCK_SHAPE = shape(0, 2, 0, 16, 16, 16).erase(2, 2, 2, 14, 16, 14) + .add(2, 0, 2, 14, 2, 14) + .build(), + BASIN_RAYTRACE_SHAPE = shape(0, 2, 0, 16, 16, 16).add(2, 0, 2, 14, 2, 14) + .build(), BASIN_COLLISION_SHAPE = shape(0, 2, 0, 16, 13, 16).erase(2, 5, 2, 14, 16, 14) .add(2, 0, 2, 14, 2, 14) .build(), @@ -240,7 +255,12 @@ public class AllShapes { // More Shapers public static final VoxelShaper - MECHANICAL_PISTON_HEAD = shape(PISTON_HEAD).forDirectional(), MECHANICAL_PISTON = CASING_12PX, + TRACK_CROSS_ORTHO_DIAG = shape(TRACK_DIAG.get(SOUTH)).add(TRACK_ORTHO.get(EAST)) + .forHorizontal(SOUTH), TRACK_CROSS_DIAG_ORTHO = + shape(TRACK_DIAG.get(SOUTH)).add(TRACK_ORTHO.get(SOUTH)) + .forHorizontal(SOUTH), + + MECHANICAL_PISTON_HEAD = shape(PISTON_HEAD).forDirectional(), MECHANICAL_PISTON = CASING_12PX, MECHANICAL_PISTON_EXTENDED = shape(PISTON_EXTENDED).forDirectional(), SMALL_GEAR = shape(SMALL_GEAR_SHAPE).add(SIX_VOXEL_POLE.get(Axis.Y)) .forAxis(), diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java index c71d2f7c4..ad776cd5b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java @@ -1,11 +1,18 @@ package com.simibubi.create.content.logistics.trains.track; +import static com.simibubi.create.AllShapes.TRACK_ASC; +import static com.simibubi.create.AllShapes.TRACK_CROSS_DIAG_ORTHO; +import static com.simibubi.create.AllShapes.TRACK_CROSS_ORTHO_DIAG; +import static com.simibubi.create.AllShapes.TRACK_DIAG; +import static com.simibubi.create.AllShapes.TRACK_ORTHO; + import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Random; +import java.util.function.Consumer; import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.util.transform.TransformStack; @@ -25,6 +32,7 @@ import com.simibubi.create.content.logistics.trains.TrackNodeLocation.Discovered import com.simibubi.create.content.logistics.trains.TrackPropagator; import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour.RenderedTrackOverlayType; import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity; +import com.simibubi.create.foundation.block.render.ReducedDestroyEffects; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VecHelper; @@ -64,6 +72,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.ticks.LevelTickAccess; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.IBlockRenderProperties; public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrackBlock { @@ -81,6 +90,11 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac super.createBlockStateDefinition(p_49915_.add(SHAPE, HAS_TURN)); } + @OnlyIn(Dist.CLIENT) + public void initializeClient(Consumer consumer) { + consumer.accept(new ReducedDestroyEffects()); + } + @Override public BlockState getStateForPlacement(BlockPlaceContext ctx) { BlockState stateForPlacement = super.getStateForPlacement(ctx); @@ -260,7 +274,48 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac @Override public VoxelShape getShape(BlockState state, BlockGetter p_60556_, BlockPos p_60557_, CollisionContext p_60558_) { - return AllShapes.TRACK.get(Direction.UP); + return getFullShape(state); + } + + @Override + public VoxelShape getInteractionShape(BlockState state, BlockGetter pLevel, BlockPos pPos) { + return getFullShape(state); + } + + private VoxelShape getFullShape(BlockState state) { + switch (state.getValue(SHAPE)) { + case AE: + return TRACK_ASC.get(Direction.EAST); + case AW: + return TRACK_ASC.get(Direction.WEST); + case AN: + return TRACK_ASC.get(Direction.NORTH); + case AS: + return TRACK_ASC.get(Direction.SOUTH); + case CR_D: + return AllShapes.TRACK_CROSS_DIAG; + case CR_NDX: + return TRACK_CROSS_ORTHO_DIAG.get(Direction.SOUTH); + case CR_NDZ: + return TRACK_CROSS_DIAG_ORTHO.get(Direction.SOUTH); + case CR_O: + return AllShapes.TRACK_CROSS; + case CR_PDX: + return TRACK_CROSS_DIAG_ORTHO.get(Direction.EAST); + case CR_PDZ: + return TRACK_CROSS_ORTHO_DIAG.get(Direction.EAST); + case ND: + return TRACK_DIAG.get(Direction.SOUTH); + case PD: + return TRACK_DIAG.get(Direction.EAST); + case XO: + return TRACK_ORTHO.get(Direction.EAST); + case ZO: + return TRACK_ORTHO.get(Direction.SOUTH); + case NONE: + default: + } + return AllShapes.TRACK_FALLBACK; } @Override @@ -296,7 +351,7 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac TrackRemoval.wrenched(context.getClickedPos()); return InteractionResult.SUCCESS; } - + @Override public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) { if (context.getLevel().isClientSide) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockOutline.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockOutline.java new file mode 100644 index 000000000..31fc38a82 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockOutline.java @@ -0,0 +1,118 @@ +package com.simibubi.create.content.logistics.trains.track; + +import java.util.function.Consumer; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllShapes; +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.DrawSelectionEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber(Dist.CLIENT) +public class TrackBlockOutline { + + @SubscribeEvent + public static void drawCustomBlockSelection(DrawSelectionEvent.HighlightBlock event) { + Minecraft mc = Minecraft.getInstance(); + BlockHitResult target = event.getTarget(); + BlockPos pos = target.getBlockPos(); + BlockState blockstate = mc.level.getBlockState(pos); + + if (!(blockstate.getBlock() instanceof TrackBlock)) + return; + if (!mc.level.getWorldBorder() + .isWithinBounds(pos)) + return; + + VertexConsumer vb = event.getMultiBufferSource() + .getBuffer(RenderType.lines()); + PoseStack ms = event.getPoseStack(); + + ms.pushPose(); + Vec3 camPos = event.getCamera() + .getPosition(); + + ms.translate(pos.getX() - camPos.x, pos.getY() - camPos.y, pos.getZ() - camPos.z); + + walkShapes(blockstate.getValue(TrackBlock.SHAPE), TransformStack.cast(ms), s -> { + event.setCanceled(true); + PoseStack.Pose transform = ms.last(); + s.forAllEdges((x1, y1, z1, x2, y2, z2) -> { + float xDiff = (float) (x2 - x1); + float yDiff = (float) (y2 - y1); + float zDiff = (float) (z2 - z1); + float length = Mth.sqrt(xDiff * xDiff + yDiff * yDiff + zDiff * zDiff); + + xDiff /= length; + yDiff /= length; + zDiff /= length; + + vb.vertex(transform.pose(), (float) x1, (float) y1, (float) z1) + .color(0f, 0f, 0f, .4f) + .normal(transform.normal(), xDiff, yDiff, zDiff) + .endVertex(); + vb.vertex(transform.pose(), (float) x2, (float) y2, (float) z2) + .color(0f, 0f, 0f, .4f) + .normal(transform.normal(), xDiff, yDiff, zDiff) + .endVertex(); + + }); + }); + + ms.popPose(); + + } + + private static final VoxelShape LONG_CROSS = + Shapes.or(TrackVoxelShapes.longOrthogonalZ(), TrackVoxelShapes.longOrthogonalX()); + private static final VoxelShape LONG_ORTHO = TrackVoxelShapes.longOrthogonalZ(); + + private static void walkShapes(TrackShape shape, TransformStack msr, Consumer renderer) { + float angle45 = Mth.PI / 4; + + if (shape == TrackShape.XO || shape == TrackShape.CR_NDX || shape == TrackShape.CR_PDX) + renderer.accept(AllShapes.TRACK_ORTHO.get(Direction.EAST)); + else if (shape == TrackShape.ZO || shape == TrackShape.CR_NDZ || shape == TrackShape.CR_PDZ) + renderer.accept(AllShapes.TRACK_ORTHO.get(Direction.SOUTH)); + + if (shape == TrackShape.PD || shape == TrackShape.CR_PDX || shape == TrackShape.CR_PDZ) { + msr.rotateCentered(Direction.UP, angle45); + renderer.accept(LONG_ORTHO); + } else if (shape == TrackShape.ND || shape == TrackShape.CR_NDX || shape == TrackShape.CR_NDZ) { + msr.rotateCentered(Direction.UP, -Mth.PI / 4); + renderer.accept(LONG_ORTHO); + } + + if (shape == TrackShape.CR_O) + renderer.accept(AllShapes.TRACK_CROSS); + else if (shape == TrackShape.CR_D) { + msr.rotateCentered(Direction.UP, angle45); + renderer.accept(LONG_CROSS); + } + + if (!(shape == TrackShape.AE || shape == TrackShape.AN || shape == TrackShape.AW || shape == TrackShape.AS)) + return; + + msr.translate(0, 1, 0); + msr.rotateCentered(Direction.UP, Mth.PI - AngleHelper.rad(shape.getModelRotation())); + msr.rotateXRadians(angle45); + msr.translate(0, -3 / 16f, 1 / 16f); + renderer.accept(LONG_ORTHO); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackVoxelShapes.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackVoxelShapes.java new file mode 100644 index 000000000..0f796a2a8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackVoxelShapes.java @@ -0,0 +1,56 @@ +package com.simibubi.create.content.logistics.trains.track; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.phys.shapes.BooleanOp; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class TrackVoxelShapes { + + public static VoxelShape orthogonal() { + return Block.box(-14, 0, 0, 16 + 14, 4, 16); + } + + public static VoxelShape longOrthogonalX() { + return Block.box(-3.3, 0, -14, 19.3, 4, 16 + 14); + } + + public static VoxelShape longOrthogonalZ() { + return Block.box(-14, 0, -3.3, 16 + 14, 4, 19.3); + } + + public static VoxelShape ascending() { + VoxelShape shape = Block.box(-14, 0, 0, 16 + 14, 4, 4); + VoxelShape[] shapes = new VoxelShape[6]; + for (int i = 0; i < 6; i++) { + int off = (i + 1) * 2; + shapes[i] = Block.box(-14, off, off, 16 + 14, 4 + off, 4 + off); + } + return Shapes.or(shape, shapes); + } + + public static VoxelShape diagonal() { + VoxelShape shape = Block.box(0, 0, 0, 16, 4, 16); + VoxelShape[] shapes = new VoxelShape[12]; + int off = 0; + + for (int i = 0; i < 6; i++) { + off = (i + 1) * 2; + shapes[i * 2] = Block.box(off, 0, off, 16 + off, 4, 16 + off); + shapes[i * 2 + 1] = Block.box(-off, 0, -off, 16 - off, 4, 16 - off); + } + + shape = Shapes.or(shape, shapes); + + off = 10 * 2; + shape = Shapes.join(shape, Block.box(off, 0, off, 16 + off, 4, 16 + off), BooleanOp.ONLY_FIRST); + shape = Shapes.join(shape, Block.box(-off, 0, -off, 16 - off, 4, 16 - off), BooleanOp.ONLY_FIRST); + + off = 4 * 2; + shape = Shapes.or(shape, Block.box(off, 0, off, 16 + off, 4, 16 + off)); + shape = Shapes.or(shape, Block.box(-off, 0, -off, 16 - off, 4, 16 - off)); + + return shape.optimize(); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/block/BigOutlines.java b/src/main/java/com/simibubi/create/foundation/block/BigOutlines.java new file mode 100644 index 000000000..b001651a6 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/block/BigOutlines.java @@ -0,0 +1,98 @@ +package com.simibubi.create.foundation.block; + +import com.simibubi.create.content.logistics.trains.track.TrackBlock; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.RaycastHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.ForgeMod; + +public class BigOutlines { + + static BlockHitResult result = null; + + public static void pick() { + Minecraft mc = Minecraft.getInstance(); + if (!(mc.cameraEntity instanceof LocalPlayer player)) + return; + if (mc.level == null) + return; + + result = null; + + Vec3 origin = player.getEyePosition(AnimationTickHolder.getPartialTicks(mc.level)); + + double maxRange = mc.hitResult == null ? Double.MAX_VALUE + : mc.hitResult.getLocation() + .distanceToSqr(origin); + + AttributeInstance range = player.getAttribute(ForgeMod.REACH_DISTANCE.get()); + Vec3 target = RaycastHelper.getTraceTarget(player, Math.min(maxRange, range.getValue()) + 1, origin); + + RaycastHelper.rayTraceUntil(origin, target, pos -> { + MutableBlockPos p = BlockPos.ZERO.mutable(); + + for (int x = -1; x <= 1; x++) { + for (int z = -1; z <= 1; z++) { + p.set(pos.getX() + x, pos.getY(), pos.getZ() + z); + BlockState blockState = mc.level.getBlockState(p); + + // Could be a dedicated interface for big blocks + if (!(blockState.getBlock() instanceof TrackBlock)) + continue; + + BlockHitResult hit = blockState.getInteractionShape(mc.level, p) + .clip(origin, target, p.immutable()); + if (hit == null) + continue; + + if (result != null && Vec3.atCenterOf(p) + .distanceToSqr(origin) >= Vec3.atCenterOf(result.getBlockPos()) + .distanceToSqr(origin)) + continue; + + Vec3 vec = hit.getLocation(); + double interactionDist = vec.distanceToSqr(origin); + if (interactionDist >= maxRange) + continue; + + BlockPos hitPos = hit.getBlockPos(); + + // pacifies ServerGamePacketListenerImpl.handleUseItemOn + vec = vec.subtract(Vec3.atCenterOf(hitPos)); + vec = VecHelper.clampComponentWise(vec, 1); + vec = vec.add(Vec3.atCenterOf(hitPos)); + + result = new BlockHitResult(vec, hit.getDirection(), hitPos, hit.isInside()); + } + } + + return result != null; + }); + + if (result != null) + mc.hitResult = result; + } + + static boolean isValidPos(Player player, BlockPos pos) { + // verify that the server will accept the fake result + double x = player.getX() - (pos.getX() + .5); + double y = player.getY() - (pos.getY() + .5) + 1.5; + double z = player.getZ() - (pos.getZ() + .5); + double distSqr = x * x + y * y + z * z; + double maxDist = player.getAttribute(ForgeMod.REACH_DISTANCE.get()) + .getValue() + 1; + maxDist *= maxDist; + return distSqr <= maxDist; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/block/render/ReducedDestroyEffects.java b/src/main/java/com/simibubi/create/foundation/block/render/ReducedDestroyEffects.java index a04d0e1fd..a8daefe44 100644 --- a/src/main/java/com/simibubi/create/foundation/block/render/ReducedDestroyEffects.java +++ b/src/main/java/com/simibubi/create/foundation/block/render/ReducedDestroyEffects.java @@ -13,7 +13,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.client.IBlockRenderProperties; public class ReducedDestroyEffects implements IBlockRenderProperties { - + @Override public boolean addDestroyEffects(BlockState state, Level worldIn, BlockPos pos, ParticleEngine manager) { if (!(worldIn instanceof ClientLevel)) @@ -27,34 +27,35 @@ public class ReducedDestroyEffects implements IBlockRenderProperties { if (state.isAir()) return true; - voxelshape.forAllBoxes((p_172273_, p_172274_, p_172275_, p_172276_, p_172277_, p_172278_) -> { - double d1 = Math.min(1.0D, p_172276_ - p_172273_); - double d2 = Math.min(1.0D, p_172277_ - p_172274_); - double d3 = Math.min(1.0D, p_172278_ - p_172275_); - int i = Math.max(2, Mth.ceil(d1 / 0.25D)); - int j = Math.max(2, Mth.ceil(d2 / 0.25D)); - int k = Math.max(2, Mth.ceil(d3 / 0.25D)); + voxelshape.forAllBoxes((x1, y1, z1, x2, y2, z2) -> { + double w = x2 - x1; + double h = y2 - y1; + double l = z2 - z1; + int xParts = Math.max(2, Mth.ceil(Math.min(1, w) * 4)); + int yParts = Math.max(2, Mth.ceil(Math.min(1, h) * 4)); + int zParts = Math.max(2, Mth.ceil(Math.min(1, l) * 4)); - for (int l = 0; l < i; ++l) { - for (int i1 = 0; i1 < j; ++i1) { - for (int j1 = 0; j1 < k; ++j1) { + for (int xIndex = 0; xIndex < xParts; ++xIndex) { + for (int yIndex = 0; yIndex < yParts; ++yIndex) { + for (int zIndex = 0; zIndex < zParts; ++zIndex) { if (world.random.nextDouble() > chance) continue; - double d4 = ((double) l + 0.5D) / (double) i; - double d5 = ((double) i1 + 0.5D) / (double) j; - double d6 = ((double) j1 + 0.5D) / (double) k; - double d7 = d4 * d1 + p_172273_; - double d8 = d5 * d2 + p_172274_; - double d9 = d6 * d3 + p_172275_; - manager.add(new TerrainParticle(world, pos.getX() + d7, pos.getY() + d8, pos.getZ() + d9, - d4 - 0.5D, d5 - 0.5D, d6 - 0.5D, state, pos).updateSprite(state, pos)); + double d4 = (xIndex + .5) / xParts; + double d5 = (yIndex + .5) / yParts; + double d6 = (zIndex + .5) / zParts; + double x = pos.getX() + d4 * w + x1; + double y = pos.getY() + d5 * h + y1; + double z = pos.getZ() + d6 * l + z1; + + manager.add(new TerrainParticle(world, x, y, z, d4 - 0.5D, d5 - 0.5D, d6 - 0.5D, state, pos) + .updateSprite(state, pos)); } } } }); - + return true; } - + } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/GameRendererMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/GameRendererMixin.java new file mode 100644 index 000000000..34500a6c0 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/GameRendererMixin.java @@ -0,0 +1,23 @@ +package com.simibubi.create.foundation.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.simibubi.create.foundation.block.BigOutlines; + +import net.minecraft.client.renderer.GameRenderer; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +@Mixin(GameRenderer.class) +public class GameRendererMixin { + + @Inject(at = @At("TAIL"), method = "pick") + private void bigShapePick(CallbackInfo ci) { + BigOutlines.pick(); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/RaycastHelper.java b/src/main/java/com/simibubi/create/foundation/utility/RaycastHelper.java index 458d4e032..de029842a 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/RaycastHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/RaycastHelper.java @@ -3,6 +3,7 @@ package com.simibubi.create.foundation.utility; import java.util.function.Predicate; import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; import net.minecraft.core.Direction; import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Player; @@ -64,10 +65,10 @@ public class RaycastHelper { int y = Mth.floor(start.y); int z = Mth.floor(start.z); - BlockPos currentPos = new BlockPos(x, y, z); + MutableBlockPos currentPos = new BlockPos(x, y, z).mutable(); if (predicate.test(currentPos)) - return new PredicateTraceResult(currentPos, Direction.getNearest(dx - x, dy - y, dz - z)); + return new PredicateTraceResult(currentPos.immutable(), Direction.getNearest(dx - x, dy - y, dz - z)); int remainingDistance = 200; @@ -158,10 +159,10 @@ public class RaycastHelper { x = Mth.floor(start.x) - (enumfacing == Direction.EAST ? 1 : 0); y = Mth.floor(start.y) - (enumfacing == Direction.UP ? 1 : 0); z = Mth.floor(start.z) - (enumfacing == Direction.SOUTH ? 1 : 0); - currentPos = new BlockPos(x, y, z); + currentPos.set(x, y, z); if (predicate.test(currentPos)) - return new PredicateTraceResult(currentPos, enumfacing); + return new PredicateTraceResult(currentPos.immutable(), enumfacing); } return new PredicateTraceResult(); diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index 4952c31b6..e7905533e 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -19,6 +19,7 @@ "HeavyBootsOnPlayerMixin", "ModelDataRefreshMixin", "WindowResizeMixin", + "GameRendererMixin", "accessor.AgeableListModelAccessor", "accessor.GameRendererAccessor", "accessor.ParticleEngineAccessor"