Junction Printer

- Fixed Stations and Signals not properly rotating with schematics
- Fixed Bezier tracks not costing anything to the cannon
- Fixed Bezier tracks not being placed by the cannon
This commit is contained in:
simibubi 2022-05-18 20:36:58 +02:00
parent 05bacd7a4e
commit 6353eedf13
7 changed files with 163 additions and 24 deletions

View file

@ -298,18 +298,26 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
public void addItemsToPlayer(Player player) {
Inventory inv = player.getInventory();
int tracks = (getSegmentCount() + 1) / 2;
int tracks = getTrackItemCost();
while (tracks > 0) {
inv.placeItemBackInInventory(AllBlocks.TRACK.asStack(Math.min(64, tracks)));
tracks -= 64;
}
int girders = hasGirder ? ((getSegmentCount() + 1) / 2) * 2 : 0;
int girders = getGirderItemCost();
while (girders > 0) {
inv.placeItemBackInInventory(AllBlocks.METAL_GIRDER.asStack(Math.min(64, girders)));
girders -= 64;
}
}
public int getGirderItemCost() {
return hasGirder ? getTrackItemCost() * 2 : 0;
}
public int getTrackItemCost() {
return (getSegmentCount() + 1) / 2;
}
public void spawnItems(Level level) {
if (!level.getGameRules()
.getBoolean(GameRules.RULE_DOBLOCKDROPS))

View file

@ -52,6 +52,16 @@ public class TrackEdge {
.normalize();
}
public Vec3 getDirectionAt(double t) {
double length = getLength();
double step = .5f / length;
t /= length;
Vec3 ahead = getPosition(Math.min(1, t + step));
Vec3 behind = getPosition(Math.max(0, t - step));
return ahead.subtract(behind)
.normalize();
}
public boolean canTravelTo(TrackEdge other) {
if (isInterDimensional() || other.isInterDimensional())
return true;

View file

@ -8,6 +8,7 @@ import javax.annotation.Nullable;
import com.jozufozu.flywheel.core.PartialModel;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
import com.simibubi.create.content.logistics.trains.DimensionPalette;
import com.simibubi.create.content.logistics.trains.GraphLocation;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
@ -18,11 +19,13 @@ import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SingleTileEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint;
import com.simibubi.create.content.logistics.trains.track.BezierTrackPointLocation;
import com.simibubi.create.content.schematics.SchematicWorld;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
@ -32,6 +35,7 @@ import net.minecraft.core.Direction.Axis;
import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
@ -49,6 +53,9 @@ public class TrackTargetingBehaviour<T extends TrackEdgePoint> extends TileEntit
private AxisDirection targetDirection;
private UUID id;
private Vec3 prevDirection;
private Vec3 rotatedDirection;
private CompoundTag migrationData;
private EdgePointType<T> edgePointType;
private T edgePoint;
@ -64,12 +71,21 @@ public class TrackTargetingBehaviour<T extends TrackEdgePoint> extends TileEntit
orthogonal = false;
}
@Override
public boolean isSafeNBT() {
return true;
}
@Override
public void write(CompoundTag nbt, boolean clientPacket) {
nbt.putUUID("Id", id);
nbt.put("TargetTrack", NbtUtils.writeBlockPos(targetTrack));
nbt.putBoolean("Ortho", orthogonal);
nbt.putBoolean("TargetDirection", targetDirection == AxisDirection.POSITIVE);
if (rotatedDirection != null)
nbt.put("RotatedAxis", VecHelper.writeNBT(rotatedDirection));
if (prevDirection != null)
nbt.put("PrevAxis", VecHelper.writeNBT(prevDirection));
if (migrationData != null && !clientPacket)
nbt.put("Migrate", migrationData);
if (targetBezier != null) {
@ -84,10 +100,14 @@ public class TrackTargetingBehaviour<T extends TrackEdgePoint> extends TileEntit
@Override
public void read(CompoundTag nbt, boolean clientPacket) {
id = nbt.getUUID("Id");
id = nbt.contains("Id") ? nbt.getUUID("Id") : UUID.randomUUID();
targetTrack = NbtUtils.readBlockPos(nbt.getCompound("TargetTrack"));
targetDirection = nbt.getBoolean("TargetDirection") ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE;
orthogonal = nbt.getBoolean("Ortho");
if (nbt.contains("PrevAxis"))
prevDirection = VecHelper.readNBT(nbt.getList("PrevAxis", Tag.TAG_DOUBLE));
if (nbt.contains("RotatedAxis"))
rotatedDirection = VecHelper.readNBT(nbt.getList("RotatedAxis", Tag.TAG_DOUBLE));
if (nbt.contains("Migrate"))
migrationData = nbt.getCompound("Migrate");
if (clientPacket)
@ -144,12 +164,26 @@ public class TrackTargetingBehaviour<T extends TrackEdgePoint> extends TileEntit
TrackNode node2 = graph.locateNode(loc.edge.getSecond());
TrackEdge edge = graph.getConnectionsFrom(node1)
.get(node2);
boolean front = getTargetDirection() == AxisDirection.POSITIVE;
if (edge == null)
return null;
T point = edgePointType.create();
boolean front = getTargetDirection() == AxisDirection.POSITIVE;
prevDirection = edge.getDirectionAt(loc.position)
.scale(front ? -1 : 1);
if (rotatedDirection != null) {
double dot = prevDirection.dot(rotatedDirection);
if (dot < -.85f) {
rotatedDirection = null;
targetDirection = targetDirection.opposite();
return null;
}
rotatedDirection = null;
}
double length = edge.getLength();
CompoundTag data = migrationData;
migrationData = null;
@ -183,13 +217,11 @@ public class TrackTargetingBehaviour<T extends TrackEdgePoint> extends TileEntit
}
}
T point = edgePointType.create();
boolean reverseEdge = front || point instanceof SingleTileEdgePoint;
if (data != null)
point.read(data, true, DimensionPalette.read(data));
point.setId(id);
boolean reverseEdge = front || point instanceof SingleTileEdgePoint;
point.setLocation(reverseEdge ? loc.edge : loc.edge.swap(), reverseEdge ? loc.position : length - loc.position);
point.tileAdded(tileEntity, front);
loc.graph.addPoint(edgePointType, point);
@ -262,6 +294,8 @@ public class TrackTargetingBehaviour<T extends TrackEdgePoint> extends TileEntit
public static void render(LevelAccessor level, BlockPos pos, AxisDirection direction,
BezierTrackPointLocation bezier, PoseStack ms, MultiBufferSource buffer, int light, int overlay,
RenderedTrackOverlayType type, float scale) {
if (level instanceof SchematicWorld)
return;
BlockState trackState = level.getBlockState(pos);
Block block = trackState.getBlock();
@ -284,4 +318,16 @@ public class TrackTargetingBehaviour<T extends TrackEdgePoint> extends TileEntit
ms.popPose();
}
public void transform(StructureTransform transform) {
id = UUID.randomUUID();
targetTrack = transform.applyWithoutOffset(targetTrack);
if (prevDirection != null)
rotatedDirection = transform.applyWithoutOffsetUncentered(prevDirection);
if (targetBezier != null)
targetBezier = new BezierTrackPointLocation(transform.applyWithoutOffset(targetBezier.curveTarget()
.subtract(getPos()))
.offset(getPos()), targetBezier.segment());
tileEntity.notifyUpdate();
}
}

View file

@ -4,6 +4,8 @@ import java.util.List;
import javax.annotation.Nullable;
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.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBlock.SignalType;
@ -19,7 +21,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.ticks.TickPriority;
public class SignalTileEntity extends SmartTileEntity {
public class SignalTileEntity extends SmartTileEntity implements ITransformableTE {
public static enum OverlayState {
RENDER, SKIP, DUAL
@ -153,4 +155,9 @@ public class SignalTileEntity extends SmartTileEntity {
return new AABB(worldPosition, edgePoint.getGlobalPosition()).inflate(2);
}
@Override
public void transform(StructureTransform transform) {
edgePoint.transform(transform);
}
}

View file

@ -17,6 +17,8 @@ import com.simibubi.create.AllItems;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableTE;
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
import com.simibubi.create.content.logistics.block.depot.DepotBehaviour;
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
@ -71,7 +73,7 @@ import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.network.PacketDistributor;
public class StationTileEntity extends SmartTileEntity {
public class StationTileEntity extends SmartTileEntity implements ITransformableTE {
public TrackTargetingBehaviour<GlobalStation> edgePoint;
public LerpedFloat flag;
@ -700,4 +702,9 @@ public class StationTileEntity extends SmartTileEntity {
return true;
}
@Override
public void transform(StructureTransform transform) {
edgePoint.transform(transform);
}
}

View file

@ -36,6 +36,9 @@ import com.simibubi.create.content.logistics.trains.TrackNodeLocation.Discovered
import com.simibubi.create.content.logistics.trains.TrackPropagator;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour.RenderedTrackOverlayType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity;
import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement;
import com.simibubi.create.content.schematics.ItemRequirement;
import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
import com.simibubi.create.foundation.block.render.DestroyProgressRenderingHandler;
import com.simibubi.create.foundation.block.render.ReducedDestroyEffects;
import com.simibubi.create.foundation.utility.AngleHelper;
@ -61,6 +64,7 @@ import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
@ -94,7 +98,7 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.IBlockRenderProperties;
public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrackBlock {
public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrackBlock, ISpecialBlockItemRequirement {
public static final EnumProperty<TrackShape> SHAPE = EnumProperty.create("shape", TrackShape.class);
public static final BooleanProperty HAS_TE = BooleanProperty.create("turn");
@ -688,6 +692,33 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
&& state1.setValue(HAS_TE, false) == state2.setValue(HAS_TE, false);
}
@Override
public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) {
int trackAmount = 1;
int girderAmount = 0;
if (te instanceof TrackTileEntity track) {
for (BezierConnection bezierConnection : track.getConnections().values()) {
if (!bezierConnection.isPrimary())
continue;
trackAmount += bezierConnection.getTrackItemCost();
girderAmount += bezierConnection.getGirderItemCost();
}
}
List<ItemStack> stacks = new ArrayList<>();
while (trackAmount > 0) {
stacks.add(AllBlocks.TRACK.asStack(Math.min(trackAmount, 64)));
trackAmount -= 64;
}
while (girderAmount > 0) {
stacks.add(AllBlocks.METAL_GIRDER.asStack(Math.min(girderAmount, 64)));
girderAmount -= 64;
}
return new ItemRequirement(ItemUseType.CONSUME, stacks);
}
public static class RenderProperties extends ReducedDestroyEffects implements DestroyProgressRenderingHandler {
@Override
public boolean renderDestroyProgress(ClientLevel level, LevelRenderer renderer, int breakerId, BlockPos pos,

View file

@ -12,12 +12,14 @@ import com.simibubi.create.AllBlocks;
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.ITrackBlock;
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.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.Debug;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.core.BlockPos;
@ -69,15 +71,34 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE
private void validateConnections() {
Set<BlockPos> invalid = new HashSet<>();
for (Entry<BlockPos, BezierConnection> entry : connections.entrySet()) {
BlockPos key = entry.getKey();
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;
if (!key.equals(bc.getKey()) || !worldPosition.equals(bc.tePositions.getFirst())) {
invalid.add(key);
continue;
}
invalid.add(key);
BlockState blockState = level.getBlockState(key);
if (blockState.getBlock()instanceof ITrackBlock trackBlock && !blockState.getValue(TrackBlock.HAS_TE))
for (Vec3 v : trackBlock.getTrackAxes(level, key, blockState)) {
Vec3 bcEndAxis = bc.axes.getSecond();
if (v.distanceTo(bcEndAxis) < 1 / 1024f || v.distanceTo(bcEndAxis.scale(-1)) < 1 / 1024f)
level.setBlock(key, blockState.setValue(TrackBlock.HAS_TE, true), 3);
else
Debug.debugChat(v + " != " + bcEndAxis);
}
BlockEntity blockEntity = level.getBlockEntity(key);
if (!(blockEntity instanceof TrackTileEntity trackTE) || blockEntity.isRemoved()) {
invalid.add(key);
continue;
}
if (!trackTE.connections.containsKey(worldPosition))
trackTE.addConnection(bc.secondary());
}
connectionsValidated = true;
@ -125,20 +146,29 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE
setChanged();
}
@Override
public void writeSafe(CompoundTag tag, boolean clientPacket) {
super.writeSafe(tag, clientPacket);
writeTurns(tag);
}
@Override
protected void write(CompoundTag tag, boolean clientPacket) {
super.write(tag, clientPacket);
writeTurns(tag);
if (boundLocation == null)
return;
tag.put("BoundLocation", NbtUtils.writeBlockPos(boundLocation.getSecond()));
tag.putString("BoundDimension", boundLocation.getFirst()
.location()
.toString());
}
private void writeTurns(CompoundTag tag) {
ListTag listTag = new ListTag();
for (BezierConnection bezierConnection : connections.values())
listTag.add(bezierConnection.write(worldPosition));
tag.put("Connections", listTag);
if (boundLocation != null) {
tag.put("BoundLocation", NbtUtils.writeBlockPos(boundLocation.getSecond()));
tag.putString("BoundDimension", boundLocation.getFirst()
.location()
.toString());
}
}
@Override