Signal distancing

- Signals and Stations can no longer share a location on a track
- Multiple stations can no longer share a location on a track
- Signals and Stations now render their overlay during the track selection process
This commit is contained in:
simibubi 2022-04-15 00:12:40 +02:00
parent 3e744db3dd
commit 502f2068cb
30 changed files with 387 additions and 107 deletions

View file

@ -543,22 +543,22 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
7fbb25c577025ff61388c54c43401d8bb80723dd assets/create/lang/en_ud.json
21a0ec20b110e23e7a44e31117dc5861a5c44b3e assets/create/lang/en_us.json
16f34e19d584fcaa1182f9fdf2cfc98f44547727 assets/create/lang/unfinished/de_de.json
74ab4c2c55ddcb691701e2cefb4602f6d4c3f605 assets/create/lang/unfinished/es_cl.json
077b360ede4375444a4233fc1f466d7fe4f1c3bc assets/create/lang/unfinished/es_es.json
b56fd9dcde4d86625ee7bac054a1930d261abbfe assets/create/lang/unfinished/fr_fr.json
588c9afc4ef58d978ed0de8ea96cf63bb936b776 assets/create/lang/unfinished/it_it.json
b7bcc397c94d218a543c4c9ce92f76a248f53cdf assets/create/lang/unfinished/ja_jp.json
8fdfe59e7b0b03e8eb630e9a11daaa074c332d2c assets/create/lang/unfinished/ko_kr.json
798baf454ac567a2e45b94455c7deee98c68ae77 assets/create/lang/unfinished/nl_nl.json
8a942df61c06c81ca7cb065acb9209ff67a645ff assets/create/lang/unfinished/pl_pl.json
ddbda3b983cd89129b260ea831e5f84c05521156 assets/create/lang/unfinished/pt_br.json
05dc11303c62b5ed0e86297a32c96e3a9f1c3cae assets/create/lang/unfinished/pt_pt.json
55e83bbfa05e4d524a570fa3da522fb6f094242c assets/create/lang/unfinished/ro_ro.json
a12be55cac22714da6c30770b7f966ad04505c15 assets/create/lang/unfinished/ru_ru.json
99846a9c58ba657a3f7b13a35927a05932125e73 assets/create/lang/unfinished/zh_cn.json
7462a0b282e5233f651aaa618d776201d6260968 assets/create/lang/unfinished/zh_tw.json
7e435e07260a70aaed229404bd8404a8d2f4146d assets/create/lang/en_us.json
a07abc26a0f35dc516bb2ea0dfe372f35d74a2b9 assets/create/lang/unfinished/de_de.json
e1df1ec44c3b3fc33bf519c474f9296fdf124f5b assets/create/lang/unfinished/es_cl.json
12353413a397b287924a2f72acbdf61a58a145eb assets/create/lang/unfinished/es_es.json
11dd818781023f97b86a197f26f09b859d189ce6 assets/create/lang/unfinished/fr_fr.json
f503be711b19278b05a54cf16077a72787b09bd7 assets/create/lang/unfinished/it_it.json
4bae3ae77ddcf5a0284731b1816e035f6fe58253 assets/create/lang/unfinished/ja_jp.json
e421c88c3aa465136414a60c1af71fd31a6a31b8 assets/create/lang/unfinished/ko_kr.json
548acc508ae8b106501d4c0617447559f6ccdb9a assets/create/lang/unfinished/nl_nl.json
792d1859b3d850136d5757bec2c648764b3b90e2 assets/create/lang/unfinished/pl_pl.json
94d7667331e4bea254b21bb799703dcf8229516e assets/create/lang/unfinished/pt_br.json
3dc867a8a1c2a061e25bf3e4ca3e035cbb8a32f3 assets/create/lang/unfinished/pt_pt.json
4f24b259987998bd606096d83c13b26cdd7e0acc assets/create/lang/unfinished/ro_ro.json
a0709243bbdd2846b47f8388f7654314e0d2b357 assets/create/lang/unfinished/ru_ru.json
dcf1c00ffcd040619092d16e1bb5bd389482379d assets/create/lang/unfinished/zh_cn.json
7a0670419615f5a0f312e2516f6baec2f1be84f8 assets/create/lang/unfinished/zh_tw.json
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json

View file

@ -1441,6 +1441,8 @@
"create.track_target.missing": "Right-click the targeted train track first",
"create.track_target.too_far": "Targeted track is too far from here",
"create.track_target.no_junctions": "Targeted track cannot be an intersection",
"create.track_target.occupied": "Targeted track is occupied",
"create.track_target.invalid": "Cannot target this track here",
"create.train.unnamed": "Unnamed Train",
"create.train.cannot_relocate_moving": "Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1526",
"_": "Missing Localizations: 1528",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 537",
"_": "Missing Localizations: 539",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 208",
"_": "Missing Localizations: 210",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1788",
"_": "Missing Localizations: 1790",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1477",
"_": "Missing Localizations: 1479",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 203",
"_": "Missing Localizations: 205",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 203",
"_": "Missing Localizations: 205",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 2141",
"_": "Missing Localizations: 2143",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 576",
"_": "Missing Localizations: 578",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1388",
"_": "Missing Localizations: 1390",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1760",
"_": "Missing Localizations: 1762",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 204",
"_": "Missing Localizations: 206",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 581",
"_": "Missing Localizations: 583",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 203",
"_": "Missing Localizations: 205",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 595",
"_": "Missing Localizations: 597",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1442,6 +1442,8 @@
"create.track_target.missing": "UNLOCALIZED: Right-click the targeted train track first",
"create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here",
"create.track_target.no_junctions": "UNLOCALIZED: Targeted track cannot be an intersection",
"create.track_target.occupied": "UNLOCALIZED: Targeted track is occupied",
"create.track_target.invalid": "UNLOCALIZED: Cannot target this track here",
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
"create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train",

View file

@ -1351,7 +1351,8 @@ public class AllBlocks {
.register();
public static final BlockEntry<StationBlock> TRACK_STATION = REGISTRATE.block("track_station", StationBlock::new)
.initialProperties(SharedProperties::wooden)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.transform(axeOrPickaxe())
.blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.partialBaseModel(c, p)))
.onRegister(assignDataBehaviour(new StationSummaryDataSource(), "station_summary"))
@ -1387,6 +1388,7 @@ public class AllBlocks {
public static final BlockEntry<ControlsBlock> CONTROLS = REGISTRATE.block("controls", ControlsBlock::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.blockstate((c, p) -> p.horizontalBlock(c.get(),
s -> AssetLookup.partialBaseModel(c, p, s.getValue(ControlsBlock.OPEN) ? "open" : "closed")))
.onRegister(addMovementBehaviour(new ControlsMovementBehaviour()))

View file

@ -4,8 +4,12 @@ import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
import com.simibubi.create.content.logistics.trains.track.BezierTrackPointLocation;
import com.simibubi.create.content.logistics.trains.track.TrackTileEntity;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.core.BlockPos;
@ -16,10 +20,11 @@ import net.minecraft.world.phys.Vec3;
public class TrackGraphHelper {
@Nullable
public static GraphLocation getGraphLocationAt(Level level, BlockPos pos, AxisDirection targetDirection,
Vec3 targetAxis) {
BlockState trackBlockState = level.getBlockState(pos);
if (!(trackBlockState.getBlock()instanceof ITrackBlock track))
if (!(trackBlockState.getBlock() instanceof ITrackBlock track))
return null;
Vec3 axis = targetAxis.scale(targetDirection.getStep());
@ -123,4 +128,48 @@ public class TrackGraphHelper {
return graphLocation;
}
@Nullable
public static GraphLocation getBezierGraphLocationAt(Level level, BlockPos pos, AxisDirection targetDirection,
BezierTrackPointLocation targetBezier) {
BlockState state = level.getBlockState(pos);
if (!(state.getBlock() instanceof ITrackBlock track))
return null;
if (!(level.getBlockEntity(pos) instanceof TrackTileEntity trackTE))
return null;
BezierConnection bc = trackTE.getConnections()
.get(targetBezier.curveTarget());
if (bc == null || !bc.isPrimary())
return null;
TrackNodeLocation targetLoc = new TrackNodeLocation(bc.starts.getSecond());
for (DiscoveredLocation location : track.getConnected(level, pos, state, true, null)) {
TrackGraph graph = Create.RAILWAYS.sided(level)
.getGraph(level, location);
if (graph == null)
continue;
TrackNode targetNode = graph.locateNode(targetLoc);
if (targetNode == null)
continue;
TrackNode node = graph.locateNode(location);
TrackEdge edge = graph.getConnectionsFrom(node)
.get(targetNode);
if (edge == null)
continue;
GraphLocation graphLocation = new GraphLocation();
graphLocation.graph = graph;
graphLocation.edge = Couple.create(location, targetLoc);
graphLocation.position = (targetBezier.segment() + 1) / 2f;
if (targetDirection == AxisDirection.POSITIVE) {
graphLocation.edge = graphLocation.edge.swap();
graphLocation.position = edge.getLength(node, targetNode) - graphLocation.position;
}
return graphLocation;
}
return null;
}
}

View file

@ -1,10 +1,17 @@
package com.simibubi.create.content.logistics.trains.management.edgePoint;
import org.apache.commons.lang3.mutable.MutableObject;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem.OverlapResult;
import com.simibubi.create.content.logistics.trains.track.BezierTrackPointLocation;
import com.simibubi.create.content.logistics.trains.track.TrackTileEntity;
import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
@ -61,10 +68,22 @@ public class CurvedTrackSelectionPacket extends TileEntityConfigurationPacket<Tr
.getItem(slot);
if (!(stack.getItem() instanceof TrackTargetingBlockItem))
return;
if (player.isSteppingCarefully() && stack.hasTag()) {
player.displayClientMessage(Lang.translate("track_target.clear"), true);
stack.setTag(null);
AllSoundEvents.CONTROLLER_CLICK.play(player.level, null, pos, 1, .5f);
return;
}
EdgePointType<?> type = AllBlocks.TRACK_SIGNAL.isIn(stack) ? EdgePointType.SIGNAL : EdgePointType.STATION;
MutableObject<OverlapResult> result = new MutableObject<>(null);
TrackTargetingBlockItem.withGraphLocation(player.level, pos, front,
new BezierTrackPointLocation(targetPos, segment), type, (overlap, location) -> result.setValue(overlap));
if (result.getValue().feedback != null) {
player.displayClientMessage(Lang.translate(result.getValue().feedback)
.withStyle(ChatFormatting.RED), true);
AllSoundEvents.DENY.play(player.level, null, pos, .5f, 1);
return;
}
@ -80,6 +99,7 @@ public class CurvedTrackSelectionPacket extends TileEntityConfigurationPacket<Tr
player.displayClientMessage(Lang.translate("track_target.set"), true);
stack.setTag(stackTag);
AllSoundEvents.CONTROLLER_CLICK.play(player.level, null, pos, 1, 1);
}
@Override

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.logistics.trains.management.edgePoint;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
@ -7,24 +8,19 @@ 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.logistics.trains.BezierConnection;
import com.simibubi.create.content.logistics.trains.GraphLocation;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackGraphHelper;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
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.logistics.trains.track.TrackTileEntity;
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.Couple;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.client.renderer.LevelRenderer;
@ -245,57 +241,16 @@ public class TrackTargetingBehaviour<T extends TrackEdgePoint> extends TileEntit
}
public GraphLocation determineGraphLocation() {
if (targetBezier != null)
return determineBezierGraphLocation();
Level level = getWorld();
BlockPos pos = getGlobalPosition();
BlockState state = getTrackBlockState();
return TrackGraphHelper.getGraphLocationAt(level, pos, getTargetDirection(),
getTrack().getTrackAxes(level, pos, state)
.get(0));
}
ITrackBlock track = getTrack();
List<Vec3> trackAxes = track.getTrackAxes(level, pos, state);
AxisDirection targetDirection = getTargetDirection();
public GraphLocation determineBezierGraphLocation() {
Level level = getWorld();
BlockPos pos = getGlobalPosition();
BlockState state = getTrackBlockState();
if (!(state.getBlock() instanceof ITrackBlock track))
return null;
if (!(level.getBlockEntity(pos) instanceof TrackTileEntity trackTE))
return null;
BezierConnection bc = trackTE.getConnections()
.get(targetBezier.curveTarget());
if (bc == null || !bc.isPrimary())
return null;
TrackNodeLocation targetLoc = new TrackNodeLocation(bc.starts.getSecond());
for (DiscoveredLocation location : track.getConnected(level, pos, state, true, null)) {
TrackGraph graph = Create.RAILWAYS.sided(level)
.getGraph(level, location);
if (graph == null)
continue;
TrackNode targetNode = graph.locateNode(targetLoc);
if (targetNode == null)
continue;
TrackNode node = graph.locateNode(location);
TrackEdge edge = graph.getConnectionsFrom(node)
.get(targetNode);
if (edge == null)
continue;
GraphLocation graphLocation = new GraphLocation();
graphLocation.graph = graph;
graphLocation.edge = Couple.create(location, targetLoc);
graphLocation.position = (targetBezier.segment() + 1) / 2f;
if (targetDirection == AxisDirection.POSITIVE) {
graphLocation.edge = graphLocation.edge.swap();
graphLocation.position = edge.getLength(node, targetNode) - graphLocation.position;
}
return graphLocation;
}
return null;
return targetBezier != null
? TrackGraphHelper.getBezierGraphLocationAt(level, pos, targetDirection, targetBezier)
: TrackGraphHelper.getGraphLocationAt(level, pos, targetDirection, trackAxes.get(0));
}
public static enum RenderedTrackOverlayType {
@ -304,8 +259,9 @@ public class TrackTargetingBehaviour<T extends TrackEdgePoint> extends TileEntit
@OnlyIn(Dist.CLIENT)
public static void render(LevelAccessor level, BlockPos pos, AxisDirection direction,
BezierTrackPointLocation bezier, int tintColor, PoseStack ms, MultiBufferSource buffer, int light, int overlay,
RenderedTrackOverlayType type) {
BezierTrackPointLocation bezier, PoseStack ms, MultiBufferSource buffer, int light, int overlay,
RenderedTrackOverlayType type, float scale) {
BlockState trackState = level.getBlockState(pos);
Block block = trackState.getBlock();
if (!(block instanceof ITrackBlock))
@ -318,6 +274,9 @@ public class TrackTargetingBehaviour<T extends TrackEdgePoint> extends TileEntit
PartialModel partial = track.prepareTrackOverlay(level, pos, trackState, bezier, direction, ms, type);
if (partial != null)
CachedBufferer.partial(partial, trackState)
.translate(.5, 0, .5)
.scale(scale)
.translate(-.5, 0, -.5)
.light(LevelRenderer.getLightColor(level, pos))
.renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped()));

View file

@ -1,12 +1,23 @@
package com.simibubi.create.content.logistics.trains.management.edgePoint;
import com.mojang.blaze3d.vertex.PoseStack;
import java.util.List;
import java.util.function.BiConsumer;
import org.apache.commons.lang3.mutable.MutableObject;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.content.logistics.trains.GraphLocation;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.content.logistics.trains.TrackGraphHelper;
import com.simibubi.create.content.logistics.trains.TrackNode;
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.logistics.trains.track.TrackBlockOutline.BezierPointSelection;
import com.simibubi.create.content.logistics.trains.track.TrackTileEntity;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.render.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.ChatFormatting;
@ -50,27 +61,36 @@ public class TrackTargetingBlockItem extends BlockItem {
return InteractionResult.SUCCESS;
player.displayClientMessage(Lang.translate("track_target.clear"), true);
stack.setTag(null);
AllSoundEvents.CONTROLLER_CLICK.play(level, null, pos, 1, .5f);
return InteractionResult.SUCCESS;
}
if (state.getBlock() instanceof ITrackBlock track) {
if (track.getTrackAxes(level, pos, state)
.size() > 1) {
player.displayClientMessage(Lang.translate("track_target.no_junctions")
.withStyle(ChatFormatting.RED), true);
return InteractionResult.FAIL;
}
if (level.isClientSide)
return InteractionResult.SUCCESS;
CompoundTag stackTag = stack.getOrCreateTag();
Vec3 lookAngle = player.getLookAngle();
boolean front = track.getNearestTrackAxis(level, pos, state, lookAngle)
.getSecond() == AxisDirection.POSITIVE;
EdgePointType<?> type = getType(stack);
MutableObject<OverlapResult> result = new MutableObject<>(null);
withGraphLocation(level, pos, front, null, type, (overlap, location) -> result.setValue(overlap));
if (result.getValue().feedback != null) {
player.displayClientMessage(Lang.translate(result.getValue().feedback)
.withStyle(ChatFormatting.RED), true);
AllSoundEvents.DENY.play(level, null, pos, .5f, 1);
return InteractionResult.FAIL;
}
CompoundTag stackTag = stack.getOrCreateTag();
stackTag.put("SelectedPos", NbtUtils.writeBlockPos(pos));
stackTag.putBoolean("SelectedDirection", front);
stackTag.remove("Bezier");
player.displayClientMessage(Lang.translate("track_target.set"), true);
stack.setTag(stackTag);
AllSoundEvents.CONTROLLER_CLICK.play(level, null, pos, 1, 1);
return InteractionResult.SUCCESS;
}
@ -112,6 +132,10 @@ public class TrackTargetingBlockItem extends BlockItem {
return useOn;
}
protected EdgePointType<?> getType(ItemStack stack) {
return AllBlocks.TRACK_SIGNAL.isIn(stack) ? EdgePointType.SIGNAL : EdgePointType.STATION;
}
@OnlyIn(Dist.CLIENT)
public boolean useOnCurve(BezierPointSelection selection, ItemStack stack) {
Minecraft mc = Minecraft.getInstance();
@ -126,12 +150,68 @@ public class TrackTargetingBlockItem extends BlockItem {
return true;
}
public static void clientTick() {
public static enum OverlapResult {
VALID,
OCCUPIED("track_target.occupied"),
JUNCTION("track_target.no_junctions"),
NO_TRACK("track_target.invalid");
public String feedback;
private OverlapResult() {}
private OverlapResult(String feedback) {
this.feedback = feedback;
}
}
public static void render(PoseStack ms, SuperRenderTypeBuffer buffer) {
public static void withGraphLocation(Level level, BlockPos pos, boolean front,
BezierTrackPointLocation targetBezier, EdgePointType<?> type,
BiConsumer<OverlapResult, GraphLocation> callback) {
BlockState state = level.getBlockState(pos);
if (!(state.getBlock() instanceof ITrackBlock track)) {
callback.accept(OverlapResult.NO_TRACK, null);
return;
}
List<Vec3> trackAxes = track.getTrackAxes(level, pos, state);
if (targetBezier == null && trackAxes.size() > 1) {
callback.accept(OverlapResult.JUNCTION, null);
return;
}
AxisDirection targetDirection = front ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE;
GraphLocation location =
targetBezier != null ? TrackGraphHelper.getBezierGraphLocationAt(level, pos, targetDirection, targetBezier)
: TrackGraphHelper.getGraphLocationAt(level, pos, targetDirection, trackAxes.get(0));
if (location == null) {
callback.accept(OverlapResult.NO_TRACK, null);
return;
}
Couple<TrackNode> nodes = location.edge.map(location.graph::locateNode);
TrackEdge edge = location.graph.getConnection(nodes);
EdgeData edgeData = edge.getEdgeData();
double edgePosition = location.position;
for (TrackEdgePoint edgePoint : edgeData.getPoints()) {
double otherEdgePosition = edgePoint.getLocationOn(nodes.getFirst(), nodes.getSecond(), edge);
double distance = Math.abs(edgePosition - otherEdgePosition);
if (distance > .75)
continue;
if (edgePoint.canCoexistWith(type, front) && distance < .25)
continue;
callback.accept(OverlapResult.OCCUPIED, location);
return;
}
callback.accept(OverlapResult.VALID, location);
}
}

View file

@ -0,0 +1,129 @@
package com.simibubi.create.content.logistics.trains.management.edgePoint;
import com.google.common.base.Objects;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.content.logistics.trains.GraphLocation;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour.RenderedTrackOverlayType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem.OverlapResult;
import com.simibubi.create.content.logistics.trains.track.BezierTrackPointLocation;
import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline;
import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline.BezierPointSelection;
import com.simibubi.create.foundation.render.SuperRenderTypeBuffer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.HitResult.Type;
import net.minecraft.world.phys.Vec3;
public class TrackTargetingClient {
static BlockPos lastHovered;
static boolean lastDirection;
static EdgePointType<?> lastType;
static BezierTrackPointLocation lastHoveredBezierSegment;
static OverlapResult lastResult;
static GraphLocation lastLocation;
public static void clientTick() {
Minecraft mc = Minecraft.getInstance();
LocalPlayer player = mc.player;
Vec3 lookAngle = player.getLookAngle();
BlockPos hovered = null;
boolean direction = false;
EdgePointType<?> type = null;
BezierTrackPointLocation hoveredBezier = null;
ItemStack stack = player.getMainHandItem();
if (stack.getItem() instanceof TrackTargetingBlockItem ttbi)
type = ttbi.getType(stack);
boolean alreadySelected = stack.hasTag() && stack.getTag()
.contains("SelectedPos");
if (type != null) {
BezierPointSelection bezierSelection = TrackBlockOutline.result;
if (alreadySelected) {
CompoundTag tag = stack.getTag();
hovered = NbtUtils.readBlockPos(tag.getCompound("SelectedPos"));
direction = tag.getBoolean("SelectedDirection");
if (tag.contains("Bezier")) {
CompoundTag bezierNbt = tag.getCompound("Bezier");
BlockPos key = NbtUtils.readBlockPos(bezierNbt.getCompound("Key"));
hoveredBezier = new BezierTrackPointLocation(key, bezierNbt.getInt("Segment"));
}
} else if (bezierSelection != null) {
hovered = bezierSelection.te()
.getBlockPos();
hoveredBezier = bezierSelection.loc();
direction = lookAngle.dot(bezierSelection.direction()) < 0;
} else {
HitResult hitResult = mc.hitResult;
if (hitResult != null && hitResult.getType() == Type.BLOCK) {
BlockHitResult blockHitResult = (BlockHitResult) hitResult;
BlockPos pos = blockHitResult.getBlockPos();
BlockState blockState = mc.level.getBlockState(pos);
if (blockState.getBlock() instanceof ITrackBlock track) {
direction = track.getNearestTrackAxis(mc.level, pos, blockState, lookAngle)
.getSecond() == AxisDirection.POSITIVE;
hovered = pos;
}
}
}
}
if (hovered == null) {
lastHovered = null;
lastResult = null;
lastLocation = null;
lastHoveredBezierSegment = null;
return;
}
if (Objects.equal(hovered, lastHovered) && Objects.equal(hoveredBezier, lastHoveredBezierSegment)
&& direction == lastDirection && type == lastType)
return;
lastType = type;
lastHovered = hovered;
lastDirection = direction;
lastHoveredBezierSegment = hoveredBezier;
TrackTargetingBlockItem.withGraphLocation(mc.level, hovered, direction, hoveredBezier, type,
(result, location) -> {
lastResult = result;
lastLocation = location;
});
}
public static void render(PoseStack ms, SuperRenderTypeBuffer buffer) {
if (lastLocation == null || lastResult.feedback != null)
return;
Minecraft mc = Minecraft.getInstance();
BlockPos pos = lastHovered;
int light = LevelRenderer.getLightColor(mc.level, pos);
AxisDirection direction = lastDirection ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE;
RenderedTrackOverlayType type =
lastType == EdgePointType.SIGNAL ? RenderedTrackOverlayType.SIGNAL : RenderedTrackOverlayType.STATION;
TrackTargetingBehaviour.render(mc.level, pos, direction, lastHoveredBezierSegment, ms, buffer, light,
OverlayTexture.NO_OVERLAY, type, 1 + 1 / 16f);
}
}

View file

@ -61,6 +61,11 @@ public class SignalBoundary extends TrackEdgePoint {
public void invalidate(LevelAccessor level) {
blockEntities.forEach(s -> s.forEach(pos -> invalidateAt(level, pos)));
}
@Override
public boolean canCoexistWith(EdgePointType<?> otherType, boolean front) {
return otherType == getType();
}
@Override
public void tileAdded(BlockEntity tile, boolean front) {

View file

@ -53,9 +53,10 @@ public class SignalRenderer extends SafeTileEntityRenderer<SignalTileEntity> {
ms.pushPose();
ms.translate(-pos.getX(), -pos.getY(), -pos.getZ());
TrackTargetingBehaviour.render(level, targetPosition, target.getTargetDirection(), target.getTargetBezier(),
0xd0cccc, ms, buffer, light, overlay,
overlayState == OverlayState.DUAL ? RenderedTrackOverlayType.DUAL_SIGNAL : RenderedTrackOverlayType.SIGNAL);
RenderedTrackOverlayType type =
overlayState == OverlayState.DUAL ? RenderedTrackOverlayType.DUAL_SIGNAL : RenderedTrackOverlayType.SIGNAL;
TrackTargetingBehaviour.render(level, targetPosition, target.getTargetDirection(), target.getTargetBezier(), ms,
buffer, light, overlay, type, 1);
ms.popPose();
}

View file

@ -64,7 +64,7 @@ public class StationRenderer extends SafeTileEntityRenderer<StationTileEntity> {
ms.pushPose();
ms.translate(-pos.getX(), -pos.getY(), -pos.getZ());
TrackTargetingBehaviour.render(level, targetPosition, target.getTargetDirection(), target.getTargetBezier(),
0xCC993B, ms, buffer, light, overlay, RenderedTrackOverlayType.STATION);
ms, buffer, light, overlay, RenderedTrackOverlayType.STATION, 1);
ms.popPose();
return;
}

View file

@ -45,7 +45,7 @@ public class TrackBlockOutline {
public static WorldAttached<Map<BlockPos, TrackTileEntity>> TRACKS_WITH_TURNS =
new WorldAttached<>(w -> new HashMap<>());
static BezierPointSelection result;
public static BezierPointSelection result;
public static void pickCurves() {
Minecraft mc = Minecraft.getInstance();

View file

@ -36,7 +36,7 @@ import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionP
import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler;
import com.simibubi.create.content.logistics.trains.entity.CarriageCouplingRenderer;
import com.simibubi.create.content.logistics.trains.entity.TrainRelocator;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingClient;
import com.simibubi.create.content.logistics.trains.management.schedule.TrainHatArmorLayer;
import com.simibubi.create.content.logistics.trains.track.CurvedTrackInteraction;
import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline;
@ -156,7 +156,7 @@ public class ClientEvents {
ContraptionRenderDispatcher.tick(world);
BlueprintOverlayRenderer.tick();
ToolboxHandlerClient.clientTick();
TrackTargetingBlockItem.clientTick();
TrackTargetingClient.clientTick();
TrackPlacement.clientTick();
TrackRemoval.clientTick();
TrainRelocator.clientTick();
@ -209,7 +209,7 @@ public class ClientEvents {
SuperRenderTypeBuffer buffer = SuperRenderTypeBuffer.getInstance();
TrackBlockOutline.drawCurveSelection(ms, buffer);
TrackTargetingBlockItem.render(ms, buffer);
TrackTargetingClient.render(ms, buffer);
CouplingRenderer.renderAll(ms, buffer);
CarriageCouplingRenderer.renderAll(ms, buffer);
CreateClient.SCHEMATIC_HANDLER.render(ms, buffer);

View file

@ -67,6 +67,7 @@ public class BuilderTransformers {
public static <B extends StandardBogeyBlock, P> NonNullUnaryOperator<BlockBuilder<B, P>> bogey() {
return b -> b.initialProperties(SharedProperties::softMetal)
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.noOcclusion())
.blockstate((c, p) -> BlockStateGen.horizontalAxisBlock(c, p, s -> p.models()
.getExistingFile(p.modLoc("block/track/bogey/top"))))

View file

@ -665,6 +665,8 @@
"create.track_target.missing": "Right-click the targeted train track first",
"create.track_target.too_far": "Targeted track is too far from here",
"create.track_target.no_junctions": "Targeted track cannot be an intersection",
"create.track_target.occupied": "Targeted track is occupied",
"create.track_target.invalid": "Cannot target this track here",
"create.train.unnamed": "Unnamed Train",
"create.train.cannot_relocate_moving": "Cannot relocate a moving Train",