In good Shape
- Improved selection boundaries of Track blocks
This commit is contained in:
parent
517fad7a62
commit
99a6836a1d
9 changed files with 414 additions and 41 deletions
|
@ -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(),
|
||||
|
|
|
@ -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<IBlockRenderProperties> 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)
|
||||
|
|
|
@ -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<VoxelShape> 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
"HeavyBootsOnPlayerMixin",
|
||||
"ModelDataRefreshMixin",
|
||||
"WindowResizeMixin",
|
||||
"GameRendererMixin",
|
||||
"accessor.AgeableListModelAccessor",
|
||||
"accessor.GameRendererAccessor",
|
||||
"accessor.ParticleEngineAccessor"
|
||||
|
|
Loading…
Reference in a new issue