mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-28 16:06:48 +01:00
Rise of the Jank II
- Girders can now connect to brackets vertically - Fixed girders not updating connections when built with placement assist - Tracks now actively update girder shapes placed beneath the ties - Fixed bezier girder texture inconsistencies to the block models - Fixed flywheel rendered tracks creating headless instances - Fixed track not removing its tileentity properly when changing to basic state - Fixed track rendering not using the correct normals for diffuse - Fixed tracks not rendering in schematic previews - Tracks now transform correctly in schematics - Fixed tracks not validating for target track after placement via schematic - Tracks can now merge TE data when placed into each other via schematic - Fixed junctions not working correctly with graph building
This commit is contained in:
parent
2b750c943a
commit
2ca099ce6b
27 changed files with 574 additions and 283 deletions
|
@ -114,8 +114,9 @@ public class AllBlockPartials {
|
||||||
TRACK_SEGMENT_LEFT = block("track/segment_left"),
|
TRACK_SEGMENT_LEFT = block("track/segment_left"),
|
||||||
TRACK_SEGMENT_RIGHT = block("track/segment_right"),
|
TRACK_SEGMENT_RIGHT = block("track/segment_right"),
|
||||||
TRACK_TIE = block("track/tie"),
|
TRACK_TIE = block("track/tie"),
|
||||||
GIRDER_SEGMENT = block("metal_girder/segment"),
|
GIRDER_SEGMENT_TOP = block("metal_girder/segment_top"),
|
||||||
GIRDER_SEGMENT_2 = block("metal_girder/segment2"),
|
GIRDER_SEGMENT_MIDDLE = block("metal_girder/segment_middle"),
|
||||||
|
GIRDER_SEGMENT_BOTTOM = block("metal_girder/segment_bottom"),
|
||||||
|
|
||||||
TRACK_STATION_OVERLAY = block("track/station_overlay"),
|
TRACK_STATION_OVERLAY = block("track/station_overlay"),
|
||||||
TRACK_STATION_OVERLAY_DIAGONAL = block("track/station_overlay_diagonal"),
|
TRACK_STATION_OVERLAY_DIAGONAL = block("track/station_overlay_diagonal"),
|
||||||
|
|
|
@ -40,11 +40,11 @@ import net.minecraft.world.phys.Vec3;
|
||||||
public class StructureTransform {
|
public class StructureTransform {
|
||||||
|
|
||||||
// Assuming structures cannot be rotated around multiple axes at once
|
// Assuming structures cannot be rotated around multiple axes at once
|
||||||
Rotation rotation;
|
public Axis rotationAxis;
|
||||||
int angle;
|
public BlockPos offset;
|
||||||
Axis rotationAxis;
|
public int angle;
|
||||||
BlockPos offset;
|
public Rotation rotation;
|
||||||
Mirror mirror;
|
public Mirror mirror;
|
||||||
|
|
||||||
private StructureTransform(BlockPos offset, int angle, Axis axis, Rotation rotation, Mirror mirror) {
|
private StructureTransform(BlockPos offset, int angle, Axis axis, Rotation rotation, Mirror mirror) {
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
|
@ -88,6 +88,15 @@ public class StructureTransform {
|
||||||
mirror = Mirror.NONE;
|
mirror = Mirror.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vec3 applyWithoutOffsetUncentered(Vec3 localVec) {
|
||||||
|
Vec3 vec = localVec;
|
||||||
|
if (mirror != null)
|
||||||
|
vec = VecHelper.mirror(vec, mirror);
|
||||||
|
if (rotationAxis != null)
|
||||||
|
vec = VecHelper.rotate(vec, angle, rotationAxis);
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
public Vec3 applyWithoutOffset(Vec3 localVec) {
|
public Vec3 applyWithoutOffset(Vec3 localVec) {
|
||||||
Vec3 vec = localVec;
|
Vec3 vec = localVec;
|
||||||
if (mirror != null)
|
if (mirror != null)
|
||||||
|
|
|
@ -55,6 +55,11 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
|
||||||
this.bracket = Optional.of(state);
|
this.bracket = Optional.of(state);
|
||||||
reRender = true;
|
reRender = true;
|
||||||
tileEntity.notifyUpdate();
|
tileEntity.notifyUpdate();
|
||||||
|
Level world = getWorld();
|
||||||
|
if (world.isClientSide)
|
||||||
|
return;
|
||||||
|
tileEntity.getBlockState()
|
||||||
|
.updateNeighbourShapes(world, getPos(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void transformBracket(StructureTransform transform) {
|
public void transformBracket(StructureTransform transform) {
|
||||||
|
@ -71,10 +76,15 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
|
||||||
world.levelEvent(2001, getPos(), Block.getId(getBracket()));
|
world.levelEvent(2001, getPos(), Block.getId(getBracket()));
|
||||||
this.bracket = Optional.empty();
|
this.bracket = Optional.empty();
|
||||||
reRender = true;
|
reRender = true;
|
||||||
if (inOnReplacedContext)
|
if (inOnReplacedContext) {
|
||||||
tileEntity.sendData();
|
tileEntity.sendData();
|
||||||
else
|
return;
|
||||||
tileEntity.notifyUpdate();
|
}
|
||||||
|
tileEntity.notifyUpdate();
|
||||||
|
if (world.isClientSide)
|
||||||
|
return;
|
||||||
|
tileEntity.getBlockState()
|
||||||
|
.updateNeighbourShapes(world, getPos(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBracketPresent() {
|
public boolean isBracketPresent() {
|
||||||
|
|
|
@ -2,6 +2,8 @@ package com.simibubi.create.content.curiosities.girder;
|
||||||
|
|
||||||
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.Random;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllShapes;
|
import com.simibubi.create.AllShapes;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
|
@ -10,7 +12,7 @@ import com.simibubi.create.content.contraptions.relays.elementary.BracketedTileE
|
||||||
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
||||||
import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock;
|
import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.track.TrackBlock;
|
import com.simibubi.create.content.logistics.trains.track.TrackBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.track.TrackBlock.TrackShape;
|
import com.simibubi.create.content.logistics.trains.track.TrackShape;
|
||||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
|
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
|
||||||
|
@ -19,6 +21,7 @@ import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
|
||||||
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.server.level.ServerLevel;
|
||||||
import net.minecraft.sounds.SoundEvents;
|
import net.minecraft.sounds.SoundEvents;
|
||||||
import net.minecraft.sounds.SoundSource;
|
import net.minecraft.sounds.SoundSource;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
|
@ -107,6 +110,12 @@ public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenc
|
||||||
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState();
|
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(BlockState p_60462_, ServerLevel p_60463_, BlockPos p_60464_, Random p_60465_) {
|
||||||
|
Block.updateOrDestroy(p_60462_, Block.updateFromNeighbourShapes(p_60462_, p_60463_, p_60464_), p_60463_,
|
||||||
|
p_60464_, 3);
|
||||||
|
}
|
||||||
|
|
||||||
@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) {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.phys.BlockHitResult;
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
import net.minecraftforge.common.ForgeMod;
|
import net.minecraftforge.common.ForgeMod;
|
||||||
|
@ -94,7 +95,8 @@ public class GirderPlacementHelper implements IPlacementHelper {
|
||||||
.isReplaceable())
|
.isReplaceable())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return PlacementOffset.success(newPos, bState -> withAxis(bState, dir.getAxis()));
|
return PlacementOffset.success(newPos,
|
||||||
|
bState -> Block.updateFromNeighbourShapes(withAxis(bState, dir.getAxis()), world, newPos));
|
||||||
}
|
}
|
||||||
|
|
||||||
return PlacementOffset.fail();
|
return PlacementOffset.fail();
|
||||||
|
|
|
@ -4,7 +4,7 @@ import java.util.Iterator;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.repack.joml.Math;
|
import com.jozufozu.flywheel.repack.joml.Math;
|
||||||
import com.jozufozu.flywheel.util.transform.MatrixTransformStack;
|
import com.jozufozu.flywheel.util.transform.MatrixTransformStack;
|
||||||
import com.mojang.math.Matrix4f;
|
import com.mojang.blaze3d.vertex.PoseStack.Pose;
|
||||||
import com.simibubi.create.content.logistics.trains.track.TrackRenderer;
|
import com.simibubi.create.content.logistics.trains.track.TrackRenderer;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
@ -24,7 +24,6 @@ import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
|
|
||||||
public Couple<BlockPos> tePositions;
|
public Couple<BlockPos> tePositions;
|
||||||
public Couple<Boolean> trackEnds;
|
|
||||||
public Couple<Vec3> starts;
|
public Couple<Vec3> starts;
|
||||||
public Couple<Vec3> axes;
|
public Couple<Vec3> axes;
|
||||||
public Couple<Vec3> normals;
|
public Couple<Vec3> normals;
|
||||||
|
@ -44,37 +43,37 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
private double handleLength;
|
private double handleLength;
|
||||||
|
|
||||||
public BezierConnection(Couple<BlockPos> positions, Couple<Vec3> starts, Couple<Vec3> axes, Couple<Vec3> normals,
|
public BezierConnection(Couple<BlockPos> positions, Couple<Vec3> starts, Couple<Vec3> axes, Couple<Vec3> normals,
|
||||||
Couple<Boolean> targets, boolean primary, boolean girder) {
|
boolean primary, boolean girder) {
|
||||||
tePositions = positions;
|
tePositions = positions;
|
||||||
this.starts = starts;
|
this.starts = starts;
|
||||||
this.axes = axes;
|
this.axes = axes;
|
||||||
this.normals = normals;
|
this.normals = normals;
|
||||||
this.trackEnds = targets;
|
|
||||||
this.primary = primary;
|
this.primary = primary;
|
||||||
this.hasGirder = girder;
|
this.hasGirder = girder;
|
||||||
resolved = false;
|
resolved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BezierConnection secondary() {
|
public BezierConnection secondary() {
|
||||||
return new BezierConnection(tePositions.swap(), starts.swap(), axes.swap(), normals.swap(), trackEnds.swap(),
|
return new BezierConnection(tePositions.swap(), starts.swap(), axes.swap(), normals.swap(), false, hasGirder);
|
||||||
false, hasGirder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BezierConnection(CompoundTag compound) {
|
public BezierConnection(CompoundTag compound, BlockPos localTo) {
|
||||||
this(Couple.deserializeEach(compound.getList("Positions", Tag.TAG_COMPOUND), NbtUtils::readBlockPos),
|
this(Couple.deserializeEach(compound.getList("Positions", Tag.TAG_COMPOUND), NbtUtils::readBlockPos)
|
||||||
Couple.deserializeEach(compound.getList("Starts", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
|
.map(b -> b.offset(localTo)),
|
||||||
|
Couple.deserializeEach(compound.getList("Starts", Tag.TAG_COMPOUND), VecHelper::readNBTCompound)
|
||||||
|
.map(v -> v.add(Vec3.atLowerCornerOf(localTo))),
|
||||||
Couple.deserializeEach(compound.getList("Axes", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
|
Couple.deserializeEach(compound.getList("Axes", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
|
||||||
Couple.deserializeEach(compound.getList("Normals", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
|
Couple.deserializeEach(compound.getList("Normals", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
|
||||||
Couple.create(compound.getBoolean("TrackEnd1"), compound.getBoolean("TrackEnd2")),
|
|
||||||
compound.getBoolean("Primary"), compound.getBoolean("Girder"));
|
compound.getBoolean("Primary"), compound.getBoolean("Girder"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompoundTag write() {
|
public CompoundTag write(BlockPos localTo) {
|
||||||
|
Couple<BlockPos> tePositions = this.tePositions.map(b -> b.subtract(localTo));
|
||||||
|
Couple<Vec3> starts = this.starts.map(v -> v.subtract(Vec3.atLowerCornerOf(localTo)));
|
||||||
|
|
||||||
CompoundTag compound = new CompoundTag();
|
CompoundTag compound = new CompoundTag();
|
||||||
compound.putBoolean("Girder", hasGirder);
|
compound.putBoolean("Girder", hasGirder);
|
||||||
compound.putBoolean("Primary", primary);
|
compound.putBoolean("Primary", primary);
|
||||||
compound.putBoolean("TrackEnd1", trackEnds.getFirst());
|
|
||||||
compound.putBoolean("TrackEnd2", trackEnds.getSecond());
|
|
||||||
compound.put("Positions", tePositions.serializeEach(NbtUtils::writeBlockPos));
|
compound.put("Positions", tePositions.serializeEach(NbtUtils::writeBlockPos));
|
||||||
compound.put("Starts", starts.serializeEach(VecHelper::writeNBTCompound));
|
compound.put("Starts", starts.serializeEach(VecHelper::writeNBTCompound));
|
||||||
compound.put("Axes", axes.serializeEach(VecHelper::writeNBTCompound));
|
compound.put("Axes", axes.serializeEach(VecHelper::writeNBTCompound));
|
||||||
|
@ -85,7 +84,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
public BezierConnection(FriendlyByteBuf buffer) {
|
public BezierConnection(FriendlyByteBuf buffer) {
|
||||||
this(Couple.create(buffer::readBlockPos), Couple.create(() -> VecHelper.read(buffer)),
|
this(Couple.create(buffer::readBlockPos), Couple.create(() -> VecHelper.read(buffer)),
|
||||||
Couple.create(() -> VecHelper.read(buffer)), Couple.create(() -> VecHelper.read(buffer)),
|
Couple.create(() -> VecHelper.read(buffer)), Couple.create(() -> VecHelper.read(buffer)),
|
||||||
Couple.create(buffer::readBoolean), buffer.readBoolean(), buffer.readBoolean());
|
buffer.readBoolean(), buffer.readBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(FriendlyByteBuf buffer) {
|
public void write(FriendlyByteBuf buffer) {
|
||||||
|
@ -93,7 +92,6 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
starts.forEach(v -> VecHelper.write(v, buffer));
|
starts.forEach(v -> VecHelper.write(v, buffer));
|
||||||
axes.forEach(v -> VecHelper.write(v, buffer));
|
axes.forEach(v -> VecHelper.write(v, buffer));
|
||||||
normals.forEach(v -> VecHelper.write(v, buffer));
|
normals.forEach(v -> VecHelper.write(v, buffer));
|
||||||
trackEnds.forEach(buffer::writeBoolean);
|
|
||||||
buffer.writeBoolean(primary);
|
buffer.writeBoolean(primary);
|
||||||
buffer.writeBoolean(hasGirder);
|
buffer.writeBoolean(hasGirder);
|
||||||
}
|
}
|
||||||
|
@ -344,8 +342,8 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public static class SegmentAngles {
|
public static class SegmentAngles {
|
||||||
|
|
||||||
public Matrix4f tieTransform;
|
public Pose tieTransform;
|
||||||
public Couple<Matrix4f> railTransforms;
|
public Couple<Pose> railTransforms;
|
||||||
public BlockPos lightPosition;
|
public BlockPos lightPosition;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -353,8 +351,8 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public static class GirderAngles {
|
public static class GirderAngles {
|
||||||
|
|
||||||
public Couple<Matrix4f> beams;
|
public Couple<Pose> beams;
|
||||||
public Couple<Couple<Matrix4f>> beamCaps;
|
public Couple<Couple<Pose>> beamCaps;
|
||||||
public BlockPos lightPosition;
|
public BlockPos lightPosition;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -398,8 +396,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
.rotateZRadians(tieAngles.z)
|
.rotateZRadians(tieAngles.z)
|
||||||
.translate(-1 / 2f, -2 / 16f - 1 / 256f, 0);
|
.translate(-1 / 2f, -2 / 16f - 1 / 256f, 0);
|
||||||
angles.tieTransform = mts.unwrap()
|
angles.tieTransform = mts.unwrap()
|
||||||
.last()
|
.last();
|
||||||
.pose();
|
|
||||||
angles.railTransforms = Couple.create(null, null);
|
angles.railTransforms = Couple.create(null, null);
|
||||||
|
|
||||||
// Rails
|
// Rails
|
||||||
|
@ -418,8 +415,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
.translate(0, -2 / 16f + (i % 2 == 0 ? 1 : -1) / 2048f - 1 / 256f, -1 / 32f)
|
.translate(0, -2 / 16f + (i % 2 == 0 ? 1 : -1) / 2048f - 1 / 256f, -1 / 32f)
|
||||||
.scale(1, 1, (float) diff.length() * scale);
|
.scale(1, 1, (float) diff.length() * scale);
|
||||||
angles.railTransforms.set(first, mts.unwrap()
|
angles.railTransforms.set(first, mts.unwrap()
|
||||||
.last()
|
.last());
|
||||||
.pose());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
previousOffsets = railOffsets;
|
previousOffsets = railOffsets;
|
||||||
|
@ -494,8 +490,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
.translate(0, 2 / 16f + (segment.index % 2 == 0 ? 1 : -1) / 2048f - 1 / 1024f, -1 / 32f)
|
.translate(0, 2 / 16f + (segment.index % 2 == 0 ? 1 : -1) / 2048f - 1 / 1024f, -1 / 32f)
|
||||||
.scale(1, 1, (float) beamDiff.length() * scale);
|
.scale(1, 1, (float) beamDiff.length() * scale);
|
||||||
angles.beams.set(first, mts.unwrap()
|
angles.beams.set(first, mts.unwrap()
|
||||||
.last()
|
.last());
|
||||||
.pose());
|
|
||||||
|
|
||||||
// Caps
|
// Caps
|
||||||
for (boolean top : Iterate.trueAndFalse) {
|
for (boolean top : Iterate.trueAndFalse) {
|
||||||
|
@ -516,8 +511,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
.scale(1, 1, (float) diff.length() * scale);
|
.scale(1, 1, (float) diff.length() * scale);
|
||||||
angles.beamCaps.get(top)
|
angles.beamCaps.get(top)
|
||||||
.set(first, mts.unwrap()
|
.set(first, mts.unwrap()
|
||||||
.last()
|
.last());
|
||||||
.pose());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.simibubi.create.content.logistics.trains;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
|
@ -60,11 +61,11 @@ public class TrackEdge {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompoundTag write() {
|
public CompoundTag write() {
|
||||||
return isTurn() ? turn.write() : new CompoundTag();
|
return isTurn() ? turn.write(BlockPos.ZERO) : new CompoundTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TrackEdge read(CompoundTag tag) {
|
public static TrackEdge read(CompoundTag tag) {
|
||||||
return new TrackEdge(tag.contains("Positions") ? new BezierConnection(tag) : null);
|
return new TrackEdge(tag.contains("Positions") ? new BezierConnection(tag, BlockPos.ZERO) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ public class TrackGraphHelper {
|
||||||
double length = axis.length();
|
double length = axis.length();
|
||||||
|
|
||||||
List<Pair<BlockPos, DiscoveredLocation>> ends =
|
List<Pair<BlockPos, DiscoveredLocation>> ends =
|
||||||
TrackPropagator.getEnds(level, pos, trackBlockState, null, true);
|
TrackPropagator.getEnds(level, pos, trackBlockState, true, null, null);
|
||||||
|
|
||||||
TrackGraph graph = null;
|
TrackGraph graph = null;
|
||||||
TrackNode frontNode = null;
|
TrackNode frontNode = null;
|
||||||
|
@ -46,7 +46,7 @@ public class TrackGraphHelper {
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
DiscoveredLocation loc = current;
|
DiscoveredLocation loc = current;
|
||||||
List<Pair<BlockPos, DiscoveredLocation>> list =
|
List<Pair<BlockPos, DiscoveredLocation>> list =
|
||||||
TrackPropagator.getEnds(level, currentPos, level.getBlockState(currentPos), current, true);
|
TrackPropagator.getEnds(level, currentPos, level.getBlockState(currentPos), true, current, null);
|
||||||
if (!list.isEmpty()) {
|
if (!list.isEmpty()) {
|
||||||
currentPos = list.get(0)
|
currentPos = list.get(0)
|
||||||
.getFirst();
|
.getFirst();
|
||||||
|
|
|
@ -13,7 +13,7 @@ import javax.annotation.Nullable;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
|
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
|
||||||
import com.simibubi.create.content.logistics.trains.track.TrackBlock;
|
import com.simibubi.create.content.logistics.trains.track.TrackBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.track.TrackBlock.TrackShape;
|
import com.simibubi.create.content.logistics.trains.track.TrackShape;
|
||||||
import com.simibubi.create.content.logistics.trains.track.TrackTileEntity;
|
import com.simibubi.create.content.logistics.trains.track.TrackTileEntity;
|
||||||
import com.simibubi.create.foundation.utility.Pair;
|
import com.simibubi.create.foundation.utility.Pair;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
@ -47,11 +47,10 @@ public class TrackPropagator {
|
||||||
currentPos = pos;
|
currentPos = pos;
|
||||||
currentNode = location;
|
currentNode = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onRailRemoved(LevelAccessor reader, BlockPos pos, BlockState state) {
|
public static void onRailRemoved(LevelAccessor reader, BlockPos pos, BlockState state) {
|
||||||
List<Pair<BlockPos, DiscoveredLocation>> ends = getEnds(reader, pos, state, null, false);
|
List<Pair<BlockPos, DiscoveredLocation>> ends = getEnds(reader, pos, state, false, null, null);
|
||||||
TrackGraph foundGraph = null;
|
TrackGraph foundGraph = null;
|
||||||
GlobalRailwayManager manager = Create.RAILWAYS;
|
GlobalRailwayManager manager = Create.RAILWAYS;
|
||||||
TrackGraphSync sync = manager.sync;
|
TrackGraphSync sync = manager.sync;
|
||||||
|
@ -78,9 +77,16 @@ public class TrackPropagator {
|
||||||
for (Pair<BlockPos, DiscoveredLocation> removedEnd : ends) {
|
for (Pair<BlockPos, DiscoveredLocation> removedEnd : ends) {
|
||||||
BlockPos adjPos = removedEnd.getFirst();
|
BlockPos adjPos = removedEnd.getFirst();
|
||||||
BlockState adjState = reader.getBlockState(adjPos);
|
BlockState adjState = reader.getBlockState(adjPos);
|
||||||
|
List<Pair<BlockPos, DiscoveredLocation>> adjEnds =
|
||||||
if (!getEnds(reader, adjPos, adjState, removedEnd.getSecond(), true).isEmpty())
|
getEnds(reader, adjPos, adjState, true, removedEnd.getSecond(), null);
|
||||||
toUpdate.add(onRailAdded(reader, adjPos, adjState));
|
if (adjEnds.isEmpty())
|
||||||
|
continue;
|
||||||
|
Vec3 filter = adjEnds.get(0)
|
||||||
|
.getSecond()
|
||||||
|
.getLocation()
|
||||||
|
.subtract(removedEnd.getSecond()
|
||||||
|
.getLocation());
|
||||||
|
toUpdate.add(onRailAdded(reader, adjPos, adjState, filter.normalize()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TrackGraph railGraph : toUpdate)
|
for (TrackGraph railGraph : toUpdate)
|
||||||
|
@ -89,7 +95,7 @@ public class TrackPropagator {
|
||||||
manager.markTracksDirty();
|
manager.markTracksDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TrackGraph onRailAdded(LevelAccessor reader, BlockPos pos, BlockState state) {
|
public static TrackGraph onRailAdded(LevelAccessor reader, BlockPos pos, BlockState state, Vec3 axisFilter) {
|
||||||
// 1. Remove all immediately reachable node locations
|
// 1. Remove all immediately reachable node locations
|
||||||
|
|
||||||
GlobalRailwayManager manager = Create.RAILWAYS;
|
GlobalRailwayManager manager = Create.RAILWAYS;
|
||||||
|
@ -97,7 +103,7 @@ public class TrackPropagator {
|
||||||
List<FrontierEntry> frontier = new ArrayList<>();
|
List<FrontierEntry> frontier = new ArrayList<>();
|
||||||
Set<DiscoveredLocation> visited = new HashSet<>();
|
Set<DiscoveredLocation> visited = new HashSet<>();
|
||||||
Set<TrackGraph> connectedGraphs = new HashSet<>();
|
Set<TrackGraph> connectedGraphs = new HashSet<>();
|
||||||
addInitialEndsOf(reader, pos, state, frontier, false);
|
addInitialEndsOf(reader, pos, state, frontier, false, axisFilter);
|
||||||
|
|
||||||
int emergencyExit = 1000;
|
int emergencyExit = 1000;
|
||||||
while (!frontier.isEmpty()) {
|
while (!frontier.isEmpty()) {
|
||||||
|
@ -155,7 +161,7 @@ public class TrackPropagator {
|
||||||
|
|
||||||
// 2. Find the first graph node candidate nearby
|
// 2. Find the first graph node candidate nearby
|
||||||
|
|
||||||
addInitialEndsOf(reader, pos, state, frontier, true);
|
addInitialEndsOf(reader, pos, state, frontier, true, axisFilter);
|
||||||
|
|
||||||
emergencyExit = 1000;
|
emergencyExit = 1000;
|
||||||
while (!frontier.isEmpty()) {
|
while (!frontier.isEmpty()) {
|
||||||
|
@ -229,8 +235,8 @@ public class TrackPropagator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addInitialEndsOf(LevelAccessor reader, BlockPos pos, BlockState state,
|
private static void addInitialEndsOf(LevelAccessor reader, BlockPos pos, BlockState state,
|
||||||
List<FrontierEntry> frontier, boolean ignoreTurns) {
|
List<FrontierEntry> frontier, boolean ignoreTurns, Vec3 axisFilter) {
|
||||||
for (Pair<BlockPos, DiscoveredLocation> initial : getEnds(reader, pos, state, null, ignoreTurns))
|
for (Pair<BlockPos, DiscoveredLocation> initial : getEnds(reader, pos, state, ignoreTurns, null, axisFilter))
|
||||||
frontier.add(new FrontierEntry(initial.getFirst(), pos, initial.getSecond()));
|
frontier.add(new FrontierEntry(initial.getFirst(), pos, initial.getSecond()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,13 +261,13 @@ public class TrackPropagator {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Pair<BlockPos, DiscoveredLocation> pair : getEnds(reader, prevPos, reader.getBlockState(prevPos),
|
for (Pair<BlockPos, DiscoveredLocation> pair : getEnds(reader, prevPos, reader.getBlockState(prevPos),
|
||||||
entry.currentNode, false))
|
false, entry.currentNode, null))
|
||||||
if (!pair.getSecond()
|
if (!pair.getSecond()
|
||||||
.equals(entry.prevNode))
|
.equals(entry.prevNode))
|
||||||
ends.add(pair);
|
ends.add(pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
ends.addAll(getEnds(reader, entry.currentPos, currentState, entry.currentNode, false));
|
ends.addAll(getEnds(reader, entry.currentPos, currentState, false, entry.currentNode, null));
|
||||||
return ends;
|
return ends;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +310,7 @@ public class TrackPropagator {
|
||||||
|
|
||||||
// TODO ITrackBlock
|
// TODO ITrackBlock
|
||||||
public static List<Pair<BlockPos, DiscoveredLocation>> getEnds(LevelReader reader, BlockPos pos, BlockState state,
|
public static List<Pair<BlockPos, DiscoveredLocation>> getEnds(LevelReader reader, BlockPos pos, BlockState state,
|
||||||
@Nullable DiscoveredLocation fromEnd, boolean ignoreTurns) {
|
boolean ignoreTurns, @Nullable DiscoveredLocation fromEnd, @Nullable Vec3 axisFilter) {
|
||||||
Vec3 center = VecHelper.getCenterOf(pos);
|
Vec3 center = VecHelper.getCenterOf(pos);
|
||||||
List<Pair<BlockPos, DiscoveredLocation>> list = new ArrayList<>();
|
List<Pair<BlockPos, DiscoveredLocation>> list = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -315,21 +321,36 @@ public class TrackPropagator {
|
||||||
if (state.getValue(TrackBlock.HAS_TURN) && blockEntity instanceof TrackTileEntity && !ignoreTurns) {
|
if (state.getValue(TrackBlock.HAS_TURN) && blockEntity instanceof TrackTileEntity && !ignoreTurns) {
|
||||||
TrackTileEntity trackTileEntity = (TrackTileEntity) blockEntity;
|
TrackTileEntity trackTileEntity = (TrackTileEntity) blockEntity;
|
||||||
trackTileEntity.getConnections()
|
trackTileEntity.getConnections()
|
||||||
.forEach(map -> map.forEach((connectedPos, bc) -> addToSet(fromEnd, list,
|
.forEach((connectedPos, bc) -> {
|
||||||
(d, b) -> d == 1 ? Vec3.atLowerCornerOf(bc.tePositions.get(b)) : bc.starts.get(b), bc.normals::get,
|
Vec3 curveHandle = bc.axes.getFirst();
|
||||||
bc)));
|
if (axisFilter != null && !testAxisFilter(curveHandle.normalize(), axisFilter))
|
||||||
|
return;
|
||||||
|
addToSet(fromEnd, list,
|
||||||
|
(d, b) -> d == 1 ? Vec3.atLowerCornerOf(bc.tePositions.get(b)) : bc.starts.get(b),
|
||||||
|
bc.normals::get, bc);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackShape shape = state.getValue(TrackBlock.SHAPE);
|
TrackShape shape = state.getValue(TrackBlock.SHAPE);
|
||||||
if (shape != TrackShape.NONE)
|
if (shape == TrackShape.NONE)
|
||||||
shape.getAxes()
|
return list;
|
||||||
.forEach(axis -> addToSet(fromEnd, list, (d, b) -> axis.scale(b ? d : -d)
|
|
||||||
|
shape.getAxes()
|
||||||
|
.forEach(axis -> {
|
||||||
|
if (axisFilter != null && !testAxisFilter(axis.normalize(), axisFilter))
|
||||||
|
return;
|
||||||
|
addToSet(fromEnd, list, (d, b) -> axis.scale(b ? d : -d)
|
||||||
.add(center)
|
.add(center)
|
||||||
.add(0, axis.y == 0 ? -.5 : 0, 0), b -> shape.getNormal(), null));
|
.add(0, axis.y == 0 ? -.5 : 0, 0), b -> shape.getNormal(), null);
|
||||||
|
});
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean testAxisFilter(Vec3 axis, Vec3 filter) {
|
||||||
|
return Mth.equal(axis.distanceToSqr(filter), 0) || Mth.equal(axis.distanceToSqr(filter.scale(-1)), 0);
|
||||||
|
}
|
||||||
|
|
||||||
private static void addToSet(DiscoveredLocation fromEnd, List<Pair<BlockPos, DiscoveredLocation>> list,
|
private static void addToSet(DiscoveredLocation fromEnd, List<Pair<BlockPos, DiscoveredLocation>> list,
|
||||||
BiFunction<Double, Boolean, Vec3> offsetFactory, Function<Boolean, Vec3> normalFactory,
|
BiFunction<Double, Boolean, Vec3> offsetFactory, Function<Boolean, Vec3> normalFactory,
|
||||||
BezierConnection viaTurn) {
|
BezierConnection viaTurn) {
|
||||||
|
|
|
@ -326,7 +326,7 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
DiscoveredLocation location = null;
|
DiscoveredLocation location = null;
|
||||||
List<Pair<BlockPos, DiscoveredLocation>> ends =
|
List<Pair<BlockPos, DiscoveredLocation>> ends =
|
||||||
TrackPropagator.getEnds(level, trackPosition, trackState, null, true);
|
TrackPropagator.getEnds(level, trackPosition, trackState, true, null, null);
|
||||||
for (Pair<BlockPos, DiscoveredLocation> pair : ends)
|
for (Pair<BlockPos, DiscoveredLocation> pair : ends)
|
||||||
if (trackPosition.relative(assemblyDirection)
|
if (trackPosition.relative(assemblyDirection)
|
||||||
.equals(pair.getFirst()))
|
.equals(pair.getFirst()))
|
||||||
|
|
|
@ -4,7 +4,6 @@ import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.jozufozu.flywheel.core.PartialModel;
|
import com.jozufozu.flywheel.core.PartialModel;
|
||||||
import com.jozufozu.flywheel.util.transform.MatrixTransformStack;
|
import com.jozufozu.flywheel.util.transform.MatrixTransformStack;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
@ -15,12 +14,12 @@ import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.CreateClient;
|
import com.simibubi.create.CreateClient;
|
||||||
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
||||||
|
import com.simibubi.create.content.curiosities.girder.GirderBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.ITrackBlock;
|
import com.simibubi.create.content.logistics.trains.ITrackBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackPropagator;
|
import com.simibubi.create.content.logistics.trains.TrackPropagator;
|
||||||
import com.simibubi.create.content.logistics.trains.management.StationTileEntity;
|
import com.simibubi.create.content.logistics.trains.management.StationTileEntity;
|
||||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
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.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -29,18 +28,20 @@ import net.minecraft.core.Direction.Axis;
|
||||||
import net.minecraft.core.Direction.AxisDirection;
|
import net.minecraft.core.Direction.AxisDirection;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.util.StringRepresentable;
|
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||||
|
import net.minecraft.world.item.context.UseOnContext;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
import net.minecraft.world.level.BlockGetter;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.LevelReader;
|
import net.minecraft.world.level.LevelReader;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.EntityBlock;
|
import net.minecraft.world.level.block.EntityBlock;
|
||||||
|
import net.minecraft.world.level.block.Mirror;
|
||||||
|
import net.minecraft.world.level.block.Rotation;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
||||||
|
@ -62,74 +63,6 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
|
||||||
public static final EnumProperty<TrackShape> SHAPE = EnumProperty.create("shape", TrackShape.class);
|
public static final EnumProperty<TrackShape> SHAPE = EnumProperty.create("shape", TrackShape.class);
|
||||||
public static final BooleanProperty HAS_TURN = BooleanProperty.create("turn");
|
public static final BooleanProperty HAS_TURN = BooleanProperty.create("turn");
|
||||||
|
|
||||||
public enum TrackShape implements StringRepresentable {
|
|
||||||
NONE("", Vec3.ZERO),
|
|
||||||
ZO("z_ortho", new Vec3(0, 0, 1)),
|
|
||||||
XO("x_ortho", new Vec3(1, 0, 0)),
|
|
||||||
PD("diag", new Vec3(1, 0, 1)),
|
|
||||||
ND("diag_2", new Vec3(-1, 0, 1)),
|
|
||||||
AN("ascending", 180, new Vec3(0, 1, -1), new Vec3(0, 1, 1)),
|
|
||||||
AS("ascending", 0, new Vec3(0, 1, 1), new Vec3(0, 1, -1)),
|
|
||||||
AE("ascending", 270, new Vec3(1, 1, 0), new Vec3(-1, 1, 0)),
|
|
||||||
AW("ascending", 90, new Vec3(-1, 1, 0), new Vec3(1, 1, 0)),
|
|
||||||
|
|
||||||
CR_O("cross_ortho", new Vec3(0, 0, 1), new Vec3(1, 0, 0)),
|
|
||||||
CR_D("cross_diag", new Vec3(1, 0, 1), new Vec3(-1, 0, 1)),
|
|
||||||
CR_PDX("cross_d1_xo", new Vec3(1, 0, 0), new Vec3(1, 0, 1)),
|
|
||||||
CR_PDZ("cross_d1_zo", new Vec3(0, 0, 1), new Vec3(1, 0, 1)),
|
|
||||||
CR_NDX("cross_d2_xo", new Vec3(1, 0, 0), new Vec3(-1, 0, 1)),
|
|
||||||
CR_NDZ("cross_d2_zo", new Vec3(0, 0, 1), new Vec3(-1, 0, 1));
|
|
||||||
|
|
||||||
private String model;
|
|
||||||
private List<Vec3> axes;
|
|
||||||
private int modelRotation;
|
|
||||||
private Vec3 normal;
|
|
||||||
|
|
||||||
private TrackShape(String model, Vec3 axis) {
|
|
||||||
this(model, 0, axis, new Vec3(0, 1, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
private TrackShape(String model, Vec3 axis, Vec3 secondAxis) {
|
|
||||||
this.model = model;
|
|
||||||
this.modelRotation = 0;
|
|
||||||
this.normal = new Vec3(0, 1, 0);
|
|
||||||
this.axes = ImmutableList.of(axis, secondAxis);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TrackShape(String model, int modelRotation, Vec3 axis, Vec3 normal) {
|
|
||||||
this.model = model;
|
|
||||||
this.modelRotation = modelRotation;
|
|
||||||
this.normal = normal.normalize();
|
|
||||||
this.axes = ImmutableList.of(axis);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSerializedName() {
|
|
||||||
return Lang.asId(name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getModel() {
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Vec3> getAxes() {
|
|
||||||
return axes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isJunction() {
|
|
||||||
return axes.size() > 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vec3 getNormal() {
|
|
||||||
return normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getModelRotation() {
|
|
||||||
return modelRotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public TrackBlock(Properties p_49795_) {
|
public TrackBlock(Properties p_49795_) {
|
||||||
super(p_49795_);
|
super(p_49795_);
|
||||||
registerDefaultState(defaultBlockState().setValue(SHAPE, TrackShape.ZO)
|
registerDefaultState(defaultBlockState().setValue(SHAPE, TrackShape.ZO)
|
||||||
|
@ -201,14 +134,18 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
|
||||||
public void onPlace(BlockState pState, Level pLevel, BlockPos pPos, BlockState pOldState, boolean pIsMoving) {
|
public void onPlace(BlockState pState, Level pLevel, BlockPos pPos, BlockState pOldState, boolean pIsMoving) {
|
||||||
if (pOldState.getBlock() == this && pState.setValue(HAS_TURN, true) == pOldState.setValue(HAS_TURN, true))
|
if (pOldState.getBlock() == this && pState.setValue(HAS_TURN, true) == pOldState.setValue(HAS_TURN, true))
|
||||||
return;
|
return;
|
||||||
|
if (pLevel.isClientSide)
|
||||||
|
return;
|
||||||
LevelTickAccess<Block> blockTicks = pLevel.getBlockTicks();
|
LevelTickAccess<Block> blockTicks = pLevel.getBlockTicks();
|
||||||
if (!blockTicks.hasScheduledTick(pPos, this))
|
if (!blockTicks.hasScheduledTick(pPos, this))
|
||||||
pLevel.scheduleTick(pPos, this, 1);
|
pLevel.scheduleTick(pPos, this, 1);
|
||||||
|
updateGirders(pState, pLevel, pPos, blockTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(BlockState p_60462_, ServerLevel p_60463_, BlockPos p_60464_, Random p_60465_) {
|
public void tick(BlockState p_60462_, ServerLevel p_60463_, BlockPos p_60464_, Random p_60465_) {
|
||||||
TrackPropagator.onRailAdded(p_60463_, p_60464_, p_60462_);
|
for (Vec3 axis : getTrackAxes(p_60463_, p_60464_, p_60462_))
|
||||||
|
TrackPropagator.onRailAdded(p_60463_, p_60464_, p_60462_, axis.normalize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -216,7 +153,7 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
|
||||||
boolean removeTE = false;
|
boolean removeTE = false;
|
||||||
if (pState.getValue(HAS_TURN) && (!pState.is(pNewState.getBlock()) || !pNewState.getValue(HAS_TURN))) {
|
if (pState.getValue(HAS_TURN) && (!pState.is(pNewState.getBlock()) || !pNewState.getValue(HAS_TURN))) {
|
||||||
BlockEntity blockEntity = pLevel.getBlockEntity(pPos);
|
BlockEntity blockEntity = pLevel.getBlockEntity(pPos);
|
||||||
if (blockEntity instanceof TrackTileEntity)
|
if (blockEntity instanceof TrackTileEntity && !pLevel.isClientSide)
|
||||||
((TrackTileEntity) blockEntity).removeInboundConnections();
|
((TrackTileEntity) blockEntity).removeInboundConnections();
|
||||||
removeTE = true;
|
removeTE = true;
|
||||||
}
|
}
|
||||||
|
@ -225,6 +162,8 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
|
||||||
TrackPropagator.onRailRemoved(pLevel, pPos, pState);
|
TrackPropagator.onRailRemoved(pLevel, pPos, pState);
|
||||||
if (removeTE)
|
if (removeTE)
|
||||||
pLevel.removeBlockEntity(pPos);
|
pLevel.removeBlockEntity(pPos);
|
||||||
|
if (!pLevel.isClientSide)
|
||||||
|
updateGirders(pState, pLevel, pPos, pLevel.getBlockTicks());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -253,14 +192,24 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
|
||||||
return InteractionResult.SUCCESS;
|
return InteractionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (asItem() == itemInHand.getItem()) {
|
|
||||||
// TrackConnectionPlacementHandler.select(world, pos, player.getLookAngle(), itemInHand);
|
|
||||||
// return InteractionResult.SUCCESS;
|
|
||||||
// }
|
|
||||||
|
|
||||||
return InteractionResult.PASS;
|
return InteractionResult.PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateGirders(BlockState pState, Level pLevel, BlockPos pPos, LevelTickAccess<Block> blockTicks) {
|
||||||
|
for (Vec3 vec3 : getTrackAxes(pLevel, pPos, pState)) {
|
||||||
|
if (vec3.length() > 1 || vec3.y != 0)
|
||||||
|
continue;
|
||||||
|
for (int side : Iterate.positiveAndNegative) {
|
||||||
|
BlockPos girderPos = pPos.below()
|
||||||
|
.offset(vec3.z * side, 0, vec3.x * side);
|
||||||
|
BlockState girderState = pLevel.getBlockState(girderPos);
|
||||||
|
if (girderState.getBlock()instanceof GirderBlock girderBlock
|
||||||
|
&& !blockTicks.hasScheduledTick(girderPos, girderBlock))
|
||||||
|
pLevel.scheduleTick(girderPos, girderBlock, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canSurvive(BlockState state, LevelReader reader, BlockPos pos) {
|
public boolean canSurvive(BlockState state, LevelReader reader, BlockPos pos) {
|
||||||
return reader.getBlockState(pos.below())
|
return reader.getBlockState(pos.below())
|
||||||
|
@ -298,16 +247,21 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
|
||||||
.add(0, (vertical ? 0 : -.5f), 0)
|
.add(0, (vertical ? 0 : -.5f), 0)
|
||||||
.add(axis.scale(.5));
|
.add(axis.scale(.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InteractionResult onWrenched(BlockState state, UseOnContext context) {
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState overlay(BlockGetter world, BlockPos pos, BlockState existing, BlockState placed) {
|
public BlockState overlay(BlockGetter world, BlockPos pos, BlockState existing, BlockState placed) {
|
||||||
if (placed.getBlock() != this)
|
if (placed.getBlock() != this)
|
||||||
return existing;
|
return existing;
|
||||||
|
|
||||||
TrackShape existingShape = existing.getValue(SHAPE);
|
TrackShape existingShape = existing.getValue(SHAPE);
|
||||||
TrackShape placedShape = placed.getValue(SHAPE);
|
TrackShape placedShape = placed.getValue(SHAPE);
|
||||||
TrackShape combinedShape = null;
|
TrackShape combinedShape = null;
|
||||||
|
|
||||||
for (boolean flip : Iterate.trueAndFalse) {
|
for (boolean flip : Iterate.trueAndFalse) {
|
||||||
TrackShape s1 = flip ? existingShape : placedShape;
|
TrackShape s1 = flip ? existingShape : placedShape;
|
||||||
TrackShape s2 = flip ? placedShape : existingShape;
|
TrackShape s2 = flip ? placedShape : existingShape;
|
||||||
|
@ -324,26 +278,22 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
|
||||||
if (s1 == TrackShape.ZO && s2 == TrackShape.ND)
|
if (s1 == TrackShape.ZO && s2 == TrackShape.ND)
|
||||||
combinedShape = TrackShape.CR_NDZ;
|
combinedShape = TrackShape.CR_NDZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (combinedShape != null)
|
if (combinedShape != null)
|
||||||
existing = existing.setValue(SHAPE, combinedShape);
|
existing = existing.setValue(SHAPE, combinedShape);
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getRotatedBlockState(BlockState state, Direction targetedFace) {
|
public BlockState rotate(BlockState state, Rotation pRotation) {
|
||||||
switch (state.getValue(SHAPE)) {
|
return state.setValue(SHAPE, state.getValue(SHAPE)
|
||||||
case ND:
|
.rotate(pRotation));
|
||||||
return state.setValue(SHAPE, TrackShape.XO);
|
}
|
||||||
case PD:
|
|
||||||
return state.setValue(SHAPE, TrackShape.ZO);
|
@Override
|
||||||
case XO:
|
public BlockState mirror(BlockState state, Mirror pMirror) {
|
||||||
return state.setValue(SHAPE, TrackShape.PD);
|
return state.setValue(SHAPE, state.getValue(SHAPE)
|
||||||
case ZO:
|
.mirror(pMirror));
|
||||||
return state.setValue(SHAPE, TrackShape.ND);
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -113,20 +113,17 @@ public class TrackBlockItem extends BlockItem {
|
||||||
|
|
||||||
ITrackBlock track = (ITrackBlock) block;
|
ITrackBlock track = (ITrackBlock) block;
|
||||||
Pair<Vec3, AxisDirection> nearestTrackAxis = track.getNearestTrackAxis(world, pos, blockState, lookVec);
|
Pair<Vec3, AxisDirection> nearestTrackAxis = track.getNearestTrackAxis(world, pos, blockState, lookVec);
|
||||||
Vec3 axis = nearestTrackAxis.getFirst();
|
Vec3 axis = nearestTrackAxis.getFirst()
|
||||||
boolean front = nearestTrackAxis.getSecond() == AxisDirection.POSITIVE;
|
.scale(nearestTrackAxis.getSecond() == AxisDirection.POSITIVE ? -1 : 1);
|
||||||
|
Vec3 end = track.getCurveStart(world, pos, blockState, axis);
|
||||||
Vec3 normal = track.getUpNormal(world, pos, blockState)
|
Vec3 normal = track.getUpNormal(world, pos, blockState)
|
||||||
.normalize();
|
.normalize();
|
||||||
|
|
||||||
axis = axis.scale(front ? -1 : 1);
|
|
||||||
Vec3 end = track.getCurveStart(world, pos, blockState, axis);
|
|
||||||
|
|
||||||
CompoundTag compoundTag = heldItem.getOrCreateTagElement("ConnectingFrom");
|
CompoundTag compoundTag = heldItem.getOrCreateTagElement("ConnectingFrom");
|
||||||
compoundTag.put("Pos", NbtUtils.writeBlockPos(pos));
|
compoundTag.put("Pos", NbtUtils.writeBlockPos(pos));
|
||||||
compoundTag.put("Axis", VecHelper.writeNBT(axis));
|
compoundTag.put("Axis", VecHelper.writeNBT(axis));
|
||||||
compoundTag.put("Normal", VecHelper.writeNBT(normal));
|
compoundTag.put("Normal", VecHelper.writeNBT(normal));
|
||||||
compoundTag.put("End", VecHelper.writeNBT(end));
|
compoundTag.put("End", VecHelper.writeNBT(end));
|
||||||
compoundTag.putBoolean("Front", front);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.simibubi.create.content.logistics.trains.track;
|
package com.simibubi.create.content.logistics.trains.track;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.logistics.trains.track.TrackBlock.TrackShape;
|
|
||||||
import com.simibubi.create.foundation.data.SpecialBlockStateGen;
|
import com.simibubi.create.foundation.data.SpecialBlockStateGen;
|
||||||
import com.tterrag.registrate.providers.DataGenContext;
|
import com.tterrag.registrate.providers.DataGenContext;
|
||||||
import com.tterrag.registrate.providers.RegistrateBlockstateProvider;
|
import com.tterrag.registrate.providers.RegistrateBlockstateProvider;
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.simibubi.create.content.logistics.trains.track;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -12,11 +11,11 @@ import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
|
||||||
import com.jozufozu.flywheel.core.Materials;
|
import com.jozufozu.flywheel.core.Materials;
|
||||||
import com.jozufozu.flywheel.core.materials.model.ModelData;
|
import com.jozufozu.flywheel.core.materials.model.ModelData;
|
||||||
import com.jozufozu.flywheel.light.LightUpdater;
|
import com.jozufozu.flywheel.light.LightUpdater;
|
||||||
import com.jozufozu.flywheel.util.FlwUtil;
|
|
||||||
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
||||||
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
||||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack.Pose;
|
||||||
import com.simibubi.create.AllBlockPartials;
|
import com.simibubi.create.AllBlockPartials;
|
||||||
import com.simibubi.create.content.logistics.trains.BezierConnection;
|
import com.simibubi.create.content.logistics.trains.BezierConnection;
|
||||||
import com.simibubi.create.content.logistics.trains.BezierConnection.GirderAngles;
|
import com.simibubi.create.content.logistics.trains.BezierConnection.GirderAngles;
|
||||||
|
@ -39,13 +38,12 @@ public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
if (blockEntity.connections.stream()
|
if (blockEntity.connections.isEmpty())
|
||||||
.allMatch(Map::isEmpty)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
instances = blockEntity.connections.stream()
|
remove();
|
||||||
.flatMap(FlwUtil::mapValues)
|
instances = blockEntity.connections.values()
|
||||||
|
.stream()
|
||||||
.map(this::createInstance)
|
.map(this::createInstance)
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.toList();
|
.toList();
|
||||||
|
@ -56,10 +54,8 @@ public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
||||||
@Override
|
@Override
|
||||||
public ImmutableBox getVolume() {
|
public ImmutableBox getVolume() {
|
||||||
List<BlockPos> out = new ArrayList<>();
|
List<BlockPos> out = new ArrayList<>();
|
||||||
out.addAll(blockEntity.connections.getFirst()
|
out.addAll(blockEntity.connections.keySet());
|
||||||
.keySet());
|
out.addAll(blockEntity.connections.keySet());
|
||||||
out.addAll(blockEntity.connections.getSecond()
|
|
||||||
.keySet());
|
|
||||||
return GridAlignedBB.containingAll(out);
|
return GridAlignedBB.containingAll(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,12 +125,15 @@ public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
||||||
var modelIndex = i - 1;
|
var modelIndex = i - 1;
|
||||||
|
|
||||||
ties[modelIndex].setTransform(pose)
|
ties[modelIndex].setTransform(pose)
|
||||||
.mulPose(segment.tieTransform);
|
.mulPose(segment.tieTransform.pose())
|
||||||
|
.mulNormal(segment.tieTransform.normal());
|
||||||
tiesLightPos[modelIndex] = segment.lightPosition.offset(tePosition);
|
tiesLightPos[modelIndex] = segment.lightPosition.offset(tePosition);
|
||||||
|
|
||||||
for (boolean first : Iterate.trueAndFalse) {
|
for (boolean first : Iterate.trueAndFalse) {
|
||||||
|
Pose transform = segment.railTransforms.get(first);
|
||||||
(first ? this.left : this.right)[modelIndex].setTransform(pose)
|
(first ? this.left : this.right)[modelIndex].setTransform(pose)
|
||||||
.mulPose(segment.railTransforms.get(first));
|
.mulPose(transform.pose())
|
||||||
|
.mulNormal(transform.normal());
|
||||||
(first ? leftLightPos : rightLightPos)[modelIndex] = segment.lightPosition.offset(tePosition);
|
(first ? leftLightPos : rightLightPos)[modelIndex] = segment.lightPosition.offset(tePosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,8 +184,9 @@ public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
||||||
beams = Couple.create(() -> new ModelData[segCount]);
|
beams = Couple.create(() -> new ModelData[segCount]);
|
||||||
beamCaps = Couple.create(() -> Couple.create(() -> new ModelData[segCount]));
|
beamCaps = Couple.create(() -> Couple.create(() -> new ModelData[segCount]));
|
||||||
lightPos = new BlockPos[segCount];
|
lightPos = new BlockPos[segCount];
|
||||||
beams.forEach(mat.getModel(AllBlockPartials.GIRDER_SEGMENT_2)::createInstances);
|
beams.forEach(mat.getModel(AllBlockPartials.GIRDER_SEGMENT_MIDDLE)::createInstances);
|
||||||
beamCaps.forEach(c -> c.forEach(mat.getModel(AllBlockPartials.GIRDER_SEGMENT)::createInstances));
|
beamCaps.forEachWithContext((c, top) -> c.forEach(mat.getModel(top ? AllBlockPartials.GIRDER_SEGMENT_TOP
|
||||||
|
: AllBlockPartials.GIRDER_SEGMENT_BOTTOM)::createInstances));
|
||||||
|
|
||||||
GirderAngles[] bakedGirders = bc.getBakedGirders();
|
GirderAngles[] bakedGirders = bc.getBakedGirders();
|
||||||
for (int i = 1; i < bakedGirders.length; i++) {
|
for (int i = 1; i < bakedGirders.length; i++) {
|
||||||
|
@ -195,13 +195,18 @@ public class TrackInstance extends BlockEntityInstance<TrackTileEntity> {
|
||||||
lightPos[modelIndex] = segment.lightPosition.offset(tePosition);
|
lightPos[modelIndex] = segment.lightPosition.offset(tePosition);
|
||||||
|
|
||||||
for (boolean first : Iterate.trueAndFalse) {
|
for (boolean first : Iterate.trueAndFalse) {
|
||||||
|
Pose beamTransform = segment.beams.get(first);
|
||||||
beams.get(first)[modelIndex].setTransform(pose)
|
beams.get(first)[modelIndex].setTransform(pose)
|
||||||
.mulPose(segment.beams.get(first));
|
.mulPose(beamTransform.pose())
|
||||||
for (boolean top : Iterate.trueAndFalse)
|
.mulNormal(beamTransform.normal());
|
||||||
|
for (boolean top : Iterate.trueAndFalse) {
|
||||||
|
Pose beamCapTransform = segment.beamCaps.get(top)
|
||||||
|
.get(first);
|
||||||
beamCaps.get(top)
|
beamCaps.get(top)
|
||||||
.get(first)[modelIndex].setTransform(pose)
|
.get(first)[modelIndex].setTransform(pose)
|
||||||
.mulPose(segment.beamCaps.get(top)
|
.mulPose(beamCapTransform.pose())
|
||||||
.get(first));
|
.mulNormal(beamCapTransform.normal());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,11 +84,10 @@ public class TrackPlacement {
|
||||||
|
|
||||||
ITrackBlock track = (ITrackBlock) state2.getBlock();
|
ITrackBlock track = (ITrackBlock) state2.getBlock();
|
||||||
Pair<Vec3, AxisDirection> nearestTrackAxis = track.getNearestTrackAxis(level, pos2, state2, lookVec);
|
Pair<Vec3, AxisDirection> nearestTrackAxis = track.getNearestTrackAxis(level, pos2, state2, lookVec);
|
||||||
Vec3 axis2 = nearestTrackAxis.getFirst();
|
Vec3 axis2 = nearestTrackAxis.getFirst()
|
||||||
boolean front2 = nearestTrackAxis.getSecond() == AxisDirection.POSITIVE;
|
.scale(nearestTrackAxis.getSecond() == AxisDirection.POSITIVE ? -1 : 1);
|
||||||
Vec3 normal2 = track.getUpNormal(level, pos2, state2)
|
Vec3 normal2 = track.getUpNormal(level, pos2, state2)
|
||||||
.normalize();
|
.normalize();
|
||||||
axis2 = axis2.scale(front2 ? -1 : 1);
|
|
||||||
Vec3 normedAxis2 = axis2.normalize();
|
Vec3 normedAxis2 = axis2.normalize();
|
||||||
Vec3 end2 = track.getCurveStart(level, pos2, state2, axis2);
|
Vec3 end2 = track.getCurveStart(level, pos2, state2, axis2);
|
||||||
|
|
||||||
|
@ -137,7 +136,6 @@ public class TrackPlacement {
|
||||||
if ((parallel && normedAxis1.dot(normedAxis2) > 0) || (!parallel && (intersect[0] < 0 || intersect[1] < 0))) {
|
if ((parallel && normedAxis1.dot(normedAxis2) > 0) || (!parallel && (intersect[0] < 0 || intersect[1] < 0))) {
|
||||||
axis2 = axis2.scale(-1);
|
axis2 = axis2.scale(-1);
|
||||||
normedAxis2 = normedAxis2.scale(-1);
|
normedAxis2 = normedAxis2.scale(-1);
|
||||||
front2 = !front2;
|
|
||||||
end2 = track.getCurveStart(level, pos2, state2, axis2);
|
end2 = track.getCurveStart(level, pos2, state2, axis2);
|
||||||
if (level.isClientSide) {
|
if (level.isClientSide) {
|
||||||
info.end2 = end2;
|
info.end2 = end2;
|
||||||
|
@ -161,7 +159,7 @@ public class TrackPlacement {
|
||||||
BlockPos targetPos2 = pos2.offset(offset2.x, offset2.y, offset2.z);
|
BlockPos targetPos2 = pos2.offset(offset2.x, offset2.y, offset2.z);
|
||||||
info.curve = new BezierConnection(Couple.create(targetPos1, targetPos2),
|
info.curve = new BezierConnection(Couple.create(targetPos1, targetPos2),
|
||||||
Couple.create(end1.add(offset1), end2.add(offset2)), Couple.create(normedAxis1, normedAxis2),
|
Couple.create(end1.add(offset1), end2.add(offset2)), Couple.create(normedAxis1, normedAxis2),
|
||||||
Couple.create(normal1, normal2), Couple.create(front1, front2), true, girder);
|
Couple.create(normal1, normal2), true, girder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// S curve or Straight
|
// S curve or Straight
|
||||||
|
@ -281,7 +279,7 @@ public class TrackPlacement {
|
||||||
if (dist2 > dist1)
|
if (dist2 > dist1)
|
||||||
ex2 = (float) ((dist2 - dist1) / axis2.length());
|
ex2 = (float) ((dist2 - dist1) / axis2.length());
|
||||||
|
|
||||||
double turnSize = Math.min(dist1, dist2);
|
double turnSize = Math.min(dist1, dist2) - .1d;
|
||||||
boolean ninety = (absAngle + .25f) % 90 < 1;
|
boolean ninety = (absAngle + .25f) % 90 < 1;
|
||||||
|
|
||||||
if (intersect[0] < 0 || intersect[1] < 0)
|
if (intersect[0] < 0 || intersect[1] < 0)
|
||||||
|
@ -312,7 +310,7 @@ public class TrackPlacement {
|
||||||
info.curve = skipCurve ? null
|
info.curve = skipCurve ? null
|
||||||
: new BezierConnection(Couple.create(targetPos1, targetPos2),
|
: new BezierConnection(Couple.create(targetPos1, targetPos2),
|
||||||
Couple.create(end1.add(offset1), end2.add(offset2)), Couple.create(normedAxis1, normedAxis2),
|
Couple.create(end1.add(offset1), end2.add(offset2)), Couple.create(normedAxis1, normedAxis2),
|
||||||
Couple.create(normal1, normal2), Couple.create(front1, front2), true, girder);
|
Couple.create(normal1, normal2), true, girder);
|
||||||
|
|
||||||
info.valid = true;
|
info.valid = true;
|
||||||
|
|
||||||
|
@ -324,13 +322,15 @@ public class TrackPlacement {
|
||||||
Vec3 axis = first ? axis1 : axis2;
|
Vec3 axis = first ? axis1 : axis2;
|
||||||
BlockPos pos = first ? pos1 : pos2;
|
BlockPos pos = first ? pos1 : pos2;
|
||||||
BlockState state = first ? state1 : state2;
|
BlockState state = first ? state1 : state2;
|
||||||
|
if (state.hasProperty(TrackBlock.HAS_TURN))
|
||||||
|
state = state.setValue(TrackBlock.HAS_TURN, false);
|
||||||
|
|
||||||
for (int i = 0; i < extent; i++) {
|
for (int i = 0; i < extent; i++) {
|
||||||
Vec3 offset = axis.scale(i);
|
Vec3 offset = axis.scale(i);
|
||||||
BlockPos offsetPos = pos.offset(offset.x, offset.y, offset.z);
|
BlockPos offsetPos = pos.offset(offset.x, offset.y, offset.z);
|
||||||
BlockState stateAtPos = level.getBlockState(offsetPos);
|
BlockState stateAtPos = level.getBlockState(offsetPos);
|
||||||
BlockState toPlace = state;
|
BlockState toPlace = state;
|
||||||
|
|
||||||
boolean canPlace = stateAtPos.getMaterial()
|
boolean canPlace = stateAtPos.getMaterial()
|
||||||
.isReplaceable();
|
.isReplaceable();
|
||||||
if (stateAtPos.getBlock()instanceof ITrackBlock trackAtPos) {
|
if (stateAtPos.getBlock()instanceof ITrackBlock trackAtPos) {
|
||||||
|
@ -361,8 +361,8 @@ public class TrackPlacement {
|
||||||
|
|
||||||
TrackTileEntity tte1 = (TrackTileEntity) te1;
|
TrackTileEntity tte1 = (TrackTileEntity) te1;
|
||||||
TrackTileEntity tte2 = (TrackTileEntity) te2;
|
TrackTileEntity tte2 = (TrackTileEntity) te2;
|
||||||
tte1.addConnection(front1, info.curve);
|
tte1.addConnection(info.curve);
|
||||||
tte2.addConnection(front2, info.curve.secondary());
|
tte2.addConnection(info.curve.secondary());
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package com.simibubi.create.content.logistics.trains.track;
|
package com.simibubi.create.content.logistics.trains.track;
|
||||||
|
|
||||||
import static com.simibubi.create.AllBlockPartials.GIRDER_SEGMENT;
|
import static com.simibubi.create.AllBlockPartials.GIRDER_SEGMENT_BOTTOM;
|
||||||
import static com.simibubi.create.AllBlockPartials.GIRDER_SEGMENT_2;
|
import static com.simibubi.create.AllBlockPartials.GIRDER_SEGMENT_MIDDLE;
|
||||||
|
import static com.simibubi.create.AllBlockPartials.GIRDER_SEGMENT_TOP;
|
||||||
import static com.simibubi.create.AllBlockPartials.TRACK_SEGMENT_LEFT;
|
import static com.simibubi.create.AllBlockPartials.TRACK_SEGMENT_LEFT;
|
||||||
import static com.simibubi.create.AllBlockPartials.TRACK_SEGMENT_RIGHT;
|
import static com.simibubi.create.AllBlockPartials.TRACK_SEGMENT_RIGHT;
|
||||||
import static com.simibubi.create.AllBlockPartials.TRACK_TIE;
|
import static com.simibubi.create.AllBlockPartials.TRACK_TIE;
|
||||||
|
@ -10,6 +11,7 @@ import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.repack.joml.Math;
|
import com.jozufozu.flywheel.repack.joml.Math;
|
||||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack.Pose;
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
import com.simibubi.create.content.logistics.trains.BezierConnection;
|
import com.simibubi.create.content.logistics.trains.BezierConnection;
|
||||||
import com.simibubi.create.content.logistics.trains.BezierConnection.GirderAngles;
|
import com.simibubi.create.content.logistics.trains.BezierConnection.GirderAngles;
|
||||||
|
@ -29,6 +31,7 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||||
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.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
@ -40,22 +43,21 @@ public class TrackRenderer extends SafeTileEntityRenderer<TrackTileEntity> {
|
||||||
@Override
|
@Override
|
||||||
protected void renderSafe(TrackTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light,
|
protected void renderSafe(TrackTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light,
|
||||||
int overlay) {
|
int overlay) {
|
||||||
if (Backend.isOn())
|
Level level = te.getLevel();
|
||||||
|
if (Backend.canUseInstancing(level))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped());
|
VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped());
|
||||||
te.connections.forEach(map -> map.values()
|
te.connections.values()
|
||||||
.forEach(bc -> renderBezierTurn(bc, ms, vb)));
|
.forEach(bc -> renderBezierTurn(level, bc, ms, vb));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void renderBezierTurn(BezierConnection bc, PoseStack ms, VertexConsumer vb) {
|
public static void renderBezierTurn(Level level, BezierConnection bc, PoseStack ms, VertexConsumer vb) {
|
||||||
if (!bc.isPrimary())
|
if (!bc.isPrimary())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ms.pushPose();
|
ms.pushPose();
|
||||||
BlockPos tePosition = bc.tePositions.getFirst();
|
BlockPos tePosition = bc.tePositions.getFirst();
|
||||||
BlockState air = Blocks.AIR.defaultBlockState();
|
BlockState air = Blocks.AIR.defaultBlockState();
|
||||||
ClientLevel level = Minecraft.getInstance().level;
|
|
||||||
SegmentAngles[] segments = bc.getBakedSegments();
|
SegmentAngles[] segments = bc.getBakedSegments();
|
||||||
|
|
||||||
TransformStack.cast(ms)
|
TransformStack.cast(ms)
|
||||||
|
@ -68,17 +70,19 @@ public class TrackRenderer extends SafeTileEntityRenderer<TrackTileEntity> {
|
||||||
int light = LevelRenderer.getLightColor(level, segment.lightPosition.offset(tePosition));
|
int light = LevelRenderer.getLightColor(level, segment.lightPosition.offset(tePosition));
|
||||||
|
|
||||||
CachedBufferer.partial(TRACK_TIE, air)
|
CachedBufferer.partial(TRACK_TIE, air)
|
||||||
.mulPose(segment.tieTransform)
|
.mulPose(segment.tieTransform.pose())
|
||||||
.disableDiffuseMult()
|
.mulNormal(segment.tieTransform.normal())
|
||||||
.light(light)
|
.light(light)
|
||||||
.renderInto(ms, vb);
|
.renderInto(ms, vb);
|
||||||
|
|
||||||
for (boolean first : Iterate.trueAndFalse)
|
for (boolean first : Iterate.trueAndFalse) {
|
||||||
|
Pose transform = segment.railTransforms.get(first);
|
||||||
CachedBufferer.partial(first ? TRACK_SEGMENT_LEFT : TRACK_SEGMENT_RIGHT, air)
|
CachedBufferer.partial(first ? TRACK_SEGMENT_LEFT : TRACK_SEGMENT_RIGHT, air)
|
||||||
.mulPose(segment.railTransforms.get(first))
|
.mulPose(transform.pose())
|
||||||
.disableDiffuseMult()
|
.mulNormal(transform.normal())
|
||||||
.light(light)
|
.light(light)
|
||||||
.renderInto(ms, vb);
|
.renderInto(ms, vb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ms.popPose();
|
ms.popPose();
|
||||||
|
@ -97,19 +101,22 @@ public class TrackRenderer extends SafeTileEntityRenderer<TrackTileEntity> {
|
||||||
int light = LevelRenderer.getLightColor(level, segment.lightPosition.offset(tePosition));
|
int light = LevelRenderer.getLightColor(level, segment.lightPosition.offset(tePosition));
|
||||||
|
|
||||||
for (boolean first : Iterate.trueAndFalse) {
|
for (boolean first : Iterate.trueAndFalse) {
|
||||||
CachedBufferer.partial(GIRDER_SEGMENT_2, air)
|
Pose beamTransform = segment.beams.get(first);
|
||||||
.mulPose(segment.beams.get(first))
|
CachedBufferer.partial(GIRDER_SEGMENT_MIDDLE, air)
|
||||||
.disableDiffuseMult()
|
.mulPose(beamTransform.pose())
|
||||||
|
.mulNormal(beamTransform.normal())
|
||||||
.light(light)
|
.light(light)
|
||||||
.renderInto(ms, vb);
|
.renderInto(ms, vb);
|
||||||
|
|
||||||
for (boolean top : Iterate.trueAndFalse)
|
for (boolean top : Iterate.trueAndFalse) {
|
||||||
CachedBufferer.partial(GIRDER_SEGMENT, air)
|
Pose beamCapTransform = segment.beamCaps.get(top)
|
||||||
.mulPose(segment.beamCaps.get(top)
|
.get(first);
|
||||||
.get(first))
|
CachedBufferer.partial(top ? GIRDER_SEGMENT_TOP : GIRDER_SEGMENT_BOTTOM, air)
|
||||||
.disableDiffuseMult()
|
.mulPose(beamCapTransform.pose())
|
||||||
|
.mulNormal(beamCapTransform.normal())
|
||||||
.light(light)
|
.light(light)
|
||||||
.renderInto(ms, vb);
|
.renderInto(ms, vb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.track;
|
||||||
|
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.util.StringRepresentable;
|
||||||
|
import net.minecraft.world.level.block.Mirror;
|
||||||
|
import net.minecraft.world.level.block.Rotation;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
|
public enum TrackShape implements StringRepresentable {
|
||||||
|
NONE("", Vec3.ZERO),
|
||||||
|
ZO("z_ortho", new Vec3(0, 0, 1)),
|
||||||
|
XO("x_ortho", new Vec3(1, 0, 0)),
|
||||||
|
PD("diag", new Vec3(1, 0, 1)),
|
||||||
|
ND("diag_2", new Vec3(-1, 0, 1)),
|
||||||
|
AN("ascending", 180, new Vec3(0, 1, -1), new Vec3(0, 1, 1)),
|
||||||
|
AS("ascending", 0, new Vec3(0, 1, 1), new Vec3(0, 1, -1)),
|
||||||
|
AE("ascending", 270, new Vec3(1, 1, 0), new Vec3(-1, 1, 0)),
|
||||||
|
AW("ascending", 90, new Vec3(-1, 1, 0), new Vec3(1, 1, 0)),
|
||||||
|
|
||||||
|
CR_O("cross_ortho", new Vec3(0, 0, 1), new Vec3(1, 0, 0)),
|
||||||
|
CR_D("cross_diag", new Vec3(1, 0, 1), new Vec3(-1, 0, 1)),
|
||||||
|
CR_PDX("cross_d1_xo", new Vec3(1, 0, 0), new Vec3(1, 0, 1)),
|
||||||
|
CR_PDZ("cross_d1_zo", new Vec3(0, 0, 1), new Vec3(1, 0, 1)),
|
||||||
|
CR_NDX("cross_d2_xo", new Vec3(1, 0, 0), new Vec3(-1, 0, 1)),
|
||||||
|
CR_NDZ("cross_d2_zo", new Vec3(0, 0, 1), new Vec3(-1, 0, 1));
|
||||||
|
|
||||||
|
private String model;
|
||||||
|
private List<Vec3> axes;
|
||||||
|
private int modelRotation;
|
||||||
|
private Vec3 normal;
|
||||||
|
|
||||||
|
static EnumMap<TrackShape, TrackShape> zMirror = new EnumMap<>(TrackShape.class),
|
||||||
|
xMirror = new EnumMap<>(TrackShape.class), clockwise = new EnumMap<>(TrackShape.class);
|
||||||
|
|
||||||
|
static {
|
||||||
|
zMirror.putAll(ImmutableMap.<TrackShape, TrackShape>builder()
|
||||||
|
.put(PD, ND)
|
||||||
|
.put(ND, PD)
|
||||||
|
.put(AN, AS)
|
||||||
|
.put(AS, AN)
|
||||||
|
.put(CR_PDX, CR_NDX)
|
||||||
|
.put(CR_NDX, CR_PDX)
|
||||||
|
.put(CR_PDZ, CR_NDZ)
|
||||||
|
.put(CR_NDZ, CR_PDZ)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
xMirror.putAll(ImmutableMap.<TrackShape, TrackShape>builder()
|
||||||
|
.put(PD, ND)
|
||||||
|
.put(ND, PD)
|
||||||
|
.put(AE, AW)
|
||||||
|
.put(AW, AE)
|
||||||
|
.put(CR_PDX, CR_NDX)
|
||||||
|
.put(CR_NDX, CR_PDX)
|
||||||
|
.put(CR_PDZ, CR_NDZ)
|
||||||
|
.put(CR_NDZ, CR_PDZ)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
clockwise.putAll(ImmutableMap.<TrackShape, TrackShape>builder()
|
||||||
|
.put(PD, ND)
|
||||||
|
.put(ND, PD)
|
||||||
|
.put(XO, ZO)
|
||||||
|
.put(ZO, XO)
|
||||||
|
.put(AE, AS)
|
||||||
|
.put(AS, AW)
|
||||||
|
.put(AW, AN)
|
||||||
|
.put(AN, AE)
|
||||||
|
.put(CR_PDX, CR_NDZ)
|
||||||
|
.put(CR_NDX, CR_PDZ)
|
||||||
|
.put(CR_PDZ, CR_NDX)
|
||||||
|
.put(CR_NDZ, CR_PDX)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private TrackShape(String model, Vec3 axis) {
|
||||||
|
this(model, 0, axis, new Vec3(0, 1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private TrackShape(String model, Vec3 axis, Vec3 secondAxis) {
|
||||||
|
this.model = model;
|
||||||
|
this.modelRotation = 0;
|
||||||
|
this.normal = new Vec3(0, 1, 0);
|
||||||
|
this.axes = ImmutableList.of(axis, secondAxis);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TrackShape(String model, int modelRotation, Vec3 axis, Vec3 normal) {
|
||||||
|
this.model = model;
|
||||||
|
this.modelRotation = modelRotation;
|
||||||
|
this.normal = normal.normalize();
|
||||||
|
this.axes = ImmutableList.of(axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSerializedName() {
|
||||||
|
return Lang.asId(name());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModel() {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Vec3> getAxes() {
|
||||||
|
return axes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isJunction() {
|
||||||
|
return axes.size() > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3 getNormal() {
|
||||||
|
return normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getModelRotation() {
|
||||||
|
return modelRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackShape mirror(Mirror mirror) {
|
||||||
|
return mirror == Mirror.NONE ? this
|
||||||
|
: mirror == Mirror.FRONT_BACK ? xMirror.getOrDefault(this, this) : zMirror.getOrDefault(this, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackShape rotate(Rotation rotation) {
|
||||||
|
TrackShape shape = this;
|
||||||
|
for (int i = 0; i < rotation.ordinal(); i++)
|
||||||
|
shape = clockwise.getOrDefault(shape, shape);
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,102 +1,118 @@
|
||||||
package com.simibubi.create.content.logistics.trains.track;
|
package com.simibubi.create.content.logistics.trains.track;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableTE;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
||||||
import com.simibubi.create.content.logistics.trains.BezierConnection;
|
import com.simibubi.create.content.logistics.trains.BezierConnection;
|
||||||
|
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
|
||||||
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.IMergeableTE;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.RemoveTileEntityPacket;
|
||||||
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.Couple;
|
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction.Axis;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.ListTag;
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
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;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.phys.AABB;
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.fml.DistExecutor;
|
import net.minecraftforge.fml.DistExecutor;
|
||||||
|
|
||||||
public class TrackTileEntity extends SmartTileEntity {
|
public class TrackTileEntity extends SmartTileEntity implements ITransformableTE, IMergeableTE {
|
||||||
|
|
||||||
Couple<Map<BlockPos, BezierConnection>> connections;
|
Map<BlockPos, BezierConnection> connections;
|
||||||
|
boolean connectionsValidated;
|
||||||
|
|
||||||
public TrackTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
public TrackTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||||
super(type, pos, state);
|
super(type, pos, state);
|
||||||
connections = Couple.create(HashMap::new);
|
connections = new HashMap<>();
|
||||||
|
connectionsValidated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Couple<Map<BlockPos, BezierConnection>> getConnections() {
|
public Map<BlockPos, BezierConnection> getConnections() {
|
||||||
|
if (!level.isClientSide && !connectionsValidated)
|
||||||
|
validateConnections();
|
||||||
return connections;
|
return connections;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addConnection(boolean front, BezierConnection connection) {
|
private void validateConnections() {
|
||||||
connections.get(front)
|
Set<BlockPos> invalid = new HashSet<>();
|
||||||
.put(connection.getKey(), connection);
|
for (Entry<BlockPos, BezierConnection> entry : connections.entrySet()) {
|
||||||
notifyUpdate();
|
BlockPos key = entry.getKey();
|
||||||
level.scheduleTick(worldPosition, getBlockState().getBlock(), 1);
|
BezierConnection bc = entry.getValue();
|
||||||
|
if (key.equals(bc.getKey()) && worldPosition.equals(bc.tePositions.getFirst())) {
|
||||||
|
BlockEntity blockEntity = level.getBlockEntity(key);
|
||||||
|
if (blockEntity instanceof TrackTileEntity trackTE && trackTE.connections.containsKey(worldPosition))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
invalid.add(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
connectionsValidated = true;
|
||||||
|
for (BlockPos blockPos : invalid)
|
||||||
|
removeConnection(blockPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeConnection(boolean front, BlockPos target) {
|
public void addConnection(BezierConnection connection) {
|
||||||
connections.get(front)
|
connections.put(connection.getKey(), connection);
|
||||||
.remove(target);
|
level.scheduleTick(worldPosition, getBlockState().getBlock(), 1);
|
||||||
notifyUpdate();
|
notifyUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO remove TE when all connections removed. seems tricky without a packet
|
public void removeConnection(BlockPos target) {
|
||||||
// because level.removeBlockEntity apparently no longer syncs
|
connections.remove(target);
|
||||||
|
notifyUpdate();
|
||||||
|
if (!connections.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
// if (connections.getFirst()
|
BlockState blockState = getBlockState();
|
||||||
// .isEmpty()
|
if (blockState.hasProperty(TrackBlock.HAS_TURN))
|
||||||
// && connections.getSecond()
|
level.setBlockAndUpdate(worldPosition, blockState.setValue(TrackBlock.HAS_TURN, false));
|
||||||
// .isEmpty()) {
|
AllPackets.channel.send(packetTarget(), new RemoveTileEntityPacket(worldPosition));
|
||||||
// BlockState blockState = getBlockState();
|
|
||||||
// if (!blockState.hasProperty(TrackBlock.HAS_TURN))
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeInboundConnections() {
|
public void removeInboundConnections() {
|
||||||
connections.forEach(map -> map.values()
|
for (BezierConnection bezierConnection : connections.values()) {
|
||||||
.forEach(bc -> {
|
BlockEntity blockEntity = level.getBlockEntity(bezierConnection.getKey());
|
||||||
BlockEntity blockEntity = level.getBlockEntity(bc.getKey());
|
if (!(blockEntity instanceof TrackTileEntity))
|
||||||
if (!(blockEntity instanceof TrackTileEntity))
|
return;
|
||||||
return;
|
TrackTileEntity other = (TrackTileEntity) blockEntity;
|
||||||
TrackTileEntity other = (TrackTileEntity) blockEntity;
|
other.removeConnection(bezierConnection.tePositions.getFirst());
|
||||||
other.removeConnection(bc.trackEnds.getSecond(), bc.tePositions.getFirst());
|
}
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void write(CompoundTag tag, boolean clientPacket) {
|
protected void write(CompoundTag tag, boolean clientPacket) {
|
||||||
super.write(tag, clientPacket);
|
super.write(tag, clientPacket);
|
||||||
|
ListTag listTag = new ListTag();
|
||||||
CompoundTag connectionsTag = new CompoundTag();
|
for (BezierConnection bezierConnection : connections.values())
|
||||||
connections.forEachWithContext((map, first) -> {
|
listTag.add(bezierConnection.write(worldPosition));
|
||||||
ListTag listTag = new ListTag();
|
tag.put("Connections", listTag);
|
||||||
map.values()
|
|
||||||
.forEach(e -> listTag.add(e.write()));
|
|
||||||
connectionsTag.put(first ? "Front" : "Back", listTag);
|
|
||||||
});
|
|
||||||
|
|
||||||
tag.put("Connections", connectionsTag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void read(CompoundTag tag, boolean clientPacket) {
|
protected void read(CompoundTag tag, boolean clientPacket) {
|
||||||
super.read(tag, clientPacket);
|
super.read(tag, clientPacket);
|
||||||
|
connections.clear();
|
||||||
CompoundTag connectionsTag = tag.getCompound("Connections");
|
for (Tag t : tag.getList("Connections", Tag.TAG_COMPOUND)) {
|
||||||
connections.forEach(Map::clear);
|
if (!(t instanceof CompoundTag))
|
||||||
connections.forEachWithContext((map, first) -> connectionsTag.getList(first ? "Front" : "Back", 10)
|
return;
|
||||||
.forEach(t -> {
|
BezierConnection connection = new BezierConnection((CompoundTag) t, worldPosition);
|
||||||
if (!(t instanceof CompoundTag))
|
connections.put(connection.getKey(), connection);
|
||||||
return;
|
}
|
||||||
BezierConnection connection = new BezierConnection((CompoundTag) t);
|
|
||||||
map.put(connection.getKey(), connection);
|
|
||||||
}));
|
|
||||||
|
|
||||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this));
|
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this));
|
||||||
}
|
}
|
||||||
|
@ -109,4 +125,49 @@ public class TrackTileEntity extends SmartTileEntity {
|
||||||
@Override
|
@Override
|
||||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
|
public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(BlockEntity other) {
|
||||||
|
if (other instanceof TrackTileEntity track)
|
||||||
|
connections.putAll(track.connections);
|
||||||
|
connectionsValidated = false;
|
||||||
|
level.scheduleTick(worldPosition, getBlockState().getBlock(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transform(StructureTransform transform) {
|
||||||
|
if (transform.rotationAxis != Axis.Y)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Map<BlockPos, BezierConnection> transformedConnections = new HashMap<>();
|
||||||
|
for (Entry<BlockPos, BezierConnection> entry : connections.entrySet()) {
|
||||||
|
BezierConnection newConnection = entry.getValue();
|
||||||
|
newConnection.normals.replace(transform::applyWithoutOffsetUncentered);
|
||||||
|
newConnection.axes.replace(transform::applyWithoutOffsetUncentered);
|
||||||
|
|
||||||
|
BlockPos diff = newConnection.tePositions.getSecond()
|
||||||
|
.subtract(newConnection.tePositions.getFirst());
|
||||||
|
newConnection.tePositions.setSecond(new BlockPos(Vec3.atCenterOf(newConnection.tePositions.getFirst())
|
||||||
|
.add(transform.applyWithoutOffsetUncentered(Vec3.atLowerCornerOf(diff)))));
|
||||||
|
|
||||||
|
Vec3 teVec = Vec3.atLowerCornerOf(worldPosition);
|
||||||
|
Vec3 teCenterVec = teVec.add(0.5, 0.5, 0.5);
|
||||||
|
Vec3 start = newConnection.starts.getFirst();
|
||||||
|
Vec3 startToTE = start.subtract(teCenterVec);
|
||||||
|
Vec3 endToStart = newConnection.starts.getSecond()
|
||||||
|
.subtract(start);
|
||||||
|
startToTE = transform.applyWithoutOffsetUncentered(startToTE)
|
||||||
|
.add(teCenterVec);
|
||||||
|
endToStart = transform.applyWithoutOffsetUncentered(endToStart)
|
||||||
|
.add(startToTE);
|
||||||
|
|
||||||
|
newConnection.starts.setFirst(new TrackNodeLocation(startToTE).getLocation());
|
||||||
|
newConnection.starts.setSecond(new TrackNodeLocation(endToStart).getLocation());
|
||||||
|
|
||||||
|
BlockPos newTarget = newConnection.getKey();
|
||||||
|
transformedConnections.put(newTarget, newConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
connections = transformedConnections;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks;
|
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
||||||
import com.simibubi.create.content.schematics.item.SchematicItem;
|
import com.simibubi.create.content.schematics.item.SchematicItem;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.IMergeableTE;
|
||||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -190,7 +191,9 @@ public class SchematicPrinter {
|
||||||
BlockEntity tileEntity = blockReader.getBlockEntity(pos);
|
BlockEntity tileEntity = blockReader.getBlockEntity(pos);
|
||||||
|
|
||||||
BlockState toReplace = world.getBlockState(pos);
|
BlockState toReplace = world.getBlockState(pos);
|
||||||
|
BlockEntity toReplaceTE = world.getBlockEntity(pos);
|
||||||
BlockState toReplaceOther = null;
|
BlockState toReplaceOther = null;
|
||||||
|
|
||||||
if (state.hasProperty(BlockStateProperties.BED_PART) && state.hasProperty(BlockStateProperties.HORIZONTAL_FACING)
|
if (state.hasProperty(BlockStateProperties.BED_PART) && state.hasProperty(BlockStateProperties.HORIZONTAL_FACING)
|
||||||
&& state.getValue(BlockStateProperties.BED_PART) == BedPart.FOOT)
|
&& state.getValue(BlockStateProperties.BED_PART) == BedPart.FOOT)
|
||||||
toReplaceOther = world.getBlockState(pos.relative(state.getValue(BlockStateProperties.HORIZONTAL_FACING)));
|
toReplaceOther = world.getBlockState(pos.relative(state.getValue(BlockStateProperties.HORIZONTAL_FACING)));
|
||||||
|
@ -198,11 +201,14 @@ public class SchematicPrinter {
|
||||||
&& state.getValue(BlockStateProperties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER)
|
&& state.getValue(BlockStateProperties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER)
|
||||||
toReplaceOther = world.getBlockState(pos.above());
|
toReplaceOther = world.getBlockState(pos.above());
|
||||||
|
|
||||||
|
boolean mergeTEs = tileEntity != null && toReplaceTE instanceof IMergeableTE mergeTE && toReplaceTE.getType()
|
||||||
|
.equals(tileEntity.getType());
|
||||||
|
|
||||||
if (!world.isLoaded(pos))
|
if (!world.isLoaded(pos))
|
||||||
return false;
|
return false;
|
||||||
if (!world.getWorldBorder().isWithinBounds(pos))
|
if (!world.getWorldBorder().isWithinBounds(pos))
|
||||||
return false;
|
return false;
|
||||||
if (toReplace == state)
|
if (toReplace == state && !mergeTEs)
|
||||||
return false;
|
return false;
|
||||||
if (toReplace.getDestroySpeed(world, pos) == -1
|
if (toReplace.getDestroySpeed(world, pos) == -1
|
||||||
|| (toReplaceOther != null && toReplaceOther.getDestroySpeed(world, pos) == -1))
|
|| (toReplaceOther != null && toReplaceOther.getDestroySpeed(world, pos) == -1))
|
||||||
|
|
|
@ -8,6 +8,7 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllItems;
|
import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.AllKeys;
|
import com.simibubi.create.AllKeys;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
||||||
import com.simibubi.create.content.schematics.SchematicWorld;
|
import com.simibubi.create.content.schematics.SchematicWorld;
|
||||||
import com.simibubi.create.content.schematics.client.tools.Tools;
|
import com.simibubi.create.content.schematics.client.tools.Tools;
|
||||||
import com.simibubi.create.content.schematics.filtering.SchematicInstances;
|
import com.simibubi.create.content.schematics.filtering.SchematicInstances;
|
||||||
|
@ -23,6 +24,7 @@ import com.simibubi.create.foundation.utility.outliner.AABBOutline;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.player.LocalPlayer;
|
import net.minecraft.client.player.LocalPlayer;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction.Axis;
|
||||||
import net.minecraft.core.Vec3i;
|
import net.minecraft.core.Vec3i;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtUtils;
|
import net.minecraft.nbt.NbtUtils;
|
||||||
|
@ -33,6 +35,8 @@ import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.Mirror;
|
import net.minecraft.world.level.block.Mirror;
|
||||||
|
import net.minecraft.world.level.block.Rotation;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
|
||||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||||
|
@ -137,16 +141,27 @@ public class SchematicHandler {
|
||||||
SchematicWorld wMirroredFB = new SchematicWorld(clientWorld);
|
SchematicWorld wMirroredFB = new SchematicWorld(clientWorld);
|
||||||
SchematicWorld wMirroredLR = new SchematicWorld(clientWorld);
|
SchematicWorld wMirroredLR = new SchematicWorld(clientWorld);
|
||||||
StructurePlaceSettings placementSettings = new StructurePlaceSettings();
|
StructurePlaceSettings placementSettings = new StructurePlaceSettings();
|
||||||
|
StructureTransform transform;
|
||||||
BlockPos pos;
|
BlockPos pos;
|
||||||
|
|
||||||
pos = BlockPos.ZERO;
|
pos = BlockPos.ZERO;
|
||||||
schematic.placeInWorld(w, pos, pos, placementSettings, w.getRandom(), Block.UPDATE_CLIENTS);
|
schematic.placeInWorld(w, pos, pos, placementSettings, w.getRandom(), Block.UPDATE_CLIENTS);
|
||||||
|
|
||||||
placementSettings.setMirror(Mirror.FRONT_BACK);
|
placementSettings.setMirror(Mirror.FRONT_BACK);
|
||||||
pos = BlockPos.ZERO.east(size.getX() - 1);
|
pos = BlockPos.ZERO.east(size.getX() - 1);
|
||||||
schematic.placeInWorld(wMirroredFB, pos, pos, placementSettings, wMirroredFB.getRandom(), Block.UPDATE_CLIENTS);
|
schematic.placeInWorld(wMirroredFB, pos, pos, placementSettings, wMirroredFB.getRandom(), Block.UPDATE_CLIENTS);
|
||||||
|
transform = new StructureTransform(placementSettings.getRotationPivot(), Axis.Y, Rotation.NONE,
|
||||||
|
placementSettings.getMirror());
|
||||||
|
for (BlockEntity te : wMirroredFB.getRenderedTileEntities())
|
||||||
|
transform.apply(te);
|
||||||
|
|
||||||
placementSettings.setMirror(Mirror.LEFT_RIGHT);
|
placementSettings.setMirror(Mirror.LEFT_RIGHT);
|
||||||
pos = BlockPos.ZERO.south(size.getZ() - 1);
|
pos = BlockPos.ZERO.south(size.getZ() - 1);
|
||||||
schematic.placeInWorld(wMirroredLR, pos, pos, placementSettings, wMirroredFB.getRandom(), Block.UPDATE_CLIENTS);
|
schematic.placeInWorld(wMirroredLR, pos, pos, placementSettings, wMirroredFB.getRandom(), Block.UPDATE_CLIENTS);
|
||||||
|
transform = new StructureTransform(placementSettings.getRotationPivot(), Axis.Y, Rotation.NONE,
|
||||||
|
placementSettings.getMirror());
|
||||||
|
for (BlockEntity te : wMirroredLR.getRenderedTileEntities())
|
||||||
|
transform.apply(te);
|
||||||
|
|
||||||
renderers.get(0)
|
renderers.get(0)
|
||||||
.display(w);
|
.display(w);
|
||||||
|
@ -187,11 +202,11 @@ public class SchematicHandler {
|
||||||
renderers.get(0)
|
renderers.get(0)
|
||||||
.render(ms, buffer);
|
.render(ms, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active)
|
if (active)
|
||||||
currentTool.getTool()
|
currentTool.getTool()
|
||||||
.renderOnSchematic(ms, buffer);
|
.renderOnSchematic(ms, buffer);
|
||||||
|
|
||||||
ms.popPose();
|
ms.popPose();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -227,7 +242,7 @@ public class SchematicHandler {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentTool.getTool()
|
currentTool.getTool()
|
||||||
.handleRightClick();
|
.handleRightClick();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onKeyInput(int key, boolean pressed) {
|
public void onKeyInput(int key, boolean pressed) {
|
||||||
|
@ -272,10 +287,12 @@ public class SchematicHandler {
|
||||||
|
|
||||||
private boolean itemLost(Player player) {
|
private boolean itemLost(Player player) {
|
||||||
for (int i = 0; i < Inventory.getSelectionSize(); i++) {
|
for (int i = 0; i < Inventory.getSelectionSize(); i++) {
|
||||||
if (!player.getInventory().getItem(i)
|
if (!player.getInventory()
|
||||||
|
.getItem(i)
|
||||||
.sameItem(activeSchematicItem))
|
.sameItem(activeSchematicItem))
|
||||||
continue;
|
continue;
|
||||||
if (!ItemStack.tagMatches(player.getInventory().getItem(i), activeSchematicItem))
|
if (!ItemStack.tagMatches(player.getInventory()
|
||||||
|
.getItem(i), activeSchematicItem))
|
||||||
continue;
|
continue;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -289,7 +306,8 @@ public class SchematicHandler {
|
||||||
public void sync() {
|
public void sync() {
|
||||||
if (activeSchematicItem == null)
|
if (activeSchematicItem == null)
|
||||||
return;
|
return;
|
||||||
AllPackets.channel.sendToServer(new SchematicSyncPacket(activeHotbarSlot, transformation.toSettings(), transformation.getAnchor(), deployed));
|
AllPackets.channel.sendToServer(new SchematicSyncPacket(activeHotbarSlot, transformation.toSettings(),
|
||||||
|
transformation.getAnchor(), deployed));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void equip(Tools tool) {
|
public void equip(Tools tool) {
|
||||||
|
|
|
@ -57,6 +57,7 @@ import com.simibubi.create.foundation.command.SConfigureConfigPacket;
|
||||||
import com.simibubi.create.foundation.config.ui.CConfigureConfigPacket;
|
import com.simibubi.create.foundation.config.ui.CConfigureConfigPacket;
|
||||||
import com.simibubi.create.foundation.gui.container.ClearContainerPacket;
|
import com.simibubi.create.foundation.gui.container.ClearContainerPacket;
|
||||||
import com.simibubi.create.foundation.gui.container.GhostItemSubmitPacket;
|
import com.simibubi.create.foundation.gui.container.GhostItemSubmitPacket;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.RemoveTileEntityPacket;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCountUpdatePacket;
|
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCountUpdatePacket;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket;
|
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket;
|
||||||
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||||
|
@ -132,6 +133,7 @@ public enum AllPackets {
|
||||||
PERSISTENT_DATA(ISyncPersistentData.PersistentDataPacket.class, ISyncPersistentData.PersistentDataPacket::new, PLAY_TO_CLIENT),
|
PERSISTENT_DATA(ISyncPersistentData.PersistentDataPacket.class, ISyncPersistentData.PersistentDataPacket::new, PLAY_TO_CLIENT),
|
||||||
SYNC_POTATO_PROJECTILE_TYPES(PotatoProjectileTypeManager.SyncPacket.class, PotatoProjectileTypeManager.SyncPacket::new, PLAY_TO_CLIENT),
|
SYNC_POTATO_PROJECTILE_TYPES(PotatoProjectileTypeManager.SyncPacket.class, PotatoProjectileTypeManager.SyncPacket::new, PLAY_TO_CLIENT),
|
||||||
SYNC_RAIL_GRAPH(RailGraphSyncPacket.class, RailGraphSyncPacket::new, PLAY_TO_CLIENT),
|
SYNC_RAIL_GRAPH(RailGraphSyncPacket.class, RailGraphSyncPacket::new, PLAY_TO_CLIENT),
|
||||||
|
REMOVE_TE(RemoveTileEntityPacket.class, RemoveTileEntityPacket::new, PLAY_TO_CLIENT),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.simibubi.create.foundation.tileEntity;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
|
||||||
|
public interface IMergeableTE {
|
||||||
|
|
||||||
|
public void accept(BlockEntity other);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.simibubi.create.foundation.tileEntity;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.networking.TileEntityDataPacket;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
|
public class RemoveTileEntityPacket extends TileEntityDataPacket<SyncedTileEntity> {
|
||||||
|
|
||||||
|
public RemoveTileEntityPacket(BlockPos pos) {
|
||||||
|
super(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RemoveTileEntityPacket(FriendlyByteBuf buffer) {
|
||||||
|
super(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeData(FriendlyByteBuf buffer) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handlePacket(SyncedTileEntity tile) {
|
||||||
|
tile.setRemoved();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import javax.annotation.Nullable;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
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.foundation.tileEntity.IMergeableTE;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
|
@ -200,15 +201,12 @@ public class BlockHelper {
|
||||||
int idx = chunk.getSectionIndex(target.getY());
|
int idx = chunk.getSectionIndex(target.getY());
|
||||||
LevelChunkSection chunksection = chunk.getSection(idx);
|
LevelChunkSection chunksection = chunk.getSection(idx);
|
||||||
if (chunksection == null) {
|
if (chunksection == null) {
|
||||||
chunksection = new LevelChunkSection(chunk.getSectionYFromSectionIndex(idx),
|
chunksection = new LevelChunkSection(chunk.getSectionYFromSectionIndex(idx), world.registryAccess()
|
||||||
world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY));
|
.registryOrThrow(Registry.BIOME_REGISTRY));
|
||||||
chunk.getSections()[idx] = chunksection;
|
chunk.getSections()[idx] = chunksection;
|
||||||
}
|
}
|
||||||
BlockState old = chunksection.setBlockState(
|
BlockState old = chunksection.setBlockState(SectionPos.sectionRelative(target.getX()),
|
||||||
SectionPos.sectionRelative(target.getX()),
|
SectionPos.sectionRelative(target.getY()), SectionPos.sectionRelative(target.getZ()), state);
|
||||||
SectionPos.sectionRelative(target.getY()),
|
|
||||||
SectionPos.sectionRelative(target.getZ()),
|
|
||||||
state);
|
|
||||||
chunk.setUnsaved(true);
|
chunk.setUnsaved(true);
|
||||||
world.markAndNotifyBlock(target, chunk, old, state, 82, 512);
|
world.markAndNotifyBlock(target, chunk, old, state, 82, 512);
|
||||||
|
|
||||||
|
@ -219,6 +217,8 @@ public class BlockHelper {
|
||||||
|
|
||||||
public static void placeSchematicBlock(Level world, BlockState state, BlockPos target, ItemStack stack,
|
public static void placeSchematicBlock(Level world, BlockState state, BlockPos target, ItemStack stack,
|
||||||
@Nullable CompoundTag data) {
|
@Nullable CompoundTag data) {
|
||||||
|
BlockEntity existingTile = world.getBlockEntity(target);
|
||||||
|
|
||||||
// Piston
|
// Piston
|
||||||
if (state.hasProperty(BlockStateProperties.EXTENDED))
|
if (state.hasProperty(BlockStateProperties.EXTENDED))
|
||||||
state = state.setValue(BlockStateProperties.EXTENDED, Boolean.FALSE);
|
state = state.setValue(BlockStateProperties.EXTENDED, Boolean.FALSE);
|
||||||
|
@ -259,6 +259,14 @@ public class BlockHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
|
if (existingTile instanceof IMergeableTE mergeable) {
|
||||||
|
BlockEntity loaded = BlockEntity.loadStatic(target, state, data);
|
||||||
|
if (existingTile.getType()
|
||||||
|
.equals(loaded.getType())) {
|
||||||
|
mergeable.accept(loaded);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
BlockEntity tile = world.getBlockEntity(target);
|
BlockEntity tile = world.getBlockEntity(target);
|
||||||
if (tile != null) {
|
if (tile != null) {
|
||||||
data.putInt("x", target.getX());
|
data.putInt("x", target.getX());
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"credit": "Made with Blockbench",
|
||||||
|
"textures": {
|
||||||
|
"0": "create:block/girder"
|
||||||
|
},
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"from": [-4, -1, 0],
|
||||||
|
"to": [4, 1, 8],
|
||||||
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, 13, 8]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [12, 2, 16, 3], "texture": "#0"},
|
||||||
|
"east": {"uv": [1, 5, 5, 4], "texture": "#0"},
|
||||||
|
"south": {"uv": [12, 2, 16, 3], "texture": "#0"},
|
||||||
|
"west": {"uv": [3, 5, 7, 4], "texture": "#0"},
|
||||||
|
"up": {"uv": [12, 0, 16, 4], "rotation": 270, "texture": "#0"},
|
||||||
|
"down": {"uv": [2, 0, 6, 4], "rotation": 270, "texture": "#0"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in a new issue