The edge case files

- Fixed train relocation not working
- Train relocation now works on selected beziers
- Fixed trains with driverless backward controls not navigating forward
- Fixed trains not properly stopped by dead ends
- Fixed tracks not separating edges meeting at 45 degrees
- Assembly screen now shows whether any drives are present on the train
- Track placement and pavement now checks and consumes inventory items in survival mode
This commit is contained in:
simibubi 2022-05-04 01:05:03 +02:00
parent 558241ca67
commit 0f2b28a2ad
42 changed files with 554 additions and 203 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
21bf73628fbf1f4e3a496f3ae1b0511193f42ddc assets/create/lang/en_us.json
b8e107ed495ab72b5ee2e5d150d10bb6f9738ef2 assets/create/lang/unfinished/de_de.json
130c39194325888e3b7d8b0fe8186cc1064558b8 assets/create/lang/unfinished/es_cl.json
fcba07a025fb54f1de46953eaa182bd422ce8b07 assets/create/lang/unfinished/es_es.json
ff2a7df3eb9555df959761654bec0df7adc14a06 assets/create/lang/unfinished/fr_fr.json
1bbaf5201cbe698bdcb946168992f1a6c59a5b5c assets/create/lang/unfinished/it_it.json
62f5f1eb810e76911ddf26af4bd14ac9ff22205e assets/create/lang/unfinished/ja_jp.json
f9788d8bdd53e4b1ddaff505eeb5ff783ac6037d assets/create/lang/unfinished/ko_kr.json
afa72a4a1bc4d3aac3ee1960713c1ee7006d0d4d assets/create/lang/unfinished/nl_nl.json
d8c932f13fde024184ab121def7d4c14195e87a0 assets/create/lang/unfinished/pl_pl.json
e65c509495f72c872a3517b40f1cba3e81b2eb4a assets/create/lang/unfinished/pt_br.json
e3757ef8da2b88d3c83e6974c2d9ef36d1548121 assets/create/lang/unfinished/pt_pt.json
1313ea94854c11e4b55fe2a2cf143c5a548ec58d assets/create/lang/unfinished/ro_ro.json
7bc26d8d8b2162615513fba5dd4f48cf787f3f45 assets/create/lang/unfinished/ru_ru.json
2e704ec8d4cfb767cf22b7c154677e374f7377c9 assets/create/lang/unfinished/zh_cn.json
c6dba4495d3a03c2ea196c59c085f90ff9452b51 assets/create/lang/unfinished/zh_tw.json
024a27fd48ffcc6a79c9743ece2e8c92e10190ab assets/create/lang/en_us.json
28f293c0e56f4b0928ed5784c6fa542cd958b08d assets/create/lang/unfinished/de_de.json
6caa5da7f0537dab9968522151a2022cbb9f017f assets/create/lang/unfinished/es_cl.json
a182e06d08d8e1b382a1c3233b5d92553ce126bd assets/create/lang/unfinished/es_es.json
0e308ef282040673debe46ec12e6e55ac9ce985e assets/create/lang/unfinished/fr_fr.json
35d0439648d6ec63cdf47aabb631afc098c32666 assets/create/lang/unfinished/it_it.json
089dd0341bd90a9ac319064a9007c25d5e5de271 assets/create/lang/unfinished/ja_jp.json
63b018284849f4afc247d42e64fe64c06e7f96b0 assets/create/lang/unfinished/ko_kr.json
e861c584c4870fa6a2449207affc91b246372862 assets/create/lang/unfinished/nl_nl.json
7ea957da93493b49328f862bab2df59afdc3fe79 assets/create/lang/unfinished/pl_pl.json
4885dd6c1e1102e24c11ad17088d7a66981c73c5 assets/create/lang/unfinished/pt_br.json
54da09cde93617abe7cdc6ccb136e94221abb612 assets/create/lang/unfinished/pt_pt.json
77c2b474774c623314f66f8c975be1075b0d3dec assets/create/lang/unfinished/ro_ro.json
573a751dba49ecb96c22d5d5374de475a4875ffa assets/create/lang/unfinished/ru_ru.json
9a14db7b7a4629a2f9030f0e9c74fd919bb108e8 assets/create/lang/unfinished/zh_cn.json
597ebfa894f0e6fe1c7c33de8504370b7a81939a 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
@ -5216,7 +5216,6 @@ d79c82bc6cf59b073b2f51f5fea9c98e81d14b68 data/create/recipes/weathered_copper_ti
452d480dd50b97fce72e0c89429cf68db534c6b2 data/create/recipes/weathered_copper_tile_slab_from_weathered_copper_tiles_stonecutting.json
ac265a674626e0e832330086fd18fe0be37fc327 data/create/recipes/weathered_copper_tile_stairs.json
5942a571f79c40524bbf408775cf91de4715f2b6 data/create/recipes/weathered_copper_tile_stairs_from_weathered_copper_tiles_stonecutting.json
0003d197585d40fda7dac6c08eac0985e4a23f5c data/create/tags/blocks/active_boiler_heaters.json
6558ef43f28c92cc558fbfc572f38496f1ed479e data/create/tags/blocks/brittle.json
330bfb3850ba3964b10b1bccbc3cbb9b012cae54 data/create/tags/blocks/fan_heaters.json
57b942386a15c874d1ca9cd6a8032c11a5599fc2 data/create/tags/blocks/fan_transparent.json

View file

@ -1414,6 +1414,8 @@
"create.track.turn_90": "Can only turn up to 90 Degrees",
"create.track.junction_start": "Cannot start connection from a Junction",
"create.track.turn_start": "Cannot start connection from a Turn",
"create.track.not_enough_tracks": "Not holding enough tracks",
"create.track.not_enough_pavement": "Not holding enough pavement blocks",
"create.station.create_train": "Create new Train",
"create.station.disassemble_train": "Disassemble Train",
@ -1434,6 +1436,7 @@
"create.train_assembly.nothing_attached": "No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "Bogey created. Click again to cycle type",
"create.track_target.set": "Targeted track selected",
"create.track_target.success": "Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1536",
"_": "Missing Localizations: 1539",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 547",
"_": "Missing Localizations: 550",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 218",
"_": "Missing Localizations: 221",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1798",
"_": "Missing Localizations: 1801",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1487",
"_": "Missing Localizations: 1490",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 213",
"_": "Missing Localizations: 216",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 213",
"_": "Missing Localizations: 216",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 2151",
"_": "Missing Localizations: 2154",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 586",
"_": "Missing Localizations: 589",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1398",
"_": "Missing Localizations: 1401",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1770",
"_": "Missing Localizations: 1773",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 214",
"_": "Missing Localizations: 217",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 591",
"_": "Missing Localizations: 594",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 213",
"_": "Missing Localizations: 216",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 605",
"_": "Missing Localizations: 608",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1415,6 +1415,8 @@
"create.track.turn_90": "UNLOCALIZED: Can only turn up to 90 Degrees",
"create.track.junction_start": "UNLOCALIZED: Cannot start connection from a Junction",
"create.track.turn_start": "UNLOCALIZED: Cannot start connection from a Turn",
"create.track.not_enough_tracks": "UNLOCALIZED: Not holding enough tracks",
"create.track.not_enough_pavement": "UNLOCALIZED: Not holding enough pavement blocks",
"create.station.create_train": "UNLOCALIZED: Create new Train",
"create.station.disassemble_train": "UNLOCALIZED: Disassemble Train",
@ -1435,6 +1437,7 @@
"create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "UNLOCALIZED: Bogey created. Click again to cycle type",
"create.track_target.set": "UNLOCALIZED: Targeted track selected",
"create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track",

View file

@ -1,8 +0,0 @@
{
"replace": false,
"values": [
"minecraft:furnace",
"minecraft:blast_furnace",
"minecraft:smoker"
]
}

View file

@ -91,10 +91,10 @@ public class SteamEngineTileEntity extends SmartTileEntity implements IHaveGoggl
@Override
@OnlyIn(Dist.CLIENT)
public AABB getRenderBoundingBox() {
return super.getRenderBoundingBox().inflate(2);
protected AABB createRenderBoundingBox() {
return super.createRenderBoundingBox().inflate(2);
}
public PoweredShaftTileEntity getShaft() {
PoweredShaftTileEntity shaft = target.get();
if (shaft == null || shaft.isRemoved() || !shaft.canBePoweredBy(worldPosition)) {

View file

@ -9,12 +9,14 @@ import java.util.Optional;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintCraftingInventory;
import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintSection;
import com.simibubi.create.content.logistics.item.filter.AttributeFilterContainer.WhitelistMode;
import com.simibubi.create.content.logistics.item.filter.FilterItem;
import com.simibubi.create.content.logistics.item.filter.ItemAttribute;
import com.simibubi.create.content.logistics.trains.track.TrackPlacement.PlacementInfo;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.element.GuiGameElement;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
@ -47,6 +49,7 @@ public class BlueprintOverlayRenderer {
static boolean active;
static boolean empty;
static boolean noOutput;
static boolean lastSneakState;
static BlueprintSection lastTargetedSection;
@ -62,6 +65,8 @@ public class BlueprintOverlayRenderer {
boolean sneak = mc.player.isShiftKeyDown();
lastTargetedSection = null;
active = false;
noOutput = false;
if (mouseOver == null)
return;
if (mouseOver.getType() != Type.ENTITY)
@ -85,6 +90,29 @@ public class BlueprintOverlayRenderer {
lastSneakState = sneak;
}
public static void displayTrackRequirements(PlacementInfo info, ItemStack pavementItem) {
if (active)
return;
active = true;
empty = false;
noOutput = true;
ingredients.clear();
int tracks = info.requiredTracks;
while (tracks > 0) {
ingredients.add(Pair.of(AllBlocks.TRACK.asStack(Math.min(64, tracks)), info.hasRequiredTracks));
tracks -= 64;
}
int pavement = info.requiredPavement;
while (pavement > 0) {
ingredients.add(Pair.of(ItemHandlerHelper.copyStackWithSize(pavementItem, Math.min(64, pavement)),
info.hasRequiredPavement));
pavement -= 64;
}
}
public static void rebuild(BlueprintSection sectionAt, boolean sneak) {
cachedRenderedFilters.clear();
ItemStackHandler items = sectionAt.getItems();
@ -212,10 +240,13 @@ public class BlueprintOverlayRenderer {
return;
Minecraft mc = Minecraft.getInstance();
int w = 30 + 21 * ingredients.size() + 21;
int w = 21 * ingredients.size();
if (!noOutput)
w += 51;
int x = (width - w) / 2;
int y = (int) (height / 3f * 2);
int y = (int) (height - 100);
for (Pair<ItemStack, Boolean> pair : ingredients) {
RenderSystem.enableBlend();
@ -226,6 +257,9 @@ public class BlueprintOverlayRenderer {
x += 21;
}
if (noOutput)
return;
x += 5;
RenderSystem.enableBlend();
AllGuiTextures.HOTSLOT_ARROW.render(poseStack, x, y + 4);

View file

@ -125,7 +125,7 @@ public class GlobalRailwayManager {
public void putGraphWithDefaultGroup(TrackGraph graph) {
SignalEdgeGroup group = new SignalEdgeGroup(graph.id);
signalEdgeGroups.put(graph.id, group);
signalEdgeGroups.put(graph.id, group.asFallback());
sync.edgeGroupCreated(graph.id, group.color);
putGraph(graph);
}

View file

@ -66,7 +66,7 @@ public interface ITrackBlock {
TrackShape shape = state.getValue(TrackBlock.SHAPE);
getTrackAxes(world, pos, state).forEach(axis -> {
addToListIfConnected(connectedTo, list, (d, b) -> axis.scale(b ? d : -d)
.add(center), b -> shape.getNormal(), null);
.add(center), b -> shape.getNormal(), axis, null);
});
return list;
@ -74,12 +74,14 @@ public interface ITrackBlock {
public static void addToListIfConnected(@Nullable TrackNodeLocation fromEnd, Collection<DiscoveredLocation> list,
BiFunction<Double, Boolean, Vec3> offsetFactory, Function<Boolean, Vec3> normalFactory,
BezierConnection viaTurn) {
Vec3 axis, BezierConnection viaTurn) {
DiscoveredLocation firstLocation = new DiscoveredLocation(offsetFactory.apply(0.5d, true)).viaTurn(viaTurn)
.withNormal(normalFactory.apply(true));
.withNormal(normalFactory.apply(true))
.withDirection(axis);
DiscoveredLocation secondLocation = new DiscoveredLocation(offsetFactory.apply(0.5d, false)).viaTurn(viaTurn)
.withNormal(normalFactory.apply(false));
.withNormal(normalFactory.apply(false))
.withDirection(axis);
boolean skipFirst = false;
boolean skipSecond = false;
@ -106,7 +108,8 @@ public interface ITrackBlock {
@OnlyIn(Dist.CLIENT)
public PartialModel prepareTrackOverlay(BlockGetter world, BlockPos pos, BlockState state,
BezierTrackPointLocation bezierPoint, AxisDirection direction, PoseStack transform, RenderedTrackOverlayType type);
BezierTrackPointLocation bezierPoint, AxisDirection direction, PoseStack transform,
RenderedTrackOverlayType type);
@OnlyIn(Dist.CLIENT)
public PartialModel prepareAssemblyOverlay(BlockGetter world, BlockPos pos, BlockState state, Direction direction,

View file

@ -28,7 +28,11 @@ public class RailwaySavedData extends SavedData {
Create.LOGGER.info("Saving Railway Information...");
nbt.put("RailGraphs", NBTHelper.writeCompoundList(railways.trackNetworks.values(), TrackGraph::write));
nbt.put("SignalBlocks",
NBTHelper.writeCompoundList(railways.signalEdgeGroups.values(), SignalEdgeGroup::write));
NBTHelper.writeCompoundList(railways.signalEdgeGroups.values(), seg -> {
if (seg.fallbackGroup && !railways.trackNetworks.containsKey(seg.id))
return null;
return seg.write();
}));
nbt.put("Trains", NBTHelper.writeCompoundList(railways.trains.values(), Train::write));
return nbt;
}

View file

@ -57,6 +57,7 @@ public class TrackNodeLocation extends Vec3i {
BezierConnection turn = null;
boolean forceNode = false;
Vec3 direction;
Vec3 normal;
public DiscoveredLocation(double p_121865_, double p_121866_, double p_121867_) {
@ -73,17 +74,22 @@ public class TrackNodeLocation extends Vec3i {
forceNode();
return this;
}
public DiscoveredLocation forceNode() {
forceNode = true;
return this;
}
public DiscoveredLocation withNormal(Vec3 normal) {
this.normal = normal;
return this;
}
public DiscoveredLocation withDirection(Vec3 direction) {
this.direction = direction == null ? null : direction.normalize();
return this;
}
public boolean connectedViaTurn() {
return turn != null;
}
@ -91,11 +97,16 @@ public class TrackNodeLocation extends Vec3i {
public BezierConnection getTurn() {
return turn;
}
public boolean shouldForceNode() {
return forceNode;
}
public boolean notInLineWith(Vec3 direction) {
return this.direction != null
&& Math.max(direction.dot(this.direction), direction.dot(this.direction.scale(-1))) < 7 / 8f;
}
}
}

View file

@ -32,7 +32,7 @@ public class TrackPropagator {
}
public static void onRailRemoved(LevelAccessor reader, BlockPos pos, BlockState state) {
if (!(state.getBlock() instanceof ITrackBlock track))
if (!(state.getBlock()instanceof ITrackBlock track))
return;
Collection<DiscoveredLocation> ends = track.getConnected(reader, pos, state, false, null);
@ -79,7 +79,7 @@ public class TrackPropagator {
}
public static TrackGraph onRailAdded(LevelAccessor reader, BlockPos pos, BlockState state) {
if (!(state.getBlock() instanceof ITrackBlock track))
if (!(state.getBlock()instanceof ITrackBlock track))
return null;
// 1. Remove all immediately reachable node locations
@ -238,6 +238,11 @@ public class TrackPropagator {
.anyMatch(DiscoveredLocation::connectedViaTurn))
return true;
Vec3 direction = location.direction;
if (direction != null && next.stream()
.anyMatch(dl -> dl.notInLineWith(direction)))
return true;
Vec3 vec = location.getLocation();
boolean centeredX = !Mth.equal(vec.x, Math.round(vec.x));
boolean centeredZ = !Mth.equal(vec.z, Math.round(vec.z));

View file

@ -60,6 +60,7 @@ public class Carriage {
this.serialisedEntity = new CompoundTag();
this.pointsInitialised = false;
this.rotationAnchors = Couple.create(null, null);
this.presentConductors = Couple.create(false, false);
updateContraptionAnchors();

View file

@ -309,7 +309,7 @@ public class CarriageSyncData {
TrackEdge newEdge = entry.getValue();
Vec3 currentDirection = edge.getDirection(false);
Vec3 newDirection = newEdge.getDirection(true);
if (currentDirection.dot(newDirection) < 3 / 4f)
if (currentDirection.dot(newDirection) < 7 / 8f)
continue;
if (!visited.add(entry.getValue()))
continue;

View file

@ -455,7 +455,7 @@ public class Navigation {
return true;
});
if (!train.doubleEnded)
if (!train.doubleEnded || !train.hasBackwardConductor())
break;
}
@ -620,7 +620,7 @@ public class Navigation {
TrackEdge newEdge = connection.getValue();
Vec3 currentDirection = edge.getDirection(false);
Vec3 newDirection = newEdge.getDirection(true);
if (currentDirection.dot(newDirection) < 3 / 4f)
if (currentDirection.dot(newDirection) < 7 / 8f)
continue;
validTargets.add(connection);
}

View file

@ -4,6 +4,7 @@ import java.util.UUID;
import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.track.BezierTrackPointLocation;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.VecHelper;
@ -22,17 +23,25 @@ public class TrainRelocationPacket extends SimplePacketBase {
BlockPos pos;
Vec3 lookAngle;
int entityId;
private boolean direction;
private BezierTrackPointLocation hoveredBezier;
public TrainRelocationPacket(FriendlyByteBuf buffer) {
trainId = buffer.readUUID();
pos = buffer.readBlockPos();
lookAngle = VecHelper.read(buffer);
entityId = buffer.readInt();
direction = buffer.readBoolean();
if (buffer.readBoolean())
hoveredBezier = new BezierTrackPointLocation(buffer.readBlockPos(), buffer.readInt());
}
public TrainRelocationPacket(UUID trainId, BlockPos pos, Vec3 lookAngle, int entityId) {
public TrainRelocationPacket(UUID trainId, BlockPos pos, BezierTrackPointLocation hoveredBezier, boolean direction,
Vec3 lookAngle, int entityId) {
this.trainId = trainId;
this.pos = pos;
this.hoveredBezier = hoveredBezier;
this.direction = direction;
this.lookAngle = lookAngle;
this.entityId = entityId;
}
@ -43,6 +52,12 @@ public class TrainRelocationPacket extends SimplePacketBase {
buffer.writeBlockPos(pos);
VecHelper.write(lookAngle, buffer);
buffer.writeInt(entityId);
buffer.writeBoolean(direction);
buffer.writeBoolean(hoveredBezier != null);
if (hoveredBezier != null) {
buffer.writeBlockPos(hoveredBezier.curveTarget());
buffer.writeInt(hoveredBezier.segment());
}
}
@Override
@ -77,7 +92,7 @@ public class TrainRelocationPacket extends SimplePacketBase {
return;
}
if (TrainRelocator.relocate(train, sender.level, pos, lookAngle, false)) {
if (TrainRelocator.relocate(train, sender.level, pos, hoveredBezier, direction, lookAngle, false)) {
sender.displayClientMessage(Lang.translate("train.relocate.success")
.withStyle(ChatFormatting.GREEN), true);
train.syncTrackGraphChanges();

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.logistics.trains.entity;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Consumer;
@ -26,6 +27,9 @@ import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.IEdge
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITurnListener;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection;
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.item.TooltipHelper;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.Couple;
@ -58,6 +62,7 @@ public class TrainRelocator {
static int relocatingEntityId;
static BlockPos lastHoveredPos;
static BezierTrackPointLocation lastHoveredBezierSegment;
static Boolean lastHoveredResult;
static List<Vec3> toVisualise;
@ -104,7 +109,9 @@ public class TrainRelocator {
HitResult hitResult = mc.hitResult;
if (!(hitResult instanceof BlockHitResult blockhit))
return null;
BlockPos blockPos = blockhit.getBlockPos();
BezierTrackPointLocation hoveredBezier = null;
if (simulate && toVisualise != null && lastHoveredResult != null) {
for (int i = 0; i < toVisualise.size() - 1; i++) {
@ -117,10 +124,19 @@ public class TrainRelocator {
}
}
BezierPointSelection bezierSelection = TrackBlockOutline.result;
if (bezierSelection != null) {
blockPos = bezierSelection.te()
.getBlockPos();
hoveredBezier = bezierSelection.loc();
}
if (simulate) {
if (lastHoveredPos != null && lastHoveredPos.equals(blockPos))
if (lastHoveredPos != null && lastHoveredPos.equals(blockPos)
&& Objects.equals(lastHoveredBezierSegment, hoveredBezier))
return lastHoveredResult;
lastHoveredPos = blockPos;
lastHoveredBezierSegment = hoveredBezier;
toVisualise = null;
}
@ -129,22 +145,27 @@ public class TrainRelocator {
return lastHoveredResult = null;
Vec3 lookAngle = mc.player.getLookAngle();
boolean result = relocate(relocating, mc.level, blockPos, lookAngle, true);
boolean direction = bezierSelection != null && lookAngle.dot(bezierSelection.direction()) < 0;
boolean result = relocate(relocating, mc.level, blockPos, hoveredBezier, direction, lookAngle, true);
if (!simulate && result)
AllPackets.channel
.sendToServer(new TrainRelocationPacket(relocatingTrain, blockPos, lookAngle, relocatingEntityId));
AllPackets.channel.sendToServer(new TrainRelocationPacket(relocatingTrain, blockPos, hoveredBezier,
direction, lookAngle, relocatingEntityId));
return lastHoveredResult = result;
}
public static boolean relocate(Train train, Level level, BlockPos pos, Vec3 lookAngle, boolean simulate) {
public static boolean relocate(Train train, Level level, BlockPos pos, BezierTrackPointLocation bezier,
boolean bezierDirection, Vec3 lookAngle, boolean simulate) {
BlockState blockState = level.getBlockState(pos);
if (!(blockState.getBlock()instanceof ITrackBlock track))
return false;
Pair<Vec3, AxisDirection> nearestTrackAxis = track.getNearestTrackAxis(level, pos, blockState, lookAngle);
GraphLocation graphLocation =
TrackGraphHelper.getGraphLocationAt(level, pos, nearestTrackAxis.getSecond(), nearestTrackAxis.getFirst());
GraphLocation graphLocation = bezier != null
? TrackGraphHelper.getBezierGraphLocationAt(level, pos,
bezierDirection ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE, bezier)
: TrackGraphHelper.getGraphLocationAt(level, pos, nearestTrackAxis.getSecond(),
nearestTrackAxis.getFirst());
if (graphLocation == null)
return false;

View file

@ -29,6 +29,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
public class TravellingPoint {
@ -179,7 +180,7 @@ public class TravellingPoint {
IEdgePointListener signalListener, ITurnListener turnListener) {
blocked = false;
double edgeLength = edge.getLength();
if (distance == 0)
if (Mth.equal(distance, 0))
return 0;
double prevPos = position;
@ -223,7 +224,7 @@ public class TravellingPoint {
TrackEdge newEdge = entry.getValue();
Vec3 currentDirection = edge.getDirection(false);
Vec3 newDirection = newEdge.getDirection(true);
if (currentDirection.dot(newDirection) < 3 / 4f)
if (currentDirection.dot(newDirection) < 7 / 8f)
continue;
validTargets.add(entry);
@ -276,14 +277,14 @@ public class TravellingPoint {
.get(node1);
Vec3 currentDirection = edge.getDirection(true);
Vec3 newDirection = newEdge.getDirection(false);
if (currentDirection.dot(newDirection) < 3 / 4f)
if (currentDirection.dot(newDirection) < 7 / 8f)
continue;
validTargets.add(entry);
}
if (validTargets.isEmpty()) {
traveled += position;
traveled -= position;
position = 0;
blocked = true;
break;

View file

@ -29,6 +29,8 @@ public class SignalEdgeGroup {
public Map<UUID, UUID> intersecting;
public Set<SignalEdgeGroup> intersectingResolved;
public Set<UUID> adjacent;
public boolean fallbackGroup;
public SignalEdgeGroup(UUID id) {
this.id = id;
@ -38,6 +40,11 @@ public class SignalEdgeGroup {
intersectingResolved = new HashSet<>();
color = EdgeGroupColor.getDefault();
}
public SignalEdgeGroup asFallback() {
fallbackGroup = true;
return this;
}
public boolean isOccupiedUnless(Train train) {
if (intersectingResolved.isEmpty())
@ -129,6 +136,7 @@ public class SignalEdgeGroup {
group.color = NBTHelper.readEnum(tag, "Color", EdgeGroupColor.class);
NBTHelper.iterateCompoundList(tag.getList("Connected", Tag.TAG_COMPOUND),
nbt -> group.intersecting.put(nbt.getUUID("Key"), nbt.getUUID("Value")));
group.fallbackGroup = tag.getBoolean("Fallback");
return group;
}
@ -142,6 +150,7 @@ public class SignalEdgeGroup {
nbt.putUUID("Value", e.getValue());
return nbt;
}));
tag.putBoolean("Fallback", fallbackGroup);
return tag;
}

View file

@ -18,7 +18,6 @@ import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.networking.AllPackets;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation;
@ -103,6 +102,10 @@ public class AssemblyScreen extends AbstractStationScreen {
tickTrainDisplay();
Train train = displayedTrain.get();
toggleAssemblyButton.active = te.bogeyCount > 0 || train != null;
if (train != null)
for (Carriage carriage : train.carriages)
carriage.updateConductors();
}
private void tickTrainDisplay() {
@ -151,15 +154,21 @@ public class AssemblyScreen extends AbstractStationScreen {
TrainIconType icon = train.icon;
int offset = 0;
int position = background.width / 2 - getTrainIconWidth(train) / 2;
boolean frontConductor = false;
boolean backConductor = false;
List<Carriage> carriages = train.carriages;
for (int i = carriages.size() - 1; i > 0; i--) {
if (i == carriages.size() - 1 && train.doubleEnded) {
offset += icon.render(TrainIconType.FLIPPED_ENGINE, ms, x + offset + position, y + 20) + 1;
continue;
}
for (int i = carriages.size() - 1; i >= 0; i--) {
Carriage carriage = carriages.get(i);
offset += icon.render(carriage.bogeySpacing, ms, x + offset + position, y + 20) + 1;
frontConductor |= carriage.presentConductors.getFirst();
backConductor |= carriage.presentConductors.getSecond();
if (i == 0)
continue;
if (i == carriages.size() - 1 && train.doubleEnded)
offset += icon.render(TrainIconType.FLIPPED_ENGINE, ms, x + offset + position, y + 20) + 1;
else
offset += icon.render(carriage.bogeySpacing, ms, x + offset + position, y + 20) + 1;
}
offset += icon.render(TrainIconType.ENGINE, ms, x + offset + position, y + 20);
@ -171,15 +180,18 @@ public class AssemblyScreen extends AbstractStationScreen {
TextComponent text = new TextComponent("Assembly Successful");
font.drawShadow(ms, text, x + 97 - font.width(text) / 2, y + 47, 0xC6C6C6);
font.drawShadow(ms,
new TextComponent("-> " + train.carriages.size() + " Carriages, " + train.getTotalLength() + "m"),
new TextComponent("-> " + train.carriages.size() + " Carriage(s), " + train.getTotalLength() + "m"),
x + 30, y + 67, 0xC6C6C6);
font.drawShadow(ms, new TextComponent("-> Fuel Type: NYI"), x + 30, y + 77, 0xC6C6C6);
font.drawShadow(ms, new TextComponent("-> " + (train.doubleEnded ? "Dual Powered" : "Single Powered")),
x + 30, y + 92, 0xC6C6C6);
font.drawShadow(ms,
new TextComponent((train.doubleEnded ? "(Navigates both ways)" : "(Navigates forward only)")), x + 30,
y + 102, 0xACC4BC);
new TextComponent("-> " + (frontConductor || backConductor ? "Drivers present" : "No drivers found")),
x + 30, y + 82, 0xC6C6C6);
font.drawShadow(ms, new TextComponent("-> " + (train.doubleEnded ? "Dual Controls" : "Single Controls")),
x + 30, y + 97, 0xC6C6C6);
font.drawShadow(ms,
new TextComponent((train.doubleEnded ? "(Navigates both ways)" : "(Navigates forward only)")), x + 35,
y + 107, 0xACC4BC);
return;
}
@ -205,10 +217,12 @@ public class AssemblyScreen extends AbstractStationScreen {
new TextComponent(bogeyCount == 0 ? "No Bogeys" : bogeyCount + (bogeyCount == 1 ? " Bogey" : " Bogeys"));
font.draw(ms, text, x + 97 - font.width(text) / 2, y + 47, 0x7A7A7A);
Component component =
new TextComponent("Right-click on highlighted Tracks to create bogeys. Use Wrench to cycle type."
+ "\n\nAttach structures to one or between two bogeys to form carriages.");
font.drawWordWrap(component, x + 30, y + 67, 134, 0x7A7A7A);
font.drawWordWrap(new TextComponent("Right-click on highlighted Tracks to create bogeys."), x + 28, y + 67, 134,
0x7A7A7A);
font.drawWordWrap(new TextComponent("Remove bogeys by breaking the block on top."), x + 28, y + 90, 134,
0x7A7A7A);
font.drawWordWrap(new TextComponent("Build carriages attached to one or two bogeys each."), x + 28, y + 113,
138, 0x7A7A7A);
}
@Override
@ -221,7 +235,7 @@ public class AssemblyScreen extends AbstractStationScreen {
AllPackets.channel.sendToServer(new TrainEditPacket(train.id, "", !assemblyCompleted, iconId));
}
}
@Override
protected PartialModel getFlag(float partialTicks) {
return AllBlockPartials.STATION_ASSEMBLE;

View file

@ -50,9 +50,11 @@ import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
@ -235,20 +237,39 @@ public class StationTileEntity extends SmartTileEntity {
}
}
public void trackClicked(Player player, ITrackBlock track, BlockState state, BlockPos pos) {
public boolean trackClicked(Player player, ITrackBlock track, BlockState state, BlockPos pos) {
refreshAssemblyInfo();
BoundingBox bb = assemblyAreas.get(level)
.get(worldPosition);
if (bb == null || !bb.isInside(pos))
return;
return false;
BlockPos up = new BlockPos(track.getUpNormal(level, pos, state));
int bogeyOffset = pos.distManhattan(edgePoint.getGlobalPosition()) - 1;
if (!isValidBogeyOffset(bogeyOffset))
return;
if (!isValidBogeyOffset(bogeyOffset)) {
for (int i = -1; i <= 1; i++) {
BlockPos bogeyPos = pos.relative(assemblyDirection, i)
.offset(up);
BlockState blockState = level.getBlockState(bogeyPos);
if (blockState.getBlock()instanceof IBogeyBlock bogey) {
level.setBlock(bogeyPos, bogey.getRotatedBlockState(blockState, Direction.DOWN), 3);
bogey.playRotateSound(level, bogeyPos);
return true;
}
}
return false;
}
Vec3 upNormal = track.getUpNormal(level, pos, state);
BlockState bogeyAnchor = track.getBogeyAnchor(level, pos, state);
level.setBlock(pos.offset(new BlockPos(upNormal)), bogeyAnchor, 3);
level.setBlock(pos.offset(up), bogeyAnchor, 3);
player.displayClientMessage(Lang.translate("train_assembly.bogey_created"), true);
SoundType soundtype = bogeyAnchor.getBlock()
.getSoundType(state, level, pos, player);
level.playSound(null, pos, soundtype.getPlaceSound(), SoundSource.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F,
soundtype.getPitch() * 0.8F);
return true;
}
public boolean isAssembling() {

View file

@ -62,7 +62,7 @@ public class StandardBogeyBlock extends Block implements IBogeyBlock, ITE<Standa
@Override
public double getWheelPointSpacing() {
return large ? .75f : 2;
return 2;
}
@Override

View file

@ -21,8 +21,6 @@ import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.Create;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.content.curiosities.girder.GirderBlock;
import com.simibubi.create.content.logistics.trains.BezierConnection;
@ -49,14 +47,12 @@ 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;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
@ -187,7 +183,7 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
ITrackBlock.addToListIfConnected(connectedTo, list,
(d, b) -> axis.scale(b ? 0 : fromCenter ? -d : d)
.add(center),
b -> shape.getNormal(), null);
b -> shape.getNormal(), axis, null);
} else
list = ITrackBlock.super.getConnected(world, pos, state, linear, connectedTo);
@ -202,7 +198,8 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
Map<BlockPos, BezierConnection> connections = trackTE.getConnections();
connections.forEach((connectedPos, bc) -> ITrackBlock.addToListIfConnected(connectedTo, list,
(d, b) -> d == 1 ? Vec3.atLowerCornerOf(bc.tePositions.get(b)) : bc.starts.get(b), bc.normals::get, bc));
(d, b) -> d == 1 ? Vec3.atLowerCornerOf(bc.tePositions.get(b)) : bc.starts.get(b), bc.normals::get, null,
bc));
return list;
}
@ -227,29 +224,17 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand,
BlockHitResult hit) {
ItemStack itemInHand = player.getItemInHand(hand);
// debug remove all graphs
if (Blocks.SPONGE.asItem() == itemInHand.getItem()) {
Create.RAILWAYS.trackNetworks.clear();
CreateClient.RAILWAYS.trackNetworks.clear();
Create.RAILWAYS.signalEdgeGroups.clear();
CreateClient.RAILWAYS.signalEdgeGroups.clear();
return InteractionResult.SUCCESS;
}
if (itemInHand.isEmpty()) {
if (world.isClientSide)
return InteractionResult.SUCCESS;
for (Entry<BlockPos, BoundingBox> entry : StationTileEntity.assemblyAreas.get(world)
.entrySet()) {
if (!entry.getValue()
.isInside(pos))
continue;
if (world.getBlockEntity(entry.getKey()) instanceof StationTileEntity station)
station.trackClicked(player, this, state, pos);
}
if (world.isClientSide)
return InteractionResult.SUCCESS;
for (Entry<BlockPos, BoundingBox> entry : StationTileEntity.assemblyAreas.get(world)
.entrySet()) {
if (!entry.getValue()
.isInside(pos))
continue;
if (world.getBlockEntity(entry.getKey())instanceof StationTileEntity station)
if (station.trackClicked(player, this, state, pos))
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
@ -263,7 +248,7 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
BlockPos girderPos = pPos.below()
.offset(vec3.z * side, 0, vec3.x * side);
BlockState girderState = pLevel.getBlockState(girderPos);
if (girderState.getBlock() instanceof GirderBlock girderBlock
if (girderState.getBlock()instanceof GirderBlock girderBlock
&& !blockTicks.hasScheduledTick(girderPos, girderBlock))
pLevel.scheduleTick(girderPos, girderBlock, 1);
}
@ -362,16 +347,16 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
@Override
public InteractionResult onWrenched(BlockState state, UseOnContext context) {
if (context.getLevel().isClientSide)
TrackRemoval.wrenched(context.getClickedPos());
// if (context.getLevel().isClientSide)
// TrackRemoval.wrenched(context.getClickedPos());
return InteractionResult.SUCCESS;
}
@Override
public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) {
if (context.getLevel().isClientSide)
TrackRemoval.sneakWrenched(context.getClickedPos());
return InteractionResult.SUCCESS;
// if (context.getLevel().isClientSide)
// TrackRemoval.sneakWrenched(context.getClickedPos());
return IWrenchable.super.onSneakWrenched(state, context);
}
@Override
@ -443,7 +428,7 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
Vec3 normal = null;
Vec3 offset = null;
if (bezierPoint != null && world.getBlockEntity(pos) instanceof TrackTileEntity trackTE) {
if (bezierPoint != null && world.getBlockEntity(pos)instanceof TrackTileEntity trackTE) {
BezierConnection bc = trackTE.connections.get(bezierPoint.curveTarget());
if (bc != null) {
double length = Mth.floor(bc.getLength() * 2);

View file

@ -1,10 +1,10 @@
package com.simibubi.create.content.logistics.trains.track;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.content.logistics.trains.track.TrackPlacement.PlacementInfo;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.VecHelper;
@ -15,6 +15,8 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
@ -25,7 +27,7 @@ import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
@ -51,11 +53,13 @@ public class TrackBlockItem extends BlockItem {
if (player == null)
return super.useOn(pContext);
if (pContext.getHand() == InteractionHand.OFF_HAND)
return super.useOn(pContext);
Vec3 lookAngle = player.getLookAngle();
if (!isFoil(stack)) {
if (state.getBlock() instanceof TrackBlock track && track.getTrackAxes(level, pos, state)
if (state.getBlock()instanceof TrackBlock track && track.getTrackAxes(level, pos, state)
.size() > 1) {
if (!level.isClientSide)
player.displayClientMessage(Lang.translate("track.junction_start")
@ -63,15 +67,18 @@ public class TrackBlockItem extends BlockItem {
return InteractionResult.SUCCESS;
}
if (select(level, pos, lookAngle, stack))
if (select(level, pos, lookAngle, stack)) {
level.playSound(null, pos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, 0.75f, 1);
return InteractionResult.SUCCESS;
}
return super.useOn(pContext);
} else if (player.isSteppingCarefully()) {
if (!level.isClientSide) {
player.displayClientMessage(Lang.translate("track.selection_cleared"), true);
stack.setTag(null);
}
} else
level.playSound(player, pos, SoundEvents.ITEM_FRAME_REMOVE_ITEM, SoundSource.BLOCKS, 0.75f, 1);
return InteractionResult.SUCCESS;
}
@ -91,36 +98,29 @@ public class TrackBlockItem extends BlockItem {
ItemStack offhandItem = player.getOffhandItem();
boolean hasGirder = AllBlocks.METAL_GIRDER.isIn(offhandItem);
PlacementInfo info = TrackPlacement.tryConnect(level, pos, state, lookAngle, stack, hasGirder, extend);
PlacementInfo info = TrackPlacement.tryConnect(level, player, pos, state, stack, hasGirder, extend);
if (info.message != null && !level.isClientSide)
player.displayClientMessage(Lang.translate(info.message), true);
if (!info.valid)
if (!info.valid) {
AllSoundEvents.DENY.playFrom(player, 1, 1);
return InteractionResult.FAIL;
}
stack.setTag(null);
if (level.isClientSide)
if (level.isClientSide)
return InteractionResult.SUCCESS;
if (offhandItem.getItem() instanceof BlockItem blockItem) {
Block block = blockItem.getBlock();
if (block == null)
return InteractionResult.SUCCESS;
if (block instanceof EntityBlock)
return InteractionResult.SUCCESS;
for (boolean first : Iterate.trueAndFalse) {
int extent = (first ? info.end1Extent : info.end2Extent) + (info.curve != null ? 1 : 0);
Vec3 axis = first ? info.axis1 : info.axis2;
BlockPos pavePos = first ? info.pos1 : info.pos2;
TrackPaver.paveStraight(level, pavePos.below(), axis, extent, block);
}
if (info.curve != null)
TrackPaver.paveCurve(level, info.curve, block);
stack = player.getMainHandItem();
if (AllBlocks.TRACK.isIn(stack)) {
stack.setTag(null);
player.setItemInHand(pContext.getHand(), stack);
}
SoundType soundtype = state.getSoundType();
if (soundtype != null)
level.playSound(null, pos, soundtype.getPlaceSound(), SoundSource.BLOCKS,
(soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
return InteractionResult.SUCCESS;
}

View file

@ -27,12 +27,17 @@ import net.minecraft.world.phys.Vec3;
public class TrackPaver {
public static void paveStraight(Level level, BlockPos startPos, Vec3 direction, int extent, Block block) {
public static int paveStraight(Level level, BlockPos startPos, Vec3 direction, int extent, Block block,
boolean simulate, Set<BlockPos> visited) {
int itemsNeeded = 0;
BlockState defaultBlockState = block.defaultBlockState();
if (defaultBlockState.hasProperty(SlabBlock.TYPE))
defaultBlockState = defaultBlockState.setValue(SlabBlock.TYPE, SlabType.DOUBLE);
boolean slabLike = defaultBlockState.hasProperty(SlabBlock.TYPE);
boolean wallLike = isWallLike(defaultBlockState);
if (slabLike)
defaultBlockState = defaultBlockState.setValue(SlabBlock.TYPE, SlabType.DOUBLE);
if (defaultBlockState.getBlock() instanceof GirderBlock)
for (Direction d : Iterate.horizontalDirections)
if (Vec3.atLowerCornerOf(d.getNormal())
@ -66,28 +71,27 @@ public class TrackPaver {
}
final BlockState state = defaultBlockState;
toPlaceOn.forEach(p -> placeBlockIfFree(level, p, state));
}
private static boolean isWallLike(BlockState defaultBlockState) {
return defaultBlockState.getBlock() instanceof WallBlock || AllBlocks.METAL_GIRDER.has(defaultBlockState);
}
private static void placeBlockIfFree(Level level, BlockPos pos, BlockState state) {
BlockState stateAtPos = level.getBlockState(pos);
if (stateAtPos.getBlock() != state.getBlock() && stateAtPos.getMaterial()
.isReplaceable()) {
level.setBlock(pos, state, 3);
for (BlockPos p : toPlaceOn) {
if (!visited.add(p))
continue;
if (placeBlockIfFree(level, p, state, simulate))
itemsNeeded += slabLike ? 2 : 1;
}
visited.addAll(toPlaceOn);
return itemsNeeded;
}
public static void paveCurve(Level level, BezierConnection bc, Block block) {
public static int paveCurve(Level level, BezierConnection bc, Block block, boolean simulate,
Set<BlockPos> visited) {
int itemsNeeded = 0;
BlockState defaultBlockState = block.defaultBlockState();
boolean slab = defaultBlockState.hasProperty(SlabBlock.TYPE);
if (slab)
boolean slabLike = defaultBlockState.hasProperty(SlabBlock.TYPE);
if (slabLike)
defaultBlockState = defaultBlockState.setValue(SlabBlock.TYPE, SlabType.DOUBLE);
if (isWallLike(defaultBlockState))
return;
return 0;
Map<Pair<Integer, Integer>, Double> yLevels = new HashMap<>();
BlockPos tePosition = bc.tePositions.getFirst();
@ -141,7 +145,7 @@ public class TrackPaver {
for (Entry<Pair<Integer, Integer>, Double> entry : yLevels.entrySet()) {
double yValue = entry.getValue();
int floor = Mth.floor(yValue);
boolean placeSlab = slab && yValue - floor >= .5;
boolean placeSlab = slabLike && yValue - floor >= .5;
BlockPos targetPos = new BlockPos(entry.getKey()
.getFirst(), floor,
entry.getKey()
@ -150,10 +154,35 @@ public class TrackPaver {
.above(placeSlab ? 1 : 0);
BlockState stateToPlace =
placeSlab ? defaultBlockState.setValue(SlabBlock.TYPE, SlabType.BOTTOM) : defaultBlockState;
placeBlockIfFree(level, targetPos, stateToPlace);
if (placeSlab)
placeBlockIfFree(level, targetPos.below(), stateToPlace.setValue(SlabBlock.TYPE, SlabType.TOP));
if (!visited.add(targetPos))
continue;
if (placeBlockIfFree(level, targetPos, stateToPlace, simulate))
itemsNeeded += !placeSlab ? 2 : 1;
if (placeSlab) {
if (!visited.add(targetPos.below()))
continue;
BlockState topSlab = stateToPlace.setValue(SlabBlock.TYPE, SlabType.TOP);
if (placeBlockIfFree(level, targetPos.below(), topSlab, simulate))
itemsNeeded++;
}
}
return itemsNeeded;
}
private static boolean isWallLike(BlockState defaultBlockState) {
return defaultBlockState.getBlock() instanceof WallBlock || AllBlocks.METAL_GIRDER.has(defaultBlockState);
}
private static boolean placeBlockIfFree(Level level, BlockPos pos, BlockState state, boolean simulate) {
BlockState stateAtPos = level.getBlockState(pos);
if (stateAtPos.getBlock() != state.getBlock() && stateAtPos.getMaterial()
.isReplaceable()) {
if (!simulate)
level.setBlock(pos, state, 3);
return true;
}
return false;
}
}

View file

@ -2,12 +2,15 @@ package com.simibubi.create.content.logistics.trains.track;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.jozufozu.flywheel.util.Color;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllSpecialTextures;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.curiosities.tools.BlueprintOverlayRenderer;
import com.simibubi.create.content.logistics.trains.BezierConnection;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.foundation.utility.AngleHelper;
@ -31,9 +34,14 @@ import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
@ -42,16 +50,23 @@ import net.minecraft.world.phys.HitResult.Type;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.items.ItemHandlerHelper;
public class TrackPlacement {
static class PlacementInfo {
public static class PlacementInfo {
BezierConnection curve = null;
boolean valid = false;
int end1Extent = 0;
int end2Extent = 0;
String message = null;
public int requiredTracks = 0;
public boolean hasRequiredTracks = false;
public int requiredPavement = 0;
public boolean hasRequiredPavement = false;
// for visualisation
Vec3 end1;
Vec3 end2;
@ -73,14 +88,16 @@ public class TrackPlacement {
}
}
static PlacementInfo cached;
public static PlacementInfo cached;
static BlockPos hoveringPos;
static boolean hoveringMaxed;
static int hoveringAngle;
static ItemStack lastItem;
public static PlacementInfo tryConnect(Level level, BlockPos pos2, BlockState state2, Vec3 lookVec, ItemStack stack,
boolean girder, boolean maximiseTurn) {
public static PlacementInfo tryConnect(Level level, Player player, BlockPos pos2, BlockState state2,
ItemStack stack, boolean girder, boolean maximiseTurn) {
Vec3 lookVec = player.getLookAngle();
int lookAngle = (int) (22.5 + AngleHelper.deg(Mth.atan2(lookVec.z, lookVec.x)) % 360) / 8;
if (level.isClientSide && cached != null && pos2.equals(hoveringPos) && stack.equals(lastItem)
@ -329,18 +346,131 @@ public class TrackPlacement {
info.valid = true;
info.pos1 = pos1;
info.pos2 = pos2;
info.axis1 = axis1;
info.axis2 = axis2;
placeTracks(level, info, state1, state2, targetPos1, targetPos2, true);
ItemStack offhandItem = player.getOffhandItem()
.copy();
boolean shouldPave = offhandItem.getItem() instanceof BlockItem;
if (shouldPave) {
BlockItem paveItem = (BlockItem) offhandItem.getItem();
paveTracks(level, info, paveItem, true);
info.hasRequiredPavement = true;
}
info.hasRequiredTracks = true;
if (!player.isCreative()) {
for (boolean simulate : Iterate.trueAndFalse) {
if (level.isClientSide && !simulate)
break;
int tracks = info.requiredTracks;
int pavement = info.requiredPavement;
int foundTracks = 0;
int foundPavement = 0;
Inventory inv = player.getInventory();
int size = inv.items.size();
for (int j = 0; j <= size + 1; j++) {
int i = j;
boolean offhand = j == size + 1;
if (j == size)
i = inv.selected;
else if (offhand)
i = 0;
else if (j == inv.selected)
continue;
ItemStack stackInSlot = (offhand ? inv.offhand : inv.items).get(i);
boolean isTrack = AllBlocks.TRACK.isIn(stackInSlot);
if (!isTrack && (!shouldPave || offhandItem.getItem() != stackInSlot.getItem()))
continue;
if (isTrack ? foundTracks >= tracks : foundPavement >= pavement)
continue;
int count = stackInSlot.getCount();
if (!simulate) {
int remainingItems =
count - Math.min(isTrack ? tracks - foundTracks : pavement - foundPavement, count);
if (i == inv.selected)
stackInSlot.setTag(null);
ItemStack newItem = ItemHandlerHelper.copyStackWithSize(stackInSlot, remainingItems);
if (offhand)
player.setItemInHand(InteractionHand.OFF_HAND, newItem);
else
inv.setItem(i, newItem);
}
if (isTrack)
foundTracks += count;
else
foundPavement += count;
}
if (simulate && foundTracks < tracks) {
info.valid = false;
info.tooJumbly();
info.hasRequiredTracks = false;
return info.withMessage("not_enough_tracks");
}
if (simulate && foundPavement < pavement) {
info.valid = false;
info.tooJumbly();
info.hasRequiredPavement = false;
return info.withMessage("not_enough_pavement");
}
}
}
if (level.isClientSide())
return info;
if (shouldPave) {
BlockItem paveItem = (BlockItem) offhandItem.getItem();
paveTracks(level, info, paveItem, false);
}
return placeTracks(level, info, state1, state2, targetPos1, targetPos2, false);
}
private static void paveTracks(Level level, PlacementInfo info, BlockItem blockItem, boolean simulate) {
Block block = blockItem.getBlock();
info.requiredPavement = 0;
if (block == null || block instanceof EntityBlock)
return;
Set<BlockPos> visited = new HashSet<>();
for (boolean first : Iterate.trueAndFalse) {
int extent = (first ? info.end1Extent : info.end2Extent) + (info.curve != null ? 1 : 0);
Vec3 axis = first ? info.axis1 : info.axis2;
BlockPos pavePos = first ? info.pos1 : info.pos2;
info.requiredPavement +=
TrackPaver.paveStraight(level, pavePos.below(), axis, extent, block, simulate, visited);
}
if (info.curve != null)
info.requiredPavement += TrackPaver.paveCurve(level, info.curve, block, simulate, visited);
}
private static PlacementInfo placeTracks(Level level, PlacementInfo info, BlockState state1, BlockState state2,
BlockPos targetPos1, BlockPos targetPos2, boolean simulate) {
info.requiredTracks = 0;
for (boolean first : Iterate.trueAndFalse) {
int extent = first ? info.end1Extent : info.end2Extent;
Vec3 axis = first ? axis1 : axis2;
BlockPos pos = first ? pos1 : pos2;
Vec3 axis = first ? info.axis1 : info.axis2;
BlockPos pos = first ? info.pos1 : info.pos2;
BlockState state = first ? state1 : state2;
if (state.hasProperty(TrackBlock.HAS_TURN))
if (state.hasProperty(TrackBlock.HAS_TURN) && !simulate)
state = state.setValue(TrackBlock.HAS_TURN, false);
for (int i = 0; i < extent; i++) {
for (int i = 0; i < (info.curve != null ? extent + 1 : extent); i++) {
Vec3 offset = axis.scale(i);
BlockPos offsetPos = pos.offset(offset.x, offset.y, offset.z);
BlockState stateAtPos = level.getBlockState(offsetPos);
@ -348,7 +478,12 @@ public class TrackPlacement {
boolean canPlace = stateAtPos.getMaterial()
.isReplaceable();
if (stateAtPos.getBlock() instanceof ITrackBlock trackAtPos) {
if (canPlace)
info.requiredTracks++;
if (simulate)
continue;
if (stateAtPos.getBlock()instanceof ITrackBlock trackAtPos) {
toPlace = trackAtPos.overlay(level, offsetPos, stateAtPos, toPlace);
canPlace = true;
}
@ -358,24 +493,40 @@ public class TrackPlacement {
}
}
info.pos1 = pos1;
info.pos2 = pos2;
info.axis1 = axis1;
info.axis2 = axis2;
if (info.curve == null)
return info;
level.setBlock(targetPos1, state1.setValue(TrackBlock.HAS_TURN, true), 3);
level.setBlock(targetPos2, state2.setValue(TrackBlock.HAS_TURN, true), 3);
if (!simulate) {
BlockState stateAtPos = level.getBlockState(targetPos1);
level.setBlock(targetPos1,
(stateAtPos.getBlock() == state1.getBlock() ? stateAtPos : state1).setValue(TrackBlock.HAS_TURN, true),
3);
stateAtPos = level.getBlockState(targetPos2);
level.setBlock(targetPos2,
(stateAtPos.getBlock() == state2.getBlock() ? stateAtPos : state2).setValue(TrackBlock.HAS_TURN, true),
3);
}
BlockEntity te1 = level.getBlockEntity(targetPos1);
BlockEntity te2 = level.getBlockEntity(targetPos2);
int requiredTracksForTurn = (info.curve.getSegmentCount() + 1) / 2;
if (!(te1 instanceof TrackTileEntity) || !(te2 instanceof TrackTileEntity))
if (!(te1 instanceof TrackTileEntity) || !(te2 instanceof TrackTileEntity)) {
info.requiredTracks += requiredTracksForTurn;
return info;
}
TrackTileEntity tte1 = (TrackTileEntity) te1;
TrackTileEntity tte2 = (TrackTileEntity) te2;
if (!tte1.getConnections()
.containsKey(tte2.getBlockPos()))
info.requiredTracks += requiredTracksForTurn;
if (simulate)
return info;
tte1.addConnection(info.curve);
tte2.addConnection(info.curve.secondary());
return info;
@ -427,7 +578,9 @@ public class TrackPlacement {
return;
boolean maxTurns = Minecraft.getInstance().options.keySprint.isDown();
PlacementInfo info = tryConnect(level, pos, hitState, player.getLookAngle(), stack, false, maxTurns);
PlacementInfo info = tryConnect(level, player, pos, hitState, stack, false, maxTurns);
if (!player.isCreative() && (info.valid || !info.hasRequiredTracks || !info.hasRequiredPavement))
BlueprintOverlayRenderer.displayTrackRequirements(info, player.getOffhandItem());
if (info.valid)
player.displayClientMessage(Lang.translate("track.valid_connection")
@ -445,8 +598,7 @@ public class TrackPlacement {
for (int xOffset = -2; xOffset <= 2; xOffset++) {
for (int zOffset = -2; zOffset <= 2; zOffset++) {
BlockPos offset = pos.offset(xOffset, 0, zOffset);
PlacementInfo adjInfo =
tryConnect(level, offset, hitState, player.getLookAngle(), stack, false, maxTurns);
PlacementInfo adjInfo = tryConnect(level, player, offset, hitState, stack, false, maxTurns);
hints.get(adjInfo.valid)
.add(offset.below());
}

View file

@ -71,7 +71,6 @@ public class InputEvents {
if (event.getKeyMapping() == mc.options.keyUse) {
if (CreateClient.GLUE_HANDLER.onMouseInput())
event.setCanceled(true);
return;
}
if (event.getKeyMapping() == mc.options.keyPickItem) {

View file

@ -43,7 +43,12 @@ public class NBTHelper {
public static <T> ListTag writeCompoundList(Iterable<T> list, Function<T, CompoundTag> serializer) {
ListTag listNBT = new ListTag();
list.forEach(t -> listNBT.add(serializer.apply(t)));
list.forEach(t -> {
CompoundTag apply = serializer.apply(t);
if (apply == null)
return;
listNBT.add(apply);
});
return listNBT;
}

View file

@ -638,6 +638,8 @@
"create.track.turn_90": "Can only turn up to 90 Degrees",
"create.track.junction_start": "Cannot start connection from a Junction",
"create.track.turn_start": "Cannot start connection from a Turn",
"create.track.not_enough_tracks": "Not holding enough tracks",
"create.track.not_enough_pavement": "Not holding enough pavement blocks",
"create.station.create_train": "Create new Train",
"create.station.disassemble_train": "Disassemble Train",
@ -658,6 +660,7 @@
"create.train_assembly.nothing_attached": "No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "A mounted controls block is facing sideways",
"create.train_assembly.bogey_created": "Bogey created. Click again to cycle type",
"create.track_target.set": "Targeted track selected",
"create.track_target.success": "Successfully bound to targeted track",