Choowo what's this?
- It trains
This commit is contained in:
parent
2a4cfef7a8
commit
576d00d3a0
219 changed files with 34359 additions and 98 deletions
|
@ -49,6 +49,7 @@ b59324f051f21d8ce1a48a08f4721a61a3c414d6 assets/create/blockstates/chute.json
|
|||
e5e3757e99c139d67b2a70288466d8a74d818841 assets/create/blockstates/cogwheel.json
|
||||
36f54136a7756c97f71bc6b47ef4e8e575e72879 assets/create/blockstates/content_observer.json
|
||||
7d11142092c89ccba3e74e0a3bdd0ccb446d63b5 assets/create/blockstates/controller_rail.json
|
||||
f292ffa3bc036947b655c0a0ce26a91615c3d40b assets/create/blockstates/controls.json
|
||||
961b615124ea9a5a5735e8a79f81a702de7da2cf assets/create/blockstates/copper_backtank.json
|
||||
cabf6b8c59eb0e3d56a0a5a856ca058bb3200882 assets/create/blockstates/copper_casing.json
|
||||
b3d0dee8f6e14fa6c637e98cc1c6f1ea55b5f0d5 assets/create/blockstates/copper_shingle_slab.json
|
||||
|
@ -235,6 +236,7 @@ be3bef7e091d8b50bfc1c6b7275946d1f636aefd assets/create/blockstates/horizontal_fr
|
|||
10ef455fd61ed1ca831d27bf2b533d05dec9c67d assets/create/blockstates/item_vault.json
|
||||
5d851c90d23de5087ce546d4bbe509e112b84c49 assets/create/blockstates/jungle_window.json
|
||||
b15bea757ef981e0ca60f740ca234ee2014eb7b7 assets/create/blockstates/jungle_window_pane.json
|
||||
f8982f0241f33b2cd55d6261ab6ee38cb83b6d8d assets/create/blockstates/large_bogey.json
|
||||
f651091db216b009b3379b2f48d56d03481c8675 assets/create/blockstates/large_cogwheel.json
|
||||
a38184e035c2ebca7471e1714494fea213af259e assets/create/blockstates/layered_andesite.json
|
||||
2409f04042380a8ad086f9c4f98032e85771c3f3 assets/create/blockstates/layered_asurine.json
|
||||
|
@ -416,6 +418,7 @@ e05f2e98984127aa6b601c4e4909e4c8207b5407 assets/create/blockstates/small_asurine
|
|||
636028cb348cf9a0f060b4232cdb5dc4d26a4d40 assets/create/blockstates/small_asurine_brick_stairs.json
|
||||
d9b5e23652ca70b29a9142ff8f2efd33dfe74904 assets/create/blockstates/small_asurine_brick_wall.json
|
||||
6fc5be0d465faa59aebe016d4ecb4d5284507bef assets/create/blockstates/small_asurine_bricks.json
|
||||
f8982f0241f33b2cd55d6261ab6ee38cb83b6d8d assets/create/blockstates/small_bogey.json
|
||||
2371c092ecbefa9a844889e0a471714d070569dd assets/create/blockstates/small_calcite_brick_slab.json
|
||||
134ba0452fc721333177695882c8cef3cb7eca8e assets/create/blockstates/small_calcite_brick_stairs.json
|
||||
7112ac7498acdd196b05af977e7e12cbab29df14 assets/create/blockstates/small_calcite_brick_wall.json
|
||||
|
@ -476,6 +479,8 @@ f385988cb6fa9c48b5d59a6942ec50ed2b60c8bf assets/create/blockstates/stockpile_swi
|
|||
e815bfd854c2653f10828bb11950f7fb991d7efc assets/create/blockstates/stressometer.json
|
||||
8b0c2c7ac72529565b3339aa8df7565858100afa assets/create/blockstates/tiled_glass.json
|
||||
a2454400b1cf9889f70aebdc89c52a1be25f543c assets/create/blockstates/tiled_glass_pane.json
|
||||
180ab07fdae2bedcf66005c572c8e5c220e6bba2 assets/create/blockstates/track.json
|
||||
aa08785f906d41933e0dd1086ea7b08f5b93aa24 assets/create/blockstates/track_station.json
|
||||
29af21c8d82891139d48d69f0393f612f2b6f8f1 assets/create/blockstates/tuff_pillar.json
|
||||
a8094531617e27a545c4815ab2062bf0ffca3633 assets/create/blockstates/turntable.json
|
||||
c9bf881ea71aa274b2803142456f1bbed9539076 assets/create/blockstates/veridium.json
|
||||
|
@ -530,22 +535,22 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
|
|||
6801fa1f466f172700e573e5b8ee8ee5f9ca4583 assets/create/blockstates/yellow_valve_handle.json
|
||||
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
|
||||
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
|
||||
64a8442735a333c7444cac12cfb22c454ca06b6b assets/create/lang/en_ud.json
|
||||
7f4222143f17e12d1e89a08d91ff97555f3c945e assets/create/lang/en_us.json
|
||||
b375c968109083d7839b80ad347a43b8861a45ac assets/create/lang/unfinished/de_de.json
|
||||
a8b0d479a7817127bc52569167f32378e11420ce assets/create/lang/unfinished/es_cl.json
|
||||
dda7983a065205140c8092b47ed7d4111c4c28a2 assets/create/lang/unfinished/es_es.json
|
||||
8c4ff5b38bae4c8bcc2fec698be98ca26fe09145 assets/create/lang/unfinished/fr_fr.json
|
||||
42281c85374f9583bfb714cc2a634bf59e5cec19 assets/create/lang/unfinished/it_it.json
|
||||
2a5261a51c544bd30fed6124fb39e386779b589b assets/create/lang/unfinished/ja_jp.json
|
||||
69f32419986e38bad60fe437f6ea5c07a3a61cf1 assets/create/lang/unfinished/ko_kr.json
|
||||
f0c2e7e2cdf82a9e8d1ce2d256982bf2050aa63c assets/create/lang/unfinished/nl_nl.json
|
||||
c3f46417c4b5e3c0a83f5a1affcf21ecd2d4694f assets/create/lang/unfinished/pl_pl.json
|
||||
9bdaf0b9b51b35fd10934be46954932d58199a21 assets/create/lang/unfinished/pt_br.json
|
||||
f96ba0f96eb04753ef4431bdda63049174792d12 assets/create/lang/unfinished/pt_pt.json
|
||||
34f8b480a8af8e449a3dfb8c978bbceeb934824f assets/create/lang/unfinished/ru_ru.json
|
||||
78690f57ef5d7dfa40026c6a7558df34203a59b5 assets/create/lang/unfinished/zh_cn.json
|
||||
1116935a6b993de72ec7e15a8f44d06a7de3ebe7 assets/create/lang/unfinished/zh_tw.json
|
||||
edf2d5f68bb6fc51fb2a1614c42b2b788fd857e2 assets/create/lang/en_ud.json
|
||||
1b63bdac0063bbc60ef3c93d8b3f97f40d648ee6 assets/create/lang/en_us.json
|
||||
9f10830c508416004fe2a745eda7e3b4adf10cf8 assets/create/lang/unfinished/de_de.json
|
||||
9f83f6ce12ee18acfb3c29591ff79adb4986d1d6 assets/create/lang/unfinished/es_cl.json
|
||||
58885e0c74b14a186d70b2f5167dfee36a7fbb51 assets/create/lang/unfinished/es_es.json
|
||||
a0f9aec0a4072fda5fd3768003b8b1038be90bb6 assets/create/lang/unfinished/fr_fr.json
|
||||
6eae75c25b1c10433d8a14d68a90454a2f2f3f6a assets/create/lang/unfinished/it_it.json
|
||||
66f7cc9e7976f4c917f4b489878c5ee658ab64a0 assets/create/lang/unfinished/ja_jp.json
|
||||
775a183ea22a2e209d6c7e752c5b0ae438c1d893 assets/create/lang/unfinished/ko_kr.json
|
||||
40dbedf8545dd976f6f84eb62ef621d399e7bdea assets/create/lang/unfinished/nl_nl.json
|
||||
3e7f5a1530cc7fd429229150fb956a2357647542 assets/create/lang/unfinished/pl_pl.json
|
||||
4aa73bd608ae220216abd601b6875ad5bf16974d assets/create/lang/unfinished/pt_br.json
|
||||
81e4b0e807cd1754c4c3a05c2797f9a1e78ab757 assets/create/lang/unfinished/pt_pt.json
|
||||
434eea7907c9b816c293f24172d7424747b4c7b8 assets/create/lang/unfinished/ru_ru.json
|
||||
82d92da2a6e4cab32086f8872387f8a723294d13 assets/create/lang/unfinished/zh_cn.json
|
||||
3813edf0e800083810ea4d51af2faa5d81ac7a98 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
|
||||
|
@ -1618,6 +1623,7 @@ c1da21be9f1af4f7a2ef4ec9cd92195d65ada316 assets/create/models/item/clockwork_bea
|
|||
dcb09deae110077bcddf090996b51cc66e9a7de3 assets/create/models/item/cogwheel.json
|
||||
7717e3b21cff39f497f07687c70c1fa40eaa756d assets/create/models/item/content_observer.json
|
||||
9dbd63c9e1b09a663fd4b83d76e3ab5967086167 assets/create/models/item/controller_rail.json
|
||||
9a93b3ccef02cd0abd8106edec954dc0f2269229 assets/create/models/item/controls.json
|
||||
10397036fc0bb1e18a767cfd7b19b10d805a83fe assets/create/models/item/copper_backtank.json
|
||||
759bcb5fe7dfdd628716f9b4ff19a5ab00393381 assets/create/models/item/copper_casing.json
|
||||
751324b03f657f4166460eb10a64dae47cb97bd4 assets/create/models/item/copper_nugget.json
|
||||
|
@ -1983,6 +1989,7 @@ ef52b3734a47e96c5f83d60da73110e925737933 assets/create/models/item/refined_radia
|
|||
acfbf487ee65c2c58d89cb2644e33fda75751fde assets/create/models/item/rotation_speed_controller.json
|
||||
171c343f7f536008f79ea1d63e0a443d064e9ef1 assets/create/models/item/sail_frame.json
|
||||
5fa0bfe8642e2614a7e97d27af1a95dd2e012097 assets/create/models/item/sand_paper.json
|
||||
98a33e62ab6ef0d1f7eec886ce56f9b4bd01ce1c assets/create/models/item/schedule.json
|
||||
3202829de06e9c532dc8a61c955458648b70d645 assets/create/models/item/schematic.json
|
||||
3f07bc7d4587d78de463ae2ce236e4f363b923cd assets/create/models/item/schematic_and_quill.json
|
||||
8dd5caa4d7a0ee45bd9b39e09c4503159933d089 assets/create/models/item/schematic_table.json
|
||||
|
@ -2066,6 +2073,8 @@ bab8f78c319b2a79ed55c5d2a94b521ddaa44996 assets/create/models/item/stressometer.
|
|||
088af343cda8a949f1d950e15e72b51ffca20a1d assets/create/models/item/sweet_roll.json
|
||||
b1d3d00ff05908feacad06a86800da96cc9bc65d assets/create/models/item/tiled_glass.json
|
||||
a7d0b746637897209bd86b1a6501ecbfb46d8270 assets/create/models/item/tiled_glass_pane.json
|
||||
6b5569f25fa2d905729a3f18deb56b6c67c5dfa4 assets/create/models/item/track.json
|
||||
d6364e9d11915e53dafd8761f016e4b23c7703c8 assets/create/models/item/track_station.json
|
||||
f8a4fa1ccecb16a3941cc46db7481ed8e8429a5e assets/create/models/item/tree_fertilizer.json
|
||||
3f6810da54724de551591b46cd5b47a98a4737ef assets/create/models/item/tuff_pillar.json
|
||||
fb24881c4e92bbb7ffa54a71e0af6b1c66d84829 assets/create/models/item/turntable.json
|
||||
|
@ -3322,6 +3331,7 @@ bd4ed53c029fcd6e5da7e43ebe4d15030d3fd9de data/create/loot_tables/blocks/clockwor
|
|||
982a41e1bccd9a130a2874aff995d4f7da0f0316 data/create/loot_tables/blocks/cogwheel.json
|
||||
c2b075008849e152f20e8da946e89c9722325df6 data/create/loot_tables/blocks/content_observer.json
|
||||
28856dc862efc6bcc421d035d26386740458f868 data/create/loot_tables/blocks/controller_rail.json
|
||||
2c2785e39e1891dff2c50cba93e814b56d935154 data/create/loot_tables/blocks/controls.json
|
||||
3abf04f6132955275ad490668cd28f481afb4ec2 data/create/loot_tables/blocks/copper_backtank.json
|
||||
8010db6b2427536c74312c85425b3ba83abc363c data/create/loot_tables/blocks/copper_casing.json
|
||||
31b3e00f6ab3e593a0d6abd42961b3e5e03fc888 data/create/loot_tables/blocks/copper_shingle_slab.json
|
||||
|
@ -3507,6 +3517,7 @@ feed1cd9639de957c9b34212d1c4aef2044d1e31 data/create/loot_tables/blocks/item_dra
|
|||
af3042824de4aff38e27657ebb084077a7d4f925 data/create/loot_tables/blocks/item_vault.json
|
||||
db23fee08abdb61fe2f200a5016e41523159feef data/create/loot_tables/blocks/jungle_window.json
|
||||
67f7d9162d3b86e198ab7faa1ddcfdfce605d10c data/create/loot_tables/blocks/jungle_window_pane.json
|
||||
5c1df8443043b3fe3b665dba348e2ff188bcbe31 data/create/loot_tables/blocks/large_bogey.json
|
||||
a70fcfe474ba023adc9c326218c5664fbd7b58f8 data/create/loot_tables/blocks/large_cogwheel.json
|
||||
81013913c3cc88e2390608420a2911d57414bd2c data/create/loot_tables/blocks/layered_andesite.json
|
||||
a89d357d3b8d7633bffe12a4197ab19cba891005 data/create/loot_tables/blocks/layered_asurine.json
|
||||
|
@ -3688,6 +3699,7 @@ af9c104f3d5863191aedf25c83c647de439c215f data/create/loot_tables/blocks/small_as
|
|||
56aa727f02da49231e52593f4904eff3a93475ab data/create/loot_tables/blocks/small_asurine_brick_stairs.json
|
||||
172dc3a9a866895035553e6ff166755a24afd0ff data/create/loot_tables/blocks/small_asurine_brick_wall.json
|
||||
db97cf328010da9b5f643dbfde12660e9f8a33f8 data/create/loot_tables/blocks/small_asurine_bricks.json
|
||||
5c1df8443043b3fe3b665dba348e2ff188bcbe31 data/create/loot_tables/blocks/small_bogey.json
|
||||
9a48f87a53b61188cfddbcf217b251ba13ee08df data/create/loot_tables/blocks/small_calcite_brick_slab.json
|
||||
542fb74a3b02b5f947dbe9bd9d919b631ffd3ff3 data/create/loot_tables/blocks/small_calcite_brick_stairs.json
|
||||
8b03b9773f2be01cf639c0fedcf69bb05f9a0f7d data/create/loot_tables/blocks/small_calcite_brick_wall.json
|
||||
|
@ -3748,6 +3760,8 @@ ad771358ecd71e2f0c4b71f7244947fc2dc2a1c9 data/create/loot_tables/blocks/spruce_w
|
|||
da3ceb80799d349b91781b0dd43a02e548045c66 data/create/loot_tables/blocks/stressometer.json
|
||||
811674fd816503cd78fc4df267dc23f760940e8f data/create/loot_tables/blocks/tiled_glass.json
|
||||
313344ef4ee67ffd0f7fd44adcb3ad08de571c92 data/create/loot_tables/blocks/tiled_glass_pane.json
|
||||
e2846b8823918bce402eb361f703ecdc14251ccc data/create/loot_tables/blocks/track.json
|
||||
4617a11e220dcd0094c29d204fe90c01495c4e9b data/create/loot_tables/blocks/track_station.json
|
||||
8fbe59bc77b029b802c43fb8a930778dede440ea data/create/loot_tables/blocks/tuff_pillar.json
|
||||
2419d50b6086e92ab05624fdf38ef2b55c0b0944 data/create/loot_tables/blocks/turntable.json
|
||||
2706ebca18074fe8d7a988d2c0002c857bff5c2b data/create/loot_tables/blocks/veridium.json
|
||||
|
@ -5259,8 +5273,8 @@ ff1900963bc4cd8ceffa78d58ef1952ceacb2fb7 data/forge/tags/items/storage_blocks/br
|
|||
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/dripstone_replaceable_blocks.json
|
||||
69f596fcb065e26b02ce246760432b5174191b76 data/minecraft/tags/blocks/impermeable.json
|
||||
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/lush_ground_replaceable.json
|
||||
59681910c06f8b7385c6641a409d352056235506 data/minecraft/tags/blocks/mineable/axe.json
|
||||
f8c66b3808efb61d2d928748783bb7eb8a1357f9 data/minecraft/tags/blocks/mineable/pickaxe.json
|
||||
02f7a9df2f9e154749266e7ac59c37aa076a3390 data/minecraft/tags/blocks/mineable/axe.json
|
||||
b52748d3d434dd40ba10db8e97fa2102d7acb638 data/minecraft/tags/blocks/mineable/pickaxe.json
|
||||
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/moss_replaceable.json
|
||||
e157c1d3af30e409e34bbefbe15a037e6e1c8daa data/minecraft/tags/blocks/needs_iron_tool.json
|
||||
a08f67865337f62601c5e333b4011382d10020e4 data/minecraft/tags/blocks/needs_stone_tool.json
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"variants": {
|
||||
"facing=north,open=false": {
|
||||
"model": "create:block/controls/block_closed"
|
||||
},
|
||||
"facing=south,open=false": {
|
||||
"model": "create:block/controls/block_closed",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,open=false": {
|
||||
"model": "create:block/controls/block_closed",
|
||||
"y": 270
|
||||
},
|
||||
"facing=east,open=false": {
|
||||
"model": "create:block/controls/block_closed",
|
||||
"y": 90
|
||||
},
|
||||
"facing=north,open=true": {
|
||||
"model": "create:block/controls/block_open"
|
||||
},
|
||||
"facing=south,open=true": {
|
||||
"model": "create:block/controls/block_open",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,open=true": {
|
||||
"model": "create:block/controls/block_open",
|
||||
"y": 270
|
||||
},
|
||||
"facing=east,open=true": {
|
||||
"model": "create:block/controls/block_open",
|
||||
"y": 90
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"variants": {
|
||||
"axis=x": {
|
||||
"model": "create:block/track/bogey/top",
|
||||
"y": 90
|
||||
},
|
||||
"axis=z": {
|
||||
"model": "create:block/track/bogey/top"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"variants": {
|
||||
"axis=x": {
|
||||
"model": "create:block/track/bogey/top",
|
||||
"y": 90
|
||||
},
|
||||
"axis=z": {
|
||||
"model": "create:block/track/bogey/top"
|
||||
}
|
||||
}
|
||||
}
|
64
src/generated/resources/assets/create/blockstates/track.json
Normal file
64
src/generated/resources/assets/create/blockstates/track.json
Normal file
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"variants": {
|
||||
"shape=none,turn=false": {
|
||||
"model": "minecraft:block/air"
|
||||
},
|
||||
"shape=zo,turn=false": {
|
||||
"model": "create:block/track/z_ortho"
|
||||
},
|
||||
"shape=xo,turn=false": {
|
||||
"model": "create:block/track/x_ortho"
|
||||
},
|
||||
"shape=pd,turn=false": {
|
||||
"model": "create:block/track/pos_diag"
|
||||
},
|
||||
"shape=nd,turn=false": {
|
||||
"model": "create:block/track/neg_diag"
|
||||
},
|
||||
"shape=an,turn=false": {
|
||||
"model": "create:block/track/ascending",
|
||||
"y": 180
|
||||
},
|
||||
"shape=as,turn=false": {
|
||||
"model": "create:block/track/ascending"
|
||||
},
|
||||
"shape=ae,turn=false": {
|
||||
"model": "create:block/track/ascending",
|
||||
"y": 270
|
||||
},
|
||||
"shape=aw,turn=false": {
|
||||
"model": "create:block/track/ascending",
|
||||
"y": 90
|
||||
},
|
||||
"shape=none,turn=true": {
|
||||
"model": "minecraft:block/air"
|
||||
},
|
||||
"shape=zo,turn=true": {
|
||||
"model": "create:block/track/z_ortho"
|
||||
},
|
||||
"shape=xo,turn=true": {
|
||||
"model": "create:block/track/x_ortho"
|
||||
},
|
||||
"shape=pd,turn=true": {
|
||||
"model": "create:block/track/pos_diag"
|
||||
},
|
||||
"shape=nd,turn=true": {
|
||||
"model": "create:block/track/neg_diag"
|
||||
},
|
||||
"shape=an,turn=true": {
|
||||
"model": "create:block/track/ascending",
|
||||
"y": 180
|
||||
},
|
||||
"shape=as,turn=true": {
|
||||
"model": "create:block/track/ascending"
|
||||
},
|
||||
"shape=ae,turn=true": {
|
||||
"model": "create:block/track/ascending",
|
||||
"y": 270
|
||||
},
|
||||
"shape=aw,turn=true": {
|
||||
"model": "create:block/track/ascending",
|
||||
"y": 90
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"variants": {
|
||||
"assembling=false,facing=north": {
|
||||
"model": "create:block/track_station/block"
|
||||
},
|
||||
"assembling=true,facing=north": {
|
||||
"model": "create:block/track_station/block_assembling"
|
||||
},
|
||||
"assembling=false,facing=south": {
|
||||
"model": "create:block/track_station/block",
|
||||
"y": 180
|
||||
},
|
||||
"assembling=true,facing=south": {
|
||||
"model": "create:block/track_station/block_assembling",
|
||||
"y": 180
|
||||
},
|
||||
"assembling=false,facing=west": {
|
||||
"model": "create:block/track_station/block",
|
||||
"y": 270
|
||||
},
|
||||
"assembling=true,facing=west": {
|
||||
"model": "create:block/track_station/block_assembling",
|
||||
"y": 270
|
||||
},
|
||||
"assembling=false,facing=east": {
|
||||
"model": "create:block/track_station/block",
|
||||
"y": 90
|
||||
},
|
||||
"assembling=true,facing=east": {
|
||||
"model": "create:block/track_station/block_assembling",
|
||||
"y": 90
|
||||
}
|
||||
}
|
||||
}
|
|
@ -50,6 +50,7 @@
|
|||
"block.create.cogwheel": "\u05DF\u01DD\u01DD\u0265\u028Dbo\u0186",
|
||||
"block.create.content_observer": "\u0279\u01DD\u028C\u0279\u01DDsqO \u0287u\u01DD\u0287uo\u0186",
|
||||
"block.create.controller_rail": "\u05DF\u0131\u0250\u1D1A \u0279\u01DD\u05DF\u05DFo\u0279\u0287uo\u0186",
|
||||
"block.create.controls": "s\u05DFo\u0279\u0287uo\u0186",
|
||||
"block.create.copper_backtank": "\u029Eu\u0250\u0287\u029E\u0254\u0250\u15FA \u0279\u01DDddo\u0186",
|
||||
"block.create.copper_casing": "bu\u0131s\u0250\u0186 \u0279\u01DDddo\u0186",
|
||||
"block.create.copper_shingle_slab": "q\u0250\u05DFS \u01DD\u05DFbu\u0131\u0265S \u0279\u01DDddo\u0186",
|
||||
|
@ -236,6 +237,7 @@
|
|||
"block.create.item_vault": "\u0287\u05DFn\u0250\u039B \u026F\u01DD\u0287I",
|
||||
"block.create.jungle_window": "\u028Dopu\u0131M \u01DD\u05DFbun\u017F",
|
||||
"block.create.jungle_window_pane": "\u01DDu\u0250\u0500 \u028Dopu\u0131M \u01DD\u05DFbun\u017F",
|
||||
"block.create.large_bogey": "\u028E\u01DDbo\u15FA \u01DDb\u0279\u0250\uA780",
|
||||
"block.create.large_cogwheel": "\u05DF\u01DD\u01DD\u0265\u028Dbo\u0186 \u01DDb\u0279\u0250\uA780",
|
||||
"block.create.layered_andesite": "\u01DD\u0287\u0131s\u01DDpu\u2C6F p\u01DD\u0279\u01DD\u028E\u0250\uA780",
|
||||
"block.create.layered_asurine": "\u01DDu\u0131\u0279ns\u2C6F p\u01DD\u0279\u01DD\u028E\u0250\uA780",
|
||||
|
@ -417,6 +419,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "s\u0279\u0131\u0250\u0287S \u029E\u0254\u0131\u0279\u15FA \u01DDu\u0131\u0279ns\u2C6F \u05DF\u05DF\u0250\u026FS",
|
||||
"block.create.small_asurine_brick_wall": "\u05DF\u05DF\u0250M \u029E\u0254\u0131\u0279\u15FA \u01DDu\u0131\u0279ns\u2C6F \u05DF\u05DF\u0250\u026FS",
|
||||
"block.create.small_asurine_bricks": "s\u029E\u0254\u0131\u0279\u15FA \u01DDu\u0131\u0279ns\u2C6F \u05DF\u05DF\u0250\u026FS",
|
||||
"block.create.small_bogey": "\u028E\u01DDbo\u15FA \u05DF\u05DF\u0250\u026FS",
|
||||
"block.create.small_calcite_brick_slab": "q\u0250\u05DFS \u029E\u0254\u0131\u0279\u15FA \u01DD\u0287\u0131\u0254\u05DF\u0250\u0186 \u05DF\u05DF\u0250\u026FS",
|
||||
"block.create.small_calcite_brick_stairs": "s\u0279\u0131\u0250\u0287S \u029E\u0254\u0131\u0279\u15FA \u01DD\u0287\u0131\u0254\u05DF\u0250\u0186 \u05DF\u05DF\u0250\u026FS",
|
||||
"block.create.small_calcite_brick_wall": "\u05DF\u05DF\u0250M \u029E\u0254\u0131\u0279\u15FA \u01DD\u0287\u0131\u0254\u05DF\u0250\u0186 \u05DF\u05DF\u0250\u026FS",
|
||||
|
@ -477,6 +480,8 @@
|
|||
"block.create.stressometer": "\u0279\u01DD\u0287\u01DD\u026Foss\u01DD\u0279\u0287S",
|
||||
"block.create.tiled_glass": "ss\u0250\u05DF\u2141 p\u01DD\u05DF\u0131\u27D8",
|
||||
"block.create.tiled_glass_pane": "\u01DDu\u0250\u0500 ss\u0250\u05DF\u2141 p\u01DD\u05DF\u0131\u27D8",
|
||||
"block.create.track": "\u029E\u0254\u0250\u0279\u27D8",
|
||||
"block.create.track_station": "uo\u0131\u0287\u0250\u0287S \u029E\u0254\u0250\u0279\u27D8",
|
||||
"block.create.tuff_pillar": "\u0279\u0250\u05DF\u05DF\u0131\u0500 \u025F\u025Fn\u27D8",
|
||||
"block.create.turntable": "\u01DD\u05DFq\u0250\u0287u\u0279n\u27D8",
|
||||
"block.create.veridium": "\u026Fn\u0131p\u0131\u0279\u01DD\u039B",
|
||||
|
@ -533,6 +538,7 @@
|
|||
"block.create.zinc_ore": "\u01DD\u0279O \u0254u\u0131Z",
|
||||
"enchantment.create.capacity": "\u028E\u0287\u0131\u0254\u0250d\u0250\u0186",
|
||||
"enchantment.create.potato_recovery": "\u028E\u0279\u01DD\u028Co\u0254\u01DD\u1D1A o\u0287\u0250\u0287o\u0500",
|
||||
"entity.create.carriage_contraption": "uo\u0131\u0287d\u0250\u0279\u0287uo\u0186 \u01DDb\u0250\u0131\u0279\u0279\u0250\u0186",
|
||||
"entity.create.contraption": "uo\u0131\u0287d\u0250\u0279\u0287uo\u0186",
|
||||
"entity.create.crafting_blueprint": "\u0287u\u0131\u0279d\u01DDn\u05DF\u15FA bu\u0131\u0287\u025F\u0250\u0279\u0186",
|
||||
"entity.create.gantry_contraption": "uo\u0131\u0287d\u0250\u0279\u0287uo\u0186 \u028E\u0279\u0287u\u0250\u2141",
|
||||
|
@ -609,6 +615,7 @@
|
|||
"item.create.refined_radiance": "\u01DD\u0254u\u0250\u0131p\u0250\u1D1A p\u01DDu\u0131\u025F\u01DD\u1D1A",
|
||||
"item.create.rose_quartz": "z\u0287\u0279\u0250n\u1F49 \u01DDso\u1D1A",
|
||||
"item.create.sand_paper": "\u0279\u01DDd\u0250\u0500 pu\u0250S",
|
||||
"item.create.schedule": "\u01DD\u05DFnp\u01DD\u0265\u0254S",
|
||||
"item.create.schematic": "\u0254\u0131\u0287\u0250\u026F\u01DD\u0265\u0254S",
|
||||
"item.create.schematic_and_quill": "\u05DF\u05DF\u0131n\u1F49 pu\u2C6F \u0254\u0131\u0287\u0250\u026F\u01DD\u0265\u0254S",
|
||||
"item.create.shadow_steel": "\u05DF\u01DD\u01DD\u0287S \u028Dop\u0250\u0265S",
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
"block.create.cogwheel": "Cogwheel",
|
||||
"block.create.content_observer": "Content Observer",
|
||||
"block.create.controller_rail": "Controller Rail",
|
||||
"block.create.controls": "Controls",
|
||||
"block.create.copper_backtank": "Copper Backtank",
|
||||
"block.create.copper_casing": "Copper Casing",
|
||||
"block.create.copper_shingle_slab": "Copper Shingle Slab",
|
||||
|
@ -239,6 +240,7 @@
|
|||
"block.create.item_vault": "Item Vault",
|
||||
"block.create.jungle_window": "Jungle Window",
|
||||
"block.create.jungle_window_pane": "Jungle Window Pane",
|
||||
"block.create.large_bogey": "Large Bogey",
|
||||
"block.create.large_cogwheel": "Large Cogwheel",
|
||||
"block.create.layered_andesite": "Layered Andesite",
|
||||
"block.create.layered_asurine": "Layered Asurine",
|
||||
|
@ -420,6 +422,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "Small Asurine Brick Stairs",
|
||||
"block.create.small_asurine_brick_wall": "Small Asurine Brick Wall",
|
||||
"block.create.small_asurine_bricks": "Small Asurine Bricks",
|
||||
"block.create.small_bogey": "Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "Small Calcite Brick Slab",
|
||||
"block.create.small_calcite_brick_stairs": "Small Calcite Brick Stairs",
|
||||
"block.create.small_calcite_brick_wall": "Small Calcite Brick Wall",
|
||||
|
@ -480,6 +483,8 @@
|
|||
"block.create.stressometer": "Stressometer",
|
||||
"block.create.tiled_glass": "Tiled Glass",
|
||||
"block.create.tiled_glass_pane": "Tiled Glass Pane",
|
||||
"block.create.track": "Track",
|
||||
"block.create.track_station": "Track Station",
|
||||
"block.create.tuff_pillar": "Tuff Pillar",
|
||||
"block.create.turntable": "Turntable",
|
||||
"block.create.veridium": "Veridium",
|
||||
|
@ -538,6 +543,7 @@
|
|||
"enchantment.create.capacity": "Capacity",
|
||||
"enchantment.create.potato_recovery": "Potato Recovery",
|
||||
|
||||
"entity.create.carriage_contraption": "Carriage Contraption",
|
||||
"entity.create.contraption": "Contraption",
|
||||
"entity.create.crafting_blueprint": "Crafting Blueprint",
|
||||
"entity.create.gantry_contraption": "Gantry Contraption",
|
||||
|
@ -616,6 +622,7 @@
|
|||
"item.create.refined_radiance": "Refined Radiance",
|
||||
"item.create.rose_quartz": "Rose Quartz",
|
||||
"item.create.sand_paper": "Sand Paper",
|
||||
"item.create.schedule": "Schedule",
|
||||
"item.create.schematic": "Schematic",
|
||||
"item.create.schematic_and_quill": "Schematic And Quill",
|
||||
"item.create.shadow_steel": "Shadow Steel",
|
||||
|
@ -863,9 +870,15 @@
|
|||
"create.generic.length": "Length",
|
||||
"create.generic.speed": "Speed",
|
||||
"create.generic.delay": "Delay",
|
||||
"create.generic.duration": "Duration",
|
||||
"create.generic.timeUnit": "Time Unit",
|
||||
"create.generic.unit.ticks": "Ticks",
|
||||
"create.generic.unit.seconds": "Seconds",
|
||||
"create.generic.unit.minutes": "Minutes",
|
||||
"create.generic.daytime.hour": "Hour",
|
||||
"create.generic.daytime.minute": "Minute",
|
||||
"create.generic.daytime.pm": "pm",
|
||||
"create.generic.daytime.am": "am",
|
||||
"create.generic.unit.rpm": "RPM",
|
||||
"create.generic.unit.stress": "su",
|
||||
"create.generic.unit.degrees": "°",
|
||||
|
@ -1309,6 +1322,60 @@
|
|||
"create.hint.full_deployer.title": "Deployer Item Overflow",
|
||||
"create.hint.full_deployer": "It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "Duplicate",
|
||||
"create.gui.schedule.remove_entry": "Remove Stop",
|
||||
"create.gui.schedule.add_entry": "Add Stop",
|
||||
"create.gui.schedule.move_up": "Move up",
|
||||
"create.gui.schedule.move_down": "Move down",
|
||||
"create.gui.schedule.add_condition": "Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "Next Stop:",
|
||||
"create.schedule.destination.editor": "Destination Editor",
|
||||
"create.schedule.destination.filtered": "Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "Station: %1$s",
|
||||
"create.schedule.destination.filter": "Station Name",
|
||||
"create.schedule.destination.filter_2": "Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "Nearest Station",
|
||||
"create.schedule.destination.redstone": "Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "Continue when:",
|
||||
"create.schedule.condition.editor": "Condition Editor",
|
||||
"create.schedule.condition.delay": "Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "Wait: %1$s",
|
||||
"create.schedule.condition.idle": "Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "for %1$s",
|
||||
"create.schedule.condition.unloaded": "Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "Station Powered",
|
||||
"create.schedule.condition.time_of_day": "Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "%1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "+%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "More than",
|
||||
"create.schedule.condition.threshold.less": "Less than",
|
||||
"create.schedule.condition.threshold.equal": "Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "%1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "Item Measure",
|
||||
"create.schedule.condition.threshold.items": "Items",
|
||||
"create.schedule.condition.threshold.stacks": "Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "Item Cargo Condition",
|
||||
"create.schedule.loop": "Loop Forever",
|
||||
"create.schedule.loop1": "Schedule starts over",
|
||||
"create.schedule.loop2": "when completed",
|
||||
|
||||
"create.train.unnamed": "Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "Hi :)",
|
||||
"create.gui.config.overlay2": "This is a sample overlay",
|
||||
"create.gui.config.overlay3": "Click or drag with your mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1323",
|
||||
"_": "Missing Localizations: 1387",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "Zahnrad",
|
||||
"block.create.content_observer": "Inhaltsbeobachter",
|
||||
"block.create.controller_rail": "Steuerungsschiene",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "UNLOCALIZED: Copper Backtank",
|
||||
"block.create.copper_casing": "Kupferrahmen",
|
||||
"block.create.copper_shingle_slab": "UNLOCALIZED: Copper Shingle Slab",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "UNLOCALIZED: Item Vault",
|
||||
"block.create.jungle_window": "Tropenholzfenster",
|
||||
"block.create.jungle_window_pane": "Tropenholzfensterscheibe",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "Großes Zahnrad",
|
||||
"block.create.layered_andesite": "Geschichteter Andesit",
|
||||
"block.create.layered_asurine": "UNLOCALIZED: Layered Asurine",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "UNLOCALIZED: Small Asurine Brick Stairs",
|
||||
"block.create.small_asurine_brick_wall": "UNLOCALIZED: Small Asurine Brick Wall",
|
||||
"block.create.small_asurine_bricks": "UNLOCALIZED: Small Asurine Bricks",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "UNLOCALIZED: Small Calcite Brick Slab",
|
||||
"block.create.small_calcite_brick_stairs": "UNLOCALIZED: Small Calcite Brick Stairs",
|
||||
"block.create.small_calcite_brick_wall": "UNLOCALIZED: Small Calcite Brick Wall",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "Stressometer",
|
||||
"block.create.tiled_glass": "Glasfliesen",
|
||||
"block.create.tiled_glass_pane": "Glasfliesenscheibe",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "UNLOCALIZED: Tuff Pillar",
|
||||
"block.create.turntable": "Drehtisch",
|
||||
"block.create.veridium": "UNLOCALIZED: Veridium",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "UNLOCALIZED: Capacity",
|
||||
"enchantment.create.potato_recovery": "UNLOCALIZED: Potato Recovery",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "Vorrichtung",
|
||||
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
|
||||
"entity.create.gantry_contraption": "Portalkran Vorrichtung",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "Raffinierter Glanz",
|
||||
"item.create.rose_quartz": "Rosenquarz",
|
||||
"item.create.sand_paper": "Schmirgelpapier",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "Bauplan",
|
||||
"item.create.schematic_and_quill": "Bauplan und Feder",
|
||||
"item.create.shadow_steel": "Schattenstahl",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "Länge",
|
||||
"create.generic.speed": "Geschwindigkeit",
|
||||
"create.generic.delay": "Verzögerung",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "Ticks",
|
||||
"create.generic.unit.seconds": "Sekunden",
|
||||
"create.generic.unit.minutes": "Minuten",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "RPM",
|
||||
"create.generic.unit.stress": "su",
|
||||
"create.generic.unit.degrees": "°",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "Einsatzgerät Gegenstand Überlauf",
|
||||
"create.hint.full_deployer": "Es scheint, dieses _Einsatzgerät_ enthält _überflüssige_ _Gegenstände_ die _extrahiert_ werden müssen. Nutze _Trichter_ oder anderes um ihn von seinem Überfluss zu befreien.",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "Hi :)",
|
||||
"create.gui.config.overlay2": "Dies ist ein Beispiel Overlay",
|
||||
"create.gui.config.overlay3": "Klicke oder ziehe mit deiner Maus",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 334",
|
||||
"_": "Missing Localizations: 398",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "Engranaje",
|
||||
"block.create.content_observer": "Observador de Contenidos",
|
||||
"block.create.controller_rail": "Raíl Controlador",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "Tanque-Mochila de Cobre",
|
||||
"block.create.copper_casing": "Cubierta de Cobre",
|
||||
"block.create.copper_shingle_slab": "UNLOCALIZED: Copper Shingle Slab",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "UNLOCALIZED: Item Vault",
|
||||
"block.create.jungle_window": "Ventana de Jungla",
|
||||
"block.create.jungle_window_pane": "Panel de Ventana de Jungla",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "Engranaje Grande",
|
||||
"block.create.layered_andesite": "Capa de Andesita",
|
||||
"block.create.layered_asurine": "UNLOCALIZED: Layered Asurine",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "UNLOCALIZED: Small Asurine Brick Stairs",
|
||||
"block.create.small_asurine_brick_wall": "UNLOCALIZED: Small Asurine Brick Wall",
|
||||
"block.create.small_asurine_bricks": "UNLOCALIZED: Small Asurine Bricks",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "UNLOCALIZED: Small Calcite Brick Slab",
|
||||
"block.create.small_calcite_brick_stairs": "UNLOCALIZED: Small Calcite Brick Stairs",
|
||||
"block.create.small_calcite_brick_wall": "UNLOCALIZED: Small Calcite Brick Wall",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "Estresómetro",
|
||||
"block.create.tiled_glass": "Vidrio Baldosa",
|
||||
"block.create.tiled_glass_pane": "Panel de Vidrio Baldosa",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "UNLOCALIZED: Tuff Pillar",
|
||||
"block.create.turntable": "Plato Giratorio",
|
||||
"block.create.veridium": "UNLOCALIZED: Veridium",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "Capacidad",
|
||||
"enchantment.create.potato_recovery": "Recuperación de papas",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "Artefacto",
|
||||
"entity.create.crafting_blueprint": "Crafteando Planos",
|
||||
"entity.create.gantry_contraption": "Artefacto de Grúa",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "Radiancia Refinada",
|
||||
"item.create.rose_quartz": "Cuarzo Rosa",
|
||||
"item.create.sand_paper": "Papel de Arena",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "Esquema",
|
||||
"item.create.schematic_and_quill": "Esquema con Pluma",
|
||||
"item.create.shadow_steel": "Acero Sombrío",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "Largo",
|
||||
"create.generic.speed": "Velocidad",
|
||||
"create.generic.delay": "Retraso",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "Ticks",
|
||||
"create.generic.unit.seconds": "Segundos",
|
||||
"create.generic.unit.minutes": "Minutos",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "RPM",
|
||||
"create.generic.unit.stress": "us",
|
||||
"create.generic.unit.degrees": "°",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "Desbordamiento de objetos del Desplegador",
|
||||
"create.hint.full_deployer": "Parece que este _Desplegador_ contiene _objetos_ de _exceso_ que requieren ser _extraídos._ Usa una _tolva,_ _tolvogán_ u otros parecidos para librarlo del sobreflujo.",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "Hola :)",
|
||||
"create.gui.config.overlay2": "Este es un overlay de ejemplo",
|
||||
"create.gui.config.overlay3": "Haz clic o arrastra con el mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 334",
|
||||
"_": "Missing Localizations: 398",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "Engranaje pequeño",
|
||||
"block.create.content_observer": "Observador de contenidos",
|
||||
"block.create.controller_rail": "Raíl de control",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "Depósito trasero de cobre",
|
||||
"block.create.copper_casing": "Revestidor de caliza",
|
||||
"block.create.copper_shingle_slab": "UNLOCALIZED: Copper Shingle Slab",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "UNLOCALIZED: Item Vault",
|
||||
"block.create.jungle_window": "Ventana de jungla",
|
||||
"block.create.jungle_window_pane": "Panel de ventana de jungla",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "Engranaje grande",
|
||||
"block.create.layered_andesite": "Andesita estratificada",
|
||||
"block.create.layered_asurine": "UNLOCALIZED: Layered Asurine",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "UNLOCALIZED: Small Asurine Brick Stairs",
|
||||
"block.create.small_asurine_brick_wall": "UNLOCALIZED: Small Asurine Brick Wall",
|
||||
"block.create.small_asurine_bricks": "UNLOCALIZED: Small Asurine Bricks",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "UNLOCALIZED: Small Calcite Brick Slab",
|
||||
"block.create.small_calcite_brick_stairs": "UNLOCALIZED: Small Calcite Brick Stairs",
|
||||
"block.create.small_calcite_brick_wall": "UNLOCALIZED: Small Calcite Brick Wall",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "Estresómetro",
|
||||
"block.create.tiled_glass": "Vidrio esmaltado",
|
||||
"block.create.tiled_glass_pane": "Panel de vidrio esmaltado",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "UNLOCALIZED: Tuff Pillar",
|
||||
"block.create.turntable": "Plataforma giratoria mecánica",
|
||||
"block.create.veridium": "UNLOCALIZED: Veridium",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "Capacidad",
|
||||
"enchantment.create.potato_recovery": "Recuperación de patatas",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "Artilugio",
|
||||
"entity.create.crafting_blueprint": "Plano de elaboración",
|
||||
"entity.create.gantry_contraption": "Artilugio de grúa",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "Resplandor refinado",
|
||||
"item.create.rose_quartz": "Cuarzo rosado",
|
||||
"item.create.sand_paper": "Papel de lija",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "Esquema",
|
||||
"item.create.schematic_and_quill": "Esquema y pluma",
|
||||
"item.create.shadow_steel": "Acero sombrío",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "Largo",
|
||||
"create.generic.speed": "Velocidad",
|
||||
"create.generic.delay": "Retraso",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "Ticks",
|
||||
"create.generic.unit.seconds": "Segundos",
|
||||
"create.generic.unit.minutes": "Minutos",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "RPM",
|
||||
"create.generic.unit.stress": "SU(unidades de estrés)",
|
||||
"create.generic.unit.degrees": "°",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "Exceso de objetos en el desplegador",
|
||||
"create.hint.full_deployer": "Parece que este _desplegador_ contiene _exceso_ de objetos que necesitan ser _extraídos._ Usa una _tolva_, _embudo_ u otro medio para liberarlo de su excedente.",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "Hola :)",
|
||||
"create.gui.config.overlay2": "Esta es una muestra de la superposición",
|
||||
"create.gui.config.overlay3": "Haga clic o arrastre con el ratón",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1585",
|
||||
"_": "Missing Localizations: 1649",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "Roue dentée",
|
||||
"block.create.content_observer": "Observateur de contenu",
|
||||
"block.create.controller_rail": "Rails controlleurs",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "UNLOCALIZED: Copper Backtank",
|
||||
"block.create.copper_casing": "Revêtement en cuivre",
|
||||
"block.create.copper_shingle_slab": "UNLOCALIZED: Copper Shingle Slab",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "UNLOCALIZED: Item Vault",
|
||||
"block.create.jungle_window": "UNLOCALIZED: Jungle Window",
|
||||
"block.create.jungle_window_pane": "UNLOCALIZED: Jungle Window Pane",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "Grande roue dentée",
|
||||
"block.create.layered_andesite": "UNLOCALIZED: Layered Andesite",
|
||||
"block.create.layered_asurine": "UNLOCALIZED: Layered Asurine",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "UNLOCALIZED: Small Asurine Brick Stairs",
|
||||
"block.create.small_asurine_brick_wall": "UNLOCALIZED: Small Asurine Brick Wall",
|
||||
"block.create.small_asurine_bricks": "UNLOCALIZED: Small Asurine Bricks",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "UNLOCALIZED: Small Calcite Brick Slab",
|
||||
"block.create.small_calcite_brick_stairs": "UNLOCALIZED: Small Calcite Brick Stairs",
|
||||
"block.create.small_calcite_brick_wall": "UNLOCALIZED: Small Calcite Brick Wall",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "Stressomètre",
|
||||
"block.create.tiled_glass": "Verre carrelé",
|
||||
"block.create.tiled_glass_pane": "Vitre carrelé",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "UNLOCALIZED: Tuff Pillar",
|
||||
"block.create.turntable": "Plaque tournante",
|
||||
"block.create.veridium": "UNLOCALIZED: Veridium",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "UNLOCALIZED: Capacity",
|
||||
"enchantment.create.potato_recovery": "UNLOCALIZED: Potato Recovery",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "Engin",
|
||||
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
|
||||
"entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "Éclat raffiné",
|
||||
"item.create.rose_quartz": "Quartz rose",
|
||||
"item.create.sand_paper": "Papier de verre",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "Schéma",
|
||||
"item.create.schematic_and_quill": "Schéma et plume",
|
||||
"item.create.shadow_steel": "Acier sombre",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "Longueur",
|
||||
"create.generic.speed": "Vitesse",
|
||||
"create.generic.delay": "Delai",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "Ticks",
|
||||
"create.generic.unit.seconds": "Secondes",
|
||||
"create.generic.unit.minutes": "Minutes",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "tr/min",
|
||||
"create.generic.unit.stress": "us",
|
||||
"create.generic.unit.degrees": "°",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "UNLOCALIZED: Deployer Item Overflow",
|
||||
"create.hint.full_deployer": "UNLOCALIZED: It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "UNLOCALIZED: Hi :)",
|
||||
"create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay",
|
||||
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1274",
|
||||
"_": "Missing Localizations: 1338",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "Ruota dentata",
|
||||
"block.create.content_observer": "Osservatore dei contenuti",
|
||||
"block.create.controller_rail": "Binario di controllo",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "UNLOCALIZED: Copper Backtank",
|
||||
"block.create.copper_casing": "Involucro di rame",
|
||||
"block.create.copper_shingle_slab": "UNLOCALIZED: Copper Shingle Slab",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "UNLOCALIZED: Item Vault",
|
||||
"block.create.jungle_window": "Finestra della giungla",
|
||||
"block.create.jungle_window_pane": "Pannello di finestra della giungla",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "Ruota dentata grande",
|
||||
"block.create.layered_andesite": "Andesite stratificata",
|
||||
"block.create.layered_asurine": "UNLOCALIZED: Layered Asurine",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "UNLOCALIZED: Small Asurine Brick Stairs",
|
||||
"block.create.small_asurine_brick_wall": "UNLOCALIZED: Small Asurine Brick Wall",
|
||||
"block.create.small_asurine_bricks": "UNLOCALIZED: Small Asurine Bricks",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "UNLOCALIZED: Small Calcite Brick Slab",
|
||||
"block.create.small_calcite_brick_stairs": "UNLOCALIZED: Small Calcite Brick Stairs",
|
||||
"block.create.small_calcite_brick_wall": "UNLOCALIZED: Small Calcite Brick Wall",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "Stressometro",
|
||||
"block.create.tiled_glass": "Vetro piastrellato",
|
||||
"block.create.tiled_glass_pane": "Pannello di vetro piastrellato",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "UNLOCALIZED: Tuff Pillar",
|
||||
"block.create.turntable": "Piatto",
|
||||
"block.create.veridium": "UNLOCALIZED: Veridium",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "UNLOCALIZED: Capacity",
|
||||
"enchantment.create.potato_recovery": "UNLOCALIZED: Potato Recovery",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "Contrazione",
|
||||
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
|
||||
"entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "Radiance raffinata",
|
||||
"item.create.rose_quartz": "Quarzo rosa",
|
||||
"item.create.sand_paper": "Carta vetrata",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "Schematica",
|
||||
"item.create.schematic_and_quill": "Schematica e penna d'oca",
|
||||
"item.create.shadow_steel": "Acciaio oscuro",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "Lunghezza",
|
||||
"create.generic.speed": "Velocità",
|
||||
"create.generic.delay": "Ritardo",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "Tick",
|
||||
"create.generic.unit.seconds": "Secondi",
|
||||
"create.generic.unit.minutes": "Minuti",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "RPM",
|
||||
"create.generic.unit.stress": "su",
|
||||
"create.generic.unit.degrees": "°",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "Overflow di oggetti dell'installatore",
|
||||
"create.hint.full_deployer": "Sembra che questo _installatore_ contenga _oggetti_ _eccessivi_ che necessitano di essere _estratti_. Usa una _tramoggia_, un _imbuto_ o altro per liberarlo dall'overflow.",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "Ciao :)",
|
||||
"create.gui.config.overlay2": "Questo overlay è di esempio",
|
||||
"create.gui.config.overlay3": "Cliccalo o trascinalo col mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 4",
|
||||
"_": "Missing Localizations: 68",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "歯車",
|
||||
"block.create.content_observer": "コンテンツオブザーバー",
|
||||
"block.create.controller_rail": "コントローラーレール",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "銅のバックタンク",
|
||||
"block.create.copper_casing": "銅ケーシング",
|
||||
"block.create.copper_shingle_slab": "銅の屋根板のハーフブロック",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "アイテム保管庫",
|
||||
"block.create.jungle_window": "ジャングルの窓",
|
||||
"block.create.jungle_window_pane": "ジャングルの板窓",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "大きな歯車",
|
||||
"block.create.layered_andesite": "安山岩の組石",
|
||||
"block.create.layered_asurine": "瑠璃岩の組石",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "小さな瑠璃岩レンガの階段",
|
||||
"block.create.small_asurine_brick_wall": "小さな瑠璃岩レンガの塀",
|
||||
"block.create.small_asurine_bricks": "小さな瑠璃岩レンガ",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "小さな方解石レンガのハーフブロック",
|
||||
"block.create.small_calcite_brick_stairs": "小さな方解石レンガの階段",
|
||||
"block.create.small_calcite_brick_wall": "小さな方解石レンガの塀",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "応力メーター",
|
||||
"block.create.tiled_glass": "タイルガラス",
|
||||
"block.create.tiled_glass_pane": "タイル板ガラス",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "凝灰岩の柱",
|
||||
"block.create.turntable": "ターンテーブル",
|
||||
"block.create.veridium": "翡翠岩",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "容量増加",
|
||||
"enchantment.create.potato_recovery": "ポテト回収",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "からくり",
|
||||
"entity.create.crafting_blueprint": "クラフトブループリント",
|
||||
"entity.create.gantry_contraption": "ガントリーからくり",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "高貴な光輝",
|
||||
"item.create.rose_quartz": "ローズクォーツ",
|
||||
"item.create.sand_paper": "紙やすり",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "概略図",
|
||||
"item.create.schematic_and_quill": "概略図と羽根ペン",
|
||||
"item.create.shadow_steel": "シャドウスチール",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "長さ",
|
||||
"create.generic.speed": "回転速度",
|
||||
"create.generic.delay": "遅延",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "ティック",
|
||||
"create.generic.unit.seconds": "秒",
|
||||
"create.generic.unit.minutes": "分",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "RPM",
|
||||
"create.generic.unit.stress": "su",
|
||||
"create.generic.unit.degrees": "度",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "デプロイヤーのアイテムが溢れています",
|
||||
"create.hint.full_deployer": "この_デプロイヤー_には、_搬出_する必要がある余分なアイテムが含まれています。_ ホッパー_や_漏斗_などの手段を利用して、溢れないようにしてください。",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "やぁ(・∀・)",
|
||||
"create.gui.config.overlay2": "これはオーバーレイのサンプルです",
|
||||
"create.gui.config.overlay3": "マウスでクリックまたはドラッグしてください",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 6",
|
||||
"_": "Missing Localizations: 70",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "톱니바퀴",
|
||||
"block.create.content_observer": "정보 감지기",
|
||||
"block.create.controller_rail": "방향 레일",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "구리 산소통",
|
||||
"block.create.copper_casing": "구리 케이스",
|
||||
"block.create.copper_shingle_slab": "구리 판자 반 블록",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "아이템 금고",
|
||||
"block.create.jungle_window": "정글나무 유리창",
|
||||
"block.create.jungle_window_pane": "정글나무 유리판",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "큰 톱니바퀴",
|
||||
"block.create.layered_andesite": "이어지는 안산암",
|
||||
"block.create.layered_asurine": "이어지는 유리암",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "작은 유리암 벽돌 계단",
|
||||
"block.create.small_asurine_brick_wall": "작은 유리암 벽돌 담장",
|
||||
"block.create.small_asurine_bricks": "작은 유리암 벽돌",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "작은 방해석 벽돌 반 블록",
|
||||
"block.create.small_calcite_brick_stairs": "작은 방해석 벽돌 계단",
|
||||
"block.create.small_calcite_brick_wall": "작은 방해석 벽돌 담장",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "피로도 계측기",
|
||||
"block.create.tiled_glass": "타일 유리",
|
||||
"block.create.tiled_glass_pane": "타일 유리판",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "응회암 기둥",
|
||||
"block.create.turntable": "돌림판",
|
||||
"block.create.veridium": "심록암",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "저장량",
|
||||
"enchantment.create.potato_recovery": "대포알 회수",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "구조물",
|
||||
"entity.create.crafting_blueprint": "조합 청사진",
|
||||
"entity.create.gantry_contraption": "갠트리 구조물",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "정제된 광채",
|
||||
"item.create.rose_quartz": "장밋빛 석영",
|
||||
"item.create.sand_paper": "사포",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "청사진",
|
||||
"item.create.schematic_and_quill": "청사진과 깃펜",
|
||||
"item.create.shadow_steel": "그림자 강철",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "길이",
|
||||
"create.generic.speed": "속도",
|
||||
"create.generic.delay": "딜레이",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "틱",
|
||||
"create.generic.unit.seconds": "초",
|
||||
"create.generic.unit.minutes": "분",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "RPM",
|
||||
"create.generic.unit.stress": "su",
|
||||
"create.generic.unit.degrees": "°",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "기계 손 아이템 과적",
|
||||
"create.hint.full_deployer": "이 _기계 손_은 _배출_할 아이템을 가지고 있습니다. 호퍼 , 퍼널 등을 이용해 아이템을 빼내세요.",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "Hi :)",
|
||||
"create.gui.config.overlay2": "This is a sample overlay",
|
||||
"create.gui.config.overlay3": "Click or drag with your mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1938",
|
||||
"_": "Missing Localizations: 2002",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "Tandwiel",
|
||||
"block.create.content_observer": "UNLOCALIZED: Content Observer",
|
||||
"block.create.controller_rail": "UNLOCALIZED: Controller Rail",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "UNLOCALIZED: Copper Backtank",
|
||||
"block.create.copper_casing": "UNLOCALIZED: Copper Casing",
|
||||
"block.create.copper_shingle_slab": "UNLOCALIZED: Copper Shingle Slab",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "UNLOCALIZED: Item Vault",
|
||||
"block.create.jungle_window": "UNLOCALIZED: Jungle Window",
|
||||
"block.create.jungle_window_pane": "UNLOCALIZED: Jungle Window Pane",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "Groot Tandwiel",
|
||||
"block.create.layered_andesite": "UNLOCALIZED: Layered Andesite",
|
||||
"block.create.layered_asurine": "UNLOCALIZED: Layered Asurine",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "UNLOCALIZED: Small Asurine Brick Stairs",
|
||||
"block.create.small_asurine_brick_wall": "UNLOCALIZED: Small Asurine Brick Wall",
|
||||
"block.create.small_asurine_bricks": "UNLOCALIZED: Small Asurine Bricks",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "UNLOCALIZED: Small Calcite Brick Slab",
|
||||
"block.create.small_calcite_brick_stairs": "UNLOCALIZED: Small Calcite Brick Stairs",
|
||||
"block.create.small_calcite_brick_wall": "UNLOCALIZED: Small Calcite Brick Wall",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "Stressmeter",
|
||||
"block.create.tiled_glass": "Getegeld Glas",
|
||||
"block.create.tiled_glass_pane": "Getegeld Glazen Paneel",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "UNLOCALIZED: Tuff Pillar",
|
||||
"block.create.turntable": "Draaischijf",
|
||||
"block.create.veridium": "UNLOCALIZED: Veridium",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "UNLOCALIZED: Capacity",
|
||||
"enchantment.create.potato_recovery": "UNLOCALIZED: Potato Recovery",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "UNLOCALIZED: Contraption",
|
||||
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
|
||||
"entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "UNLOCALIZED: Refined Radiance",
|
||||
"item.create.rose_quartz": "Roze Kwarts",
|
||||
"item.create.sand_paper": "UNLOCALIZED: Sand Paper",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "Bouwtekening",
|
||||
"item.create.schematic_and_quill": "Bouwtekening en Veer",
|
||||
"item.create.shadow_steel": "UNLOCALIZED: Shadow Steel",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "UNLOCALIZED: Length",
|
||||
"create.generic.speed": "Snelheid",
|
||||
"create.generic.delay": "Vertraging",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "Ticks",
|
||||
"create.generic.unit.seconds": "Seconden",
|
||||
"create.generic.unit.minutes": "Minuten",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "UNLOCALIZED: RPM",
|
||||
"create.generic.unit.stress": "UNLOCALIZED: su",
|
||||
"create.generic.unit.degrees": "UNLOCALIZED: °",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "UNLOCALIZED: Deployer Item Overflow",
|
||||
"create.hint.full_deployer": "UNLOCALIZED: It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "UNLOCALIZED: Hi :)",
|
||||
"create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay",
|
||||
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 373",
|
||||
"_": "Missing Localizations: 437",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "Koło zębate",
|
||||
"block.create.content_observer": "Detektor zawartości",
|
||||
"block.create.controller_rail": "Tory sterujące",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "Miedziany zbiornik w plecaku",
|
||||
"block.create.copper_casing": "Miedziana Obudowa",
|
||||
"block.create.copper_shingle_slab": "UNLOCALIZED: Copper Shingle Slab",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "UNLOCALIZED: Item Vault",
|
||||
"block.create.jungle_window": "Dżunglowe okno",
|
||||
"block.create.jungle_window_pane": "Dżunglowa szyba okienna",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "Duże koło zębate",
|
||||
"block.create.layered_andesite": "Warstwowy andezyt",
|
||||
"block.create.layered_asurine": "UNLOCALIZED: Layered Asurine",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "UNLOCALIZED: Small Asurine Brick Stairs",
|
||||
"block.create.small_asurine_brick_wall": "UNLOCALIZED: Small Asurine Brick Wall",
|
||||
"block.create.small_asurine_bricks": "UNLOCALIZED: Small Asurine Bricks",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "UNLOCALIZED: Small Calcite Brick Slab",
|
||||
"block.create.small_calcite_brick_stairs": "UNLOCALIZED: Small Calcite Brick Stairs",
|
||||
"block.create.small_calcite_brick_wall": "UNLOCALIZED: Small Calcite Brick Wall",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "Miernik obciążenia",
|
||||
"block.create.tiled_glass": "Kafelkowane szkło",
|
||||
"block.create.tiled_glass_pane": "Kafelkowana szyba",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "UNLOCALIZED: Tuff Pillar",
|
||||
"block.create.turntable": "Talerz obrotowy",
|
||||
"block.create.veridium": "UNLOCALIZED: Veridium",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "Pojameność",
|
||||
"enchantment.create.potato_recovery": "Odzyskiwanie",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "Maszyna",
|
||||
"entity.create.crafting_blueprint": "Szablon konstruowania",
|
||||
"entity.create.gantry_contraption": "Maszyna suwnicowa",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "Świetlisty materiał",
|
||||
"item.create.rose_quartz": "Różowy kwarc",
|
||||
"item.create.sand_paper": "Papier ścierny",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "Schemat",
|
||||
"item.create.schematic_and_quill": "Schemat z piórem",
|
||||
"item.create.shadow_steel": "Mroczna stal",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "Długość",
|
||||
"create.generic.speed": "Prędkość",
|
||||
"create.generic.delay": "Opóźnienie",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "Tiki",
|
||||
"create.generic.unit.seconds": "Sekundy",
|
||||
"create.generic.unit.minutes": "Minuty",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "Ob/min",
|
||||
"create.generic.unit.stress": "JO",
|
||||
"create.generic.unit.degrees": "°",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "Nadmiar przedmiotów w aplikatorze",
|
||||
"create.hint.full_deployer": "Wygląda na to, że ten _aplikator_ zawiera _nadmiar_ _przedmiotów_, które muszą zostać _wyciągnięte_. Użyj _leji_, _lejków_ lub innych sposobów, aby uwolnić od przepełnienia.",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "Cześć :)",
|
||||
"create.gui.config.overlay2": "To jest przykładowa nakładka",
|
||||
"create.gui.config.overlay3": "Kliknij lub przeciągnij myszką",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1557",
|
||||
"_": "Missing Localizations: 1621",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "Roda Dentada",
|
||||
"block.create.content_observer": "Observador de Conteúdo",
|
||||
"block.create.controller_rail": "Trilho Controlador",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "Tanque Traseiro de Cobre",
|
||||
"block.create.copper_casing": "Revestimento de Cobre",
|
||||
"block.create.copper_shingle_slab": "UNLOCALIZED: Copper Shingle Slab",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "Cofre de itens",
|
||||
"block.create.jungle_window": "UNLOCALIZED: Jungle Window",
|
||||
"block.create.jungle_window_pane": "UNLOCALIZED: Jungle Window Pane",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "UNLOCALIZED: Large Cogwheel",
|
||||
"block.create.layered_andesite": "UNLOCALIZED: Layered Andesite",
|
||||
"block.create.layered_asurine": "UNLOCALIZED: Layered Asurine",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "UNLOCALIZED: Small Asurine Brick Stairs",
|
||||
"block.create.small_asurine_brick_wall": "UNLOCALIZED: Small Asurine Brick Wall",
|
||||
"block.create.small_asurine_bricks": "UNLOCALIZED: Small Asurine Bricks",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "UNLOCALIZED: Small Calcite Brick Slab",
|
||||
"block.create.small_calcite_brick_stairs": "UNLOCALIZED: Small Calcite Brick Stairs",
|
||||
"block.create.small_calcite_brick_wall": "UNLOCALIZED: Small Calcite Brick Wall",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "Estressómetro",
|
||||
"block.create.tiled_glass": "Vidro Entalhado",
|
||||
"block.create.tiled_glass_pane": "Vidraça Entalhada",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "UNLOCALIZED: Tuff Pillar",
|
||||
"block.create.turntable": "Mesa giratória",
|
||||
"block.create.veridium": "UNLOCALIZED: Veridium",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "Capacidade",
|
||||
"enchantment.create.potato_recovery": "Recuperação de Batata",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "Engenhoca",
|
||||
"entity.create.crafting_blueprint": "Esquema de Fabricação",
|
||||
"entity.create.gantry_contraption": "Engenhoca de Pórticolo",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "Luz Refinada",
|
||||
"item.create.rose_quartz": "Quartzo Rosa",
|
||||
"item.create.sand_paper": "Lixa",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "Esquema",
|
||||
"item.create.schematic_and_quill": "Esquema e pena",
|
||||
"item.create.shadow_steel": "Aço sombrio",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "Comprimento",
|
||||
"create.generic.speed": "Velocidade",
|
||||
"create.generic.delay": "Demorada",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "Ticks",
|
||||
"create.generic.unit.seconds": "Segundos",
|
||||
"create.generic.unit.minutes": "Minutos",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "RPM",
|
||||
"create.generic.unit.stress": "us",
|
||||
"create.generic.unit.degrees": "°",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "UNLOCALIZED: Deployer Item Overflow",
|
||||
"create.hint.full_deployer": "UNLOCALIZED: It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "UNLOCALIZED: Hi :)",
|
||||
"create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay",
|
||||
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1557",
|
||||
"_": "Missing Localizations: 1621",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "Roda Dentada",
|
||||
"block.create.content_observer": "Observador de Conteúdo",
|
||||
"block.create.controller_rail": "Trilho Controlador",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "Tanque Traseiro de Cobre",
|
||||
"block.create.copper_casing": "Revestimento de Cobre",
|
||||
"block.create.copper_shingle_slab": "UNLOCALIZED: Copper Shingle Slab",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "Cofre de itens",
|
||||
"block.create.jungle_window": "UNLOCALIZED: Jungle Window",
|
||||
"block.create.jungle_window_pane": "UNLOCALIZED: Jungle Window Pane",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "UNLOCALIZED: Large Cogwheel",
|
||||
"block.create.layered_andesite": "UNLOCALIZED: Layered Andesite",
|
||||
"block.create.layered_asurine": "UNLOCALIZED: Layered Asurine",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "UNLOCALIZED: Small Asurine Brick Stairs",
|
||||
"block.create.small_asurine_brick_wall": "UNLOCALIZED: Small Asurine Brick Wall",
|
||||
"block.create.small_asurine_bricks": "UNLOCALIZED: Small Asurine Bricks",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "UNLOCALIZED: Small Calcite Brick Slab",
|
||||
"block.create.small_calcite_brick_stairs": "UNLOCALIZED: Small Calcite Brick Stairs",
|
||||
"block.create.small_calcite_brick_wall": "UNLOCALIZED: Small Calcite Brick Wall",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "Estressómetro",
|
||||
"block.create.tiled_glass": "Vidro Entalhado",
|
||||
"block.create.tiled_glass_pane": "Vidraça Entalhada",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "UNLOCALIZED: Tuff Pillar",
|
||||
"block.create.turntable": "Mesa giratória",
|
||||
"block.create.veridium": "UNLOCALIZED: Veridium",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "Capacidade",
|
||||
"enchantment.create.potato_recovery": "Recuperação de Batata",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "Engenhoca",
|
||||
"entity.create.crafting_blueprint": "Esquema de Fabricação",
|
||||
"entity.create.gantry_contraption": "Engenhoca de Pórticolo",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "Luz Refinada",
|
||||
"item.create.rose_quartz": "Quartzo Rosa",
|
||||
"item.create.sand_paper": "Lixa",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "Esquema",
|
||||
"item.create.schematic_and_quill": "Esquema e pena",
|
||||
"item.create.shadow_steel": "Aço sombrio",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "Comprimento",
|
||||
"create.generic.speed": "Velocidade",
|
||||
"create.generic.delay": "Demorada",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "Ticks",
|
||||
"create.generic.unit.seconds": "Segundos",
|
||||
"create.generic.unit.minutes": "Minutos",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "RPM",
|
||||
"create.generic.unit.stress": "us",
|
||||
"create.generic.unit.degrees": "°",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "UNLOCALIZED: Deployer Item Overflow",
|
||||
"create.hint.full_deployer": "UNLOCALIZED: It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "UNLOCALIZED: Hi :)",
|
||||
"create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay",
|
||||
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 378",
|
||||
"_": "Missing Localizations: 442",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "Шестерня",
|
||||
"block.create.content_observer": "Наблюдатель за содержимым",
|
||||
"block.create.controller_rail": "Контролирующая рельса",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "Медный баллон",
|
||||
"block.create.copper_casing": "Медный корпус",
|
||||
"block.create.copper_shingle_slab": "UNLOCALIZED: Copper Shingle Slab",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "UNLOCALIZED: Item Vault",
|
||||
"block.create.jungle_window": "Окно из тропического дерева",
|
||||
"block.create.jungle_window_pane": "Панель окна из тропического дерева",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "Большая шестерня",
|
||||
"block.create.layered_andesite": "Слоистый андезит",
|
||||
"block.create.layered_asurine": "UNLOCALIZED: Layered Asurine",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "UNLOCALIZED: Small Asurine Brick Stairs",
|
||||
"block.create.small_asurine_brick_wall": "UNLOCALIZED: Small Asurine Brick Wall",
|
||||
"block.create.small_asurine_bricks": "UNLOCALIZED: Small Asurine Bricks",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "UNLOCALIZED: Small Calcite Brick Slab",
|
||||
"block.create.small_calcite_brick_stairs": "UNLOCALIZED: Small Calcite Brick Stairs",
|
||||
"block.create.small_calcite_brick_wall": "UNLOCALIZED: Small Calcite Brick Wall",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "Стрессометр",
|
||||
"block.create.tiled_glass": "Плиточное стекло",
|
||||
"block.create.tiled_glass_pane": "Плиточная стеклянная панель",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "UNLOCALIZED: Tuff Pillar",
|
||||
"block.create.turntable": "Поворотный стол",
|
||||
"block.create.veridium": "UNLOCALIZED: Veridium",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "Вместимость",
|
||||
"enchantment.create.potato_recovery": "Возобновление картофеля",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "Штуковина",
|
||||
"entity.create.crafting_blueprint": "Создание чертежа",
|
||||
"entity.create.gantry_contraption": "Крановая штуковина",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "Изысканное сияние",
|
||||
"item.create.rose_quartz": "Розовый кварц",
|
||||
"item.create.sand_paper": "Наждачная бумага",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "Схематика",
|
||||
"item.create.schematic_and_quill": "Схематика и перо",
|
||||
"item.create.shadow_steel": "Призрачная сталь",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "Длина",
|
||||
"create.generic.speed": "Скорость",
|
||||
"create.generic.delay": "Задержка",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "тиков",
|
||||
"create.generic.unit.seconds": "секунд",
|
||||
"create.generic.unit.minutes": "минут",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "об./мин.",
|
||||
"create.generic.unit.stress": "ен",
|
||||
"create.generic.unit.degrees": "°",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "Переполнение автономного активатора",
|
||||
"create.hint.full_deployer": "Похоже, этот _автономный активатор_ содержит _лишние_ _предметы_, которые необходимо _извлечь_. Используйте _воронку_ или _другие способы_, чтобы освободить его от переполнения.",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "Привет :)",
|
||||
"create.gui.config.overlay2": "Это образец оверлея",
|
||||
"create.gui.config.overlay3": "Кликни и тащи с помощью мыши",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 4",
|
||||
"_": "Missing Localizations: 68",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "齿轮",
|
||||
"block.create.content_observer": "物品侦测器",
|
||||
"block.create.controller_rail": "控制铁轨",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "铜制背罐",
|
||||
"block.create.copper_casing": "铜机壳",
|
||||
"block.create.copper_shingle_slab": "铜砖块台阶",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "物品保险库",
|
||||
"block.create.jungle_window": "丛林木窗户",
|
||||
"block.create.jungle_window_pane": "丛林木窗户板",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "大齿轮",
|
||||
"block.create.layered_andesite": "层叠安山岩",
|
||||
"block.create.layered_asurine": "层叠皓蓝石",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "皓蓝石小砖块楼梯",
|
||||
"block.create.small_asurine_brick_wall": "皓蓝石小砖块墙",
|
||||
"block.create.small_asurine_bricks": "皓蓝石小砖块",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "方解石小砖块台阶",
|
||||
"block.create.small_calcite_brick_stairs": "方解石小砖块楼梯",
|
||||
"block.create.small_calcite_brick_wall": "方解石小砖块墙",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "应力表",
|
||||
"block.create.tiled_glass": "十字玻璃窗",
|
||||
"block.create.tiled_glass_pane": "十字玻璃窗户板",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "凝灰岩柱",
|
||||
"block.create.turntable": "转盘",
|
||||
"block.create.veridium": "辉绿矿",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "扩容",
|
||||
"enchantment.create.potato_recovery": "土豆回收",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "装置",
|
||||
"entity.create.crafting_blueprint": "合成蓝图",
|
||||
"entity.create.gantry_contraption": "起重机装置",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "光辉石",
|
||||
"item.create.rose_quartz": "玫瑰石英",
|
||||
"item.create.sand_paper": "砂纸",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "蓝图",
|
||||
"item.create.schematic_and_quill": "蓝图与笔",
|
||||
"item.create.shadow_steel": "暗影钢",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "长度",
|
||||
"create.generic.speed": "速度",
|
||||
"create.generic.delay": "延时",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "Ticks",
|
||||
"create.generic.unit.seconds": "秒",
|
||||
"create.generic.unit.minutes": "分钟",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "RPM",
|
||||
"create.generic.unit.stress": "su",
|
||||
"create.generic.unit.degrees": "°",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "机械手物品溢出",
|
||||
"create.hint.full_deployer": "_机械手_包含_过剩的物品,_需要被_提取。你需要_使用_料斗,__漏斗_或其他方法将溢出释放出来。",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "Hi :)",
|
||||
"create.gui.config.overlay2": "这是一个实例层",
|
||||
"create.gui.config.overlay3": "点击拖拽你的鼠标",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 392",
|
||||
"_": "Missing Localizations: 456",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
|||
"block.create.cogwheel": "齒輪",
|
||||
"block.create.content_observer": "物品偵測器",
|
||||
"block.create.controller_rail": "控制鐵軌",
|
||||
"block.create.controls": "UNLOCALIZED: Controls",
|
||||
"block.create.copper_backtank": "銅製後背包",
|
||||
"block.create.copper_casing": "銅機殼",
|
||||
"block.create.copper_shingle_slab": "UNLOCALIZED: Copper Shingle Slab",
|
||||
|
@ -240,6 +241,7 @@
|
|||
"block.create.item_vault": "UNLOCALIZED: Item Vault",
|
||||
"block.create.jungle_window": "叢林木窗戶",
|
||||
"block.create.jungle_window_pane": "叢林木窗戶片",
|
||||
"block.create.large_bogey": "UNLOCALIZED: Large Bogey",
|
||||
"block.create.large_cogwheel": "大齒輪",
|
||||
"block.create.layered_andesite": "疊層安山岩",
|
||||
"block.create.layered_asurine": "UNLOCALIZED: Layered Asurine",
|
||||
|
@ -421,6 +423,7 @@
|
|||
"block.create.small_asurine_brick_stairs": "UNLOCALIZED: Small Asurine Brick Stairs",
|
||||
"block.create.small_asurine_brick_wall": "UNLOCALIZED: Small Asurine Brick Wall",
|
||||
"block.create.small_asurine_bricks": "UNLOCALIZED: Small Asurine Bricks",
|
||||
"block.create.small_bogey": "UNLOCALIZED: Small Bogey",
|
||||
"block.create.small_calcite_brick_slab": "UNLOCALIZED: Small Calcite Brick Slab",
|
||||
"block.create.small_calcite_brick_stairs": "UNLOCALIZED: Small Calcite Brick Stairs",
|
||||
"block.create.small_calcite_brick_wall": "UNLOCALIZED: Small Calcite Brick Wall",
|
||||
|
@ -481,6 +484,8 @@
|
|||
"block.create.stressometer": "動能錶",
|
||||
"block.create.tiled_glass": "十字玻璃窗",
|
||||
"block.create.tiled_glass_pane": "十字玻璃窗戶片",
|
||||
"block.create.track": "UNLOCALIZED: Track",
|
||||
"block.create.track_station": "UNLOCALIZED: Track Station",
|
||||
"block.create.tuff_pillar": "UNLOCALIZED: Tuff Pillar",
|
||||
"block.create.turntable": "轉盤",
|
||||
"block.create.veridium": "UNLOCALIZED: Veridium",
|
||||
|
@ -539,6 +544,7 @@
|
|||
"enchantment.create.capacity": "容量",
|
||||
"enchantment.create.potato_recovery": "馬鈴薯恢復",
|
||||
|
||||
"entity.create.carriage_contraption": "UNLOCALIZED: Carriage Contraption",
|
||||
"entity.create.contraption": "結構",
|
||||
"entity.create.crafting_blueprint": "合成藍圖",
|
||||
"entity.create.gantry_contraption": "門式結構",
|
||||
|
@ -617,6 +623,7 @@
|
|||
"item.create.refined_radiance": "光輝石",
|
||||
"item.create.rose_quartz": "玫瑰石英",
|
||||
"item.create.sand_paper": "砂紙",
|
||||
"item.create.schedule": "UNLOCALIZED: Schedule",
|
||||
"item.create.schematic": "藍圖",
|
||||
"item.create.schematic_and_quill": "藍圖與筆",
|
||||
"item.create.shadow_steel": "暗影鋼",
|
||||
|
@ -864,9 +871,15 @@
|
|||
"create.generic.length": "長",
|
||||
"create.generic.speed": "速度",
|
||||
"create.generic.delay": "延時",
|
||||
"create.generic.duration": "UNLOCALIZED: Duration",
|
||||
"create.generic.timeUnit": "UNLOCALIZED: Time Unit",
|
||||
"create.generic.unit.ticks": "Ticks",
|
||||
"create.generic.unit.seconds": "秒",
|
||||
"create.generic.unit.minutes": "分",
|
||||
"create.generic.daytime.hour": "UNLOCALIZED: Hour",
|
||||
"create.generic.daytime.minute": "UNLOCALIZED: Minute",
|
||||
"create.generic.daytime.pm": "UNLOCALIZED: pm",
|
||||
"create.generic.daytime.am": "UNLOCALIZED: am",
|
||||
"create.generic.unit.rpm": "RPM",
|
||||
"create.generic.unit.stress": "su",
|
||||
"create.generic.unit.degrees": "度",
|
||||
|
@ -1310,6 +1323,60 @@
|
|||
"create.hint.full_deployer.title": "機械手物品溢出",
|
||||
"create.hint.full_deployer": "_機械手_包含_過剩的物品_需要被_取出._使用漏斗_或其他方法將溢出解決。",
|
||||
|
||||
"create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit",
|
||||
"create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove",
|
||||
"create.gui.schedule.duplicate": "UNLOCALIZED: Duplicate",
|
||||
"create.gui.schedule.remove_entry": "UNLOCALIZED: Remove Stop",
|
||||
"create.gui.schedule.add_entry": "UNLOCALIZED: Add Stop",
|
||||
"create.gui.schedule.move_up": "UNLOCALIZED: Move up",
|
||||
"create.gui.schedule.move_down": "UNLOCALIZED: Move down",
|
||||
"create.gui.schedule.add_condition": "UNLOCALIZED: Add Condition",
|
||||
"create.gui.schedule.alternative_condition": "UNLOCALIZED: Alternative Condition",
|
||||
|
||||
"create.schedule.destination_type": "UNLOCALIZED: Next Stop:",
|
||||
"create.schedule.destination.editor": "UNLOCALIZED: Destination Editor",
|
||||
"create.schedule.destination.filtered": "UNLOCALIZED: Specific Station",
|
||||
"create.schedule.destination.filtered_matching": "UNLOCALIZED: Station: %1$s",
|
||||
"create.schedule.destination.filter": "UNLOCALIZED: Station Name",
|
||||
"create.schedule.destination.filter_2": "UNLOCALIZED: Use * as a text wildcard",
|
||||
"create.schedule.destination.filter_3": "UNLOCALIZED: Example: 'My Station, Platform *'",
|
||||
"create.schedule.destination.filter_4": "UNLOCALIZED: Train picks nearest unoccupied match",
|
||||
"create.schedule.destination.nearest": "UNLOCALIZED: Nearest Station",
|
||||
"create.schedule.destination.redstone": "UNLOCALIZED: Station with Redstone Pulse",
|
||||
"create.schedule.condition_type": "UNLOCALIZED: Continue when:",
|
||||
"create.schedule.condition.editor": "UNLOCALIZED: Condition Editor",
|
||||
"create.schedule.condition.delay": "UNLOCALIZED: Scheduled Delay",
|
||||
"create.schedule.condition.delay_short": "UNLOCALIZED: Wait: %1$s",
|
||||
"create.schedule.condition.idle": "UNLOCALIZED: Cargo Inactivity",
|
||||
"create.schedule.condition.idle_short": "UNLOCALIZED: Cargo Idle: %1$s",
|
||||
"create.schedule.condition.for_x_time": "UNLOCALIZED: for %1$s",
|
||||
"create.schedule.condition.unloaded": "UNLOCALIZED: Chunk Unloaded",
|
||||
"create.schedule.condition.powered": "UNLOCALIZED: Station Powered",
|
||||
"create.schedule.condition.time_of_day": "UNLOCALIZED: Time of Day",
|
||||
"create.schedule.condition.time_of_day.scheduled": "UNLOCALIZED: Scheduled Time: %1$s",
|
||||
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
|
||||
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
|
||||
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
|
||||
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s",
|
||||
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than",
|
||||
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
|
||||
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
|
||||
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
|
||||
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
|
||||
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
|
||||
"create.schedule.condition.threshold.items": "UNLOCALIZED: Items",
|
||||
"create.schedule.condition.threshold.stacks": "UNLOCALIZED: Stacks",
|
||||
"create.schedule.condition.threshold.buckets": "UNLOCALIZED: Buckets",
|
||||
"create.schedule.condition.threshold.place_item": "UNLOCALIZED: Reference Item",
|
||||
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
|
||||
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
|
||||
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
|
||||
"create.schedule.loop": "UNLOCALIZED: Loop Forever",
|
||||
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
|
||||
"create.schedule.loop2": "UNLOCALIZED: when completed",
|
||||
|
||||
"create.train.unnamed": "UNLOCALIZED: Unnamed Train",
|
||||
|
||||
"create.gui.config.overlay1": "嗨 :)",
|
||||
"create.gui.config.overlay2": "這是一個實例層",
|
||||
"create.gui.config.overlay3": "點擊拖拽你的滑鼠",
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "create:block/controls/item"
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "create:item/schedule"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "create:item/track"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "create:block/track_station/block"
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1.0,
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "create:controls"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1.0,
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:air"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1.0,
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:air"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1.0,
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "create:track"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1.0,
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "create:track_station"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -96,6 +96,7 @@
|
|||
"create:flywheel",
|
||||
"create:rotation_speed_controller",
|
||||
"create:mechanical_arm",
|
||||
"create:track_station",
|
||||
"create:content_observer",
|
||||
"create:stockpile_switch",
|
||||
"create:creative_crate",
|
||||
|
|
|
@ -104,6 +104,8 @@
|
|||
"create:furnace_engine",
|
||||
"create:rotation_speed_controller",
|
||||
"create:mechanical_arm",
|
||||
"create:track",
|
||||
"create:track_station",
|
||||
"create:item_vault",
|
||||
"create:andesite_funnel",
|
||||
"create:andesite_belt_funnel",
|
||||
|
|
|
@ -17,8 +17,7 @@ public class AllBlockPartials {
|
|||
|
||||
public static final PartialModel
|
||||
|
||||
SCHEMATICANNON_CONNECTOR = block("schematicannon/connector"),
|
||||
SCHEMATICANNON_PIPE = block("schematicannon/pipe"),
|
||||
SCHEMATICANNON_CONNECTOR = block("schematicannon/connector"), SCHEMATICANNON_PIPE = block("schematicannon/pipe"),
|
||||
|
||||
SHAFTLESS_COGWHEEL = block("cogwheel_shaftless"), SHAFTLESS_LARGE_COGWHEEL = block("large_cogwheel_shaftless"),
|
||||
COGWHEEL_SHAFT = block("cogwheel_shaft"), SHAFT_HALF = block("shaft_half"),
|
||||
|
@ -31,7 +30,8 @@ public class AllBlockPartials {
|
|||
|
||||
ENCASED_FAN_INNER = block("encased_fan/propeller"), HAND_CRANK_HANDLE = block("hand_crank/handle"),
|
||||
MECHANICAL_PRESS_HEAD = block("mechanical_press/head"), MECHANICAL_MIXER_POLE = block("mechanical_mixer/pole"),
|
||||
MECHANICAL_MIXER_HEAD = block("mechanical_mixer/head"), MECHANICAL_CRAFTER_LID = block("mechanical_crafter/lid"),
|
||||
MECHANICAL_MIXER_HEAD = block("mechanical_mixer/head"),
|
||||
MECHANICAL_CRAFTER_LID = block("mechanical_crafter/lid"),
|
||||
MECHANICAL_CRAFTER_ARROW = block("mechanical_crafter/arrow"),
|
||||
MECHANICAL_CRAFTER_BELT_FRAME = block("mechanical_crafter/belt"),
|
||||
MECHANICAL_CRAFTER_BELT = block("mechanical_crafter/belt_animated"),
|
||||
|
@ -45,7 +45,8 @@ public class AllBlockPartials {
|
|||
GAUGE_HEAD_STRESS = block("gauge/stressometer/head"), BEARING_TOP = block("bearing/top"),
|
||||
BEARING_TOP_WOODEN = block("bearing/top_wooden"), DRILL_HEAD = block("mechanical_drill/head"),
|
||||
HARVESTER_BLADE = block("mechanical_harvester/blade"), DEPLOYER_POLE = block("deployer/pole"),
|
||||
DEPLOYER_HAND_POINTING = block("deployer/hand_pointing"), DEPLOYER_HAND_PUNCHING = block("deployer/hand_punching"),
|
||||
DEPLOYER_HAND_POINTING = block("deployer/hand_pointing"),
|
||||
DEPLOYER_HAND_PUNCHING = block("deployer/hand_punching"),
|
||||
DEPLOYER_HAND_HOLDING = block("deployer/hand_holding"), ANALOG_LEVER_HANDLE = block("analog_lever/handle"),
|
||||
ANALOG_LEVER_INDICATOR = block("analog_lever/indicator"), FUNNEL_FLAP = block("funnel/flap"),
|
||||
BELT_FUNNEL_FLAP = block("belt_funnel/flap"), BELT_TUNNEL_FLAP = block("belt_tunnel/flap"),
|
||||
|
@ -109,20 +110,43 @@ public class AllBlockPartials {
|
|||
|
||||
COPPER_BACKTANK_SHAFT = block("copper_backtank/block_shaft_input"),
|
||||
COPPER_BACKTANK_COGS = block("copper_backtank/block_cogs"),
|
||||
|
||||
TRACK_SEGMENT_LEFT = block("track/segment_left"),
|
||||
TRACK_SEGMENT_RIGHT = block("track/segment_right"),
|
||||
TRACK_TIE = block("track/tie"),
|
||||
|
||||
TRACK_STATION_OVERLAY = block("track/station_overlay"),
|
||||
TRACK_STATION_OVERLAY_DIAGONAL = block("track/station_overlay_diagonal"),
|
||||
TRACK_STATION_OVERLAY_ASCENDING = block("track/station_overlay_ascending"),
|
||||
TRACK_ASSEMBLY_OVERLAY = block("track/assembly_overlay"),
|
||||
|
||||
BOGEY_FRAME = block("track/bogey/bogey_frame"),
|
||||
SMALL_BOGEY_WHEELS = block("track/bogey/bogey_wheel"),
|
||||
BOGEY_PIN = block("track/bogey/bogey_drive_wheel_pin"),
|
||||
BOGEY_PISTON = block("track/bogey/bogey_drive_piston"),
|
||||
BOGEY_DRIVE = block("track/bogey/bogey_drive"),
|
||||
LARGE_BOGEY_WHEELS = block("track/bogey/bogey_drive_wheel"),
|
||||
|
||||
TRAIN_COUPLING_HEAD = block("track/bogey/coupling_head"),
|
||||
TRAIN_COUPLING_CABLE = block("track/bogey/coupling_cable"),
|
||||
|
||||
TRAIN_CONTROLS_COVER = block("controls/train/cover"),
|
||||
TRAIN_CONTROLS_LEVER = block("controls/train/lever"),
|
||||
|
||||
CRAFTING_BLUEPRINT_1x1 = entity("crafting_blueprint_small"),
|
||||
CRAFTING_BLUEPRINT_2x2 = entity("crafting_blueprint_medium"),
|
||||
CRAFTING_BLUEPRINT_3x3 = entity("crafting_blueprint_large"),
|
||||
|
||||
COUPLING_ATTACHMENT = entity("minecart_coupling/attachment"),
|
||||
COUPLING_RING = entity("minecart_coupling/ring"),
|
||||
|
||||
COUPLING_ATTACHMENT = entity("minecart_coupling/attachment"), COUPLING_RING = entity("minecart_coupling/ring"),
|
||||
COUPLING_CONNECTOR = entity("minecart_coupling/connector")
|
||||
|
||||
;
|
||||
|
||||
public static final Map<FluidTransportBehaviour.AttachmentTypes, Map<Direction, PartialModel>> PIPE_ATTACHMENTS =
|
||||
new EnumMap<>(FluidTransportBehaviour.AttachmentTypes.class);
|
||||
public static final Map<BlazeBurnerBlock.HeatLevel, PartialModel> BLAZES = new EnumMap<>(BlazeBurnerBlock.HeatLevel.class);
|
||||
|
||||
public static final Map<BlazeBurnerBlock.HeatLevel, PartialModel> BLAZES =
|
||||
new EnumMap<>(BlazeBurnerBlock.HeatLevel.class);
|
||||
public static final Map<DyeColor, PartialModel> TOOLBOX_LIDS = new EnumMap<>(DyeColor.class);
|
||||
|
||||
static {
|
||||
|
|
|
@ -58,6 +58,8 @@ import com.simibubi.create.content.contraptions.components.structureMovement.cha
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.RadialChassisBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsMovementBehaviour;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock.MinecartAnchorBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlockItem;
|
||||
|
@ -161,6 +163,13 @@ import com.simibubi.create.content.logistics.block.vault.ItemVaultBlock;
|
|||
import com.simibubi.create.content.logistics.block.vault.ItemVaultCTBehaviour;
|
||||
import com.simibubi.create.content.logistics.block.vault.ItemVaultItem;
|
||||
import com.simibubi.create.content.logistics.item.LecternControllerBlock;
|
||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
||||
import com.simibubi.create.content.logistics.trains.management.StationBlock;
|
||||
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBlockItem;
|
||||
import com.simibubi.create.content.logistics.trains.track.StandardBogeyBlock;
|
||||
import com.simibubi.create.content.logistics.trains.track.TrackBlock;
|
||||
import com.simibubi.create.content.logistics.trains.track.TrackBlockItem;
|
||||
import com.simibubi.create.content.logistics.trains.track.TrackBlockStateGenerator;
|
||||
import com.simibubi.create.content.schematics.block.SchematicTableBlock;
|
||||
import com.simibubi.create.content.schematics.block.SchematicannonBlock;
|
||||
import com.simibubi.create.foundation.block.BlockStressDefaults;
|
||||
|
@ -304,14 +313,14 @@ public class AllBlocks {
|
|||
.transform(axeOrPickaxe())
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<EncasedCogwheelBlock> ANDESITE_ENCASED_COGWHEEL =
|
||||
REGISTRATE.block("andesite_encased_cogwheel", p -> EncasedCogwheelBlock.andesite(false, p))
|
||||
.transform(BuilderTransformers.encasedCogwheel("andesite", () -> AllSpriteShifts.ANDESITE_CASING))
|
||||
.onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCogCTBehaviour(AllSpriteShifts.ANDESITE_CASING,
|
||||
Couple.create(AllSpriteShifts.ANDESITE_ENCASED_COGWHEEL_SIDE,
|
||||
AllSpriteShifts.ANDESITE_ENCASED_COGWHEEL_OTHERSIDE))))
|
||||
.transform(axeOrPickaxe())
|
||||
.register();
|
||||
public static final BlockEntry<EncasedCogwheelBlock> ANDESITE_ENCASED_COGWHEEL = REGISTRATE
|
||||
.block("andesite_encased_cogwheel", p -> EncasedCogwheelBlock.andesite(false, p))
|
||||
.transform(BuilderTransformers.encasedCogwheel("andesite", () -> AllSpriteShifts.ANDESITE_CASING))
|
||||
.onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCogCTBehaviour(AllSpriteShifts.ANDESITE_CASING,
|
||||
Couple.create(AllSpriteShifts.ANDESITE_ENCASED_COGWHEEL_SIDE,
|
||||
AllSpriteShifts.ANDESITE_ENCASED_COGWHEEL_OTHERSIDE))))
|
||||
.transform(axeOrPickaxe())
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<EncasedCogwheelBlock> BRASS_ENCASED_COGWHEEL =
|
||||
REGISTRATE.block("brass_encased_cogwheel", p -> EncasedCogwheelBlock.brass(false, p))
|
||||
|
@ -1247,6 +1256,53 @@ public class AllBlocks {
|
|||
.transform(customItemModel())
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<TrackBlock> TRACK = REGISTRATE.block("track", TrackBlock::new)
|
||||
.initialProperties(() -> Blocks.RAIL)
|
||||
.addLayer(() -> RenderType::cutoutMipped)
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate(new TrackBlockStateGenerator()::generate)
|
||||
.item(TrackBlockItem::new)
|
||||
.model((c, p) -> p.generated(c, Create.asResource("item/" + c.getName())))
|
||||
.build()
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<StationBlock> TRACK_STATION = REGISTRATE.block("track_station", StationBlock::new)
|
||||
.initialProperties(SharedProperties::wooden)
|
||||
.transform(axeOrPickaxe())
|
||||
.blockstate((c, p) -> p.horizontalBlock(c.get(),
|
||||
s -> s.getValue(StationBlock.ASSEMBLING) ? AssetLookup.partialBaseModel(c, p, "assembling")
|
||||
: AssetLookup.partialBaseModel(c, p)))
|
||||
.item(TrackTargetingBlockItem::new)
|
||||
.transform(customItemModel("_", "block"))
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<StandardBogeyBlock> SMALL_BOGEY =
|
||||
REGISTRATE.block("small_bogey", p -> new StandardBogeyBlock(p, false))
|
||||
.initialProperties(SharedProperties::softMetal)
|
||||
.properties(p -> p.noOcclusion())
|
||||
.blockstate((c, p) -> BlockStateGen.horizontalAxisBlock(c, p, s -> p.models()
|
||||
.getExistingFile(p.modLoc("block/track/bogey/top"))))
|
||||
.onRegister(b -> IBogeyBlock.register(b.getRegistryName()))
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<StandardBogeyBlock> LARGE_BOGEY =
|
||||
REGISTRATE.block("large_bogey", p -> new StandardBogeyBlock(p, true))
|
||||
.initialProperties(SharedProperties::softMetal)
|
||||
.properties(p -> p.noOcclusion())
|
||||
.blockstate((c, p) -> BlockStateGen.horizontalAxisBlock(c, p, s -> p.models()
|
||||
.getExistingFile(p.modLoc("block/track/bogey/top"))))
|
||||
.onRegister(b -> IBogeyBlock.register(b.getRegistryName()))
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<ControlsBlock> CONTROLS = REGISTRATE.block("controls", ControlsBlock::new)
|
||||
.initialProperties(SharedProperties::softMetal)
|
||||
.blockstate((c, p) -> p.horizontalBlock(c.get(),
|
||||
s -> AssetLookup.partialBaseModel(c, p, s.getValue(ControlsBlock.OPEN) ? "open" : "closed")))
|
||||
.onRegister(addMovementBehaviour(new ControlsMovementBehaviour()))
|
||||
.item()
|
||||
.transform(customItemModel())
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<ItemVaultBlock> ITEM_VAULT = REGISTRATE.block("item_vault", ItemVaultBlock::new)
|
||||
.initialProperties(SharedProperties::softMetal)
|
||||
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK)
|
||||
|
|
|
@ -10,6 +10,8 @@ import com.simibubi.create.content.logistics.item.filter.AttributeFilterContaine
|
|||
import com.simibubi.create.content.logistics.item.filter.AttributeFilterScreen;
|
||||
import com.simibubi.create.content.logistics.item.filter.FilterContainer;
|
||||
import com.simibubi.create.content.logistics.item.filter.FilterScreen;
|
||||
import com.simibubi.create.content.logistics.trains.management.ScheduleContainer;
|
||||
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
|
||||
import com.simibubi.create.content.schematics.block.SchematicTableContainer;
|
||||
import com.simibubi.create.content.schematics.block.SchematicTableScreen;
|
||||
import com.simibubi.create.content.schematics.block.SchematicannonContainer;
|
||||
|
@ -45,6 +47,9 @@ public class AllContainerTypes {
|
|||
|
||||
public static final MenuEntry<ToolboxContainer> TOOLBOX =
|
||||
register("toolbox", ToolboxContainer::new, () -> ToolboxScreen::new);
|
||||
|
||||
public static final MenuEntry<ScheduleContainer> SCHEDULE =
|
||||
register("schedule", ScheduleContainer::new, () -> ScheduleScreen::new);
|
||||
|
||||
private static <C extends AbstractContainerMenu, S extends Screen & MenuAccess<C>> MenuEntry<C> register(
|
||||
String name, ForgeMenuFactory<C> factory, NonNullSupplier<ScreenFactory<C, S>> screenFactory) {
|
||||
|
|
|
@ -14,6 +14,8 @@ import com.simibubi.create.content.curiosities.tools.BlueprintEntity;
|
|||
import com.simibubi.create.content.curiosities.tools.BlueprintRenderer;
|
||||
import com.simibubi.create.content.curiosities.weapons.PotatoProjectileEntity;
|
||||
import com.simibubi.create.content.curiosities.weapons.PotatoProjectileRenderer;
|
||||
import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity;
|
||||
import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntityRenderer;
|
||||
import com.simibubi.create.foundation.data.CreateEntityBuilder;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.tterrag.registrate.util.entry.EntityEntry;
|
||||
|
@ -37,6 +39,9 @@ public class AllEntityTypes {
|
|||
20, 40, false);
|
||||
public static final EntityEntry<GantryContraptionEntity> GANTRY_CONTRAPTION = contraption("gantry_contraption",
|
||||
GantryContraptionEntity::new, () -> ContraptionEntityRenderer::new, 10, 40, false);
|
||||
public static final EntityEntry<CarriageContraptionEntity> CARRIAGE_CONTRAPTION =
|
||||
contraption("carriage_contraption", CarriageContraptionEntity::new,
|
||||
() -> CarriageContraptionEntityRenderer::new, 5, 100, true);
|
||||
|
||||
public static final EntityEntry<SuperGlueEntity> SUPER_GLUE =
|
||||
register("super_glue", SuperGlueEntity::new, () -> SuperGlueRenderer::new, MobCategory.MISC, 10,
|
||||
|
@ -44,8 +49,8 @@ public class AllEntityTypes {
|
|||
.register();
|
||||
|
||||
public static final EntityEntry<BlueprintEntity> CRAFTING_BLUEPRINT =
|
||||
register("crafting_blueprint", BlueprintEntity::new, () -> BlueprintRenderer::new, MobCategory.MISC,
|
||||
10, Integer.MAX_VALUE, false, true, BlueprintEntity::build).register();
|
||||
register("crafting_blueprint", BlueprintEntity::new, () -> BlueprintRenderer::new, MobCategory.MISC, 10,
|
||||
Integer.MAX_VALUE, false, true, BlueprintEntity::build).register();
|
||||
|
||||
public static final EntityEntry<PotatoProjectileEntity> POTATO_PROJECTILE =
|
||||
register("potato_projectile", PotatoProjectileEntity::new, () -> PotatoProjectileRenderer::new,
|
||||
|
@ -57,16 +62,16 @@ public class AllEntityTypes {
|
|||
//
|
||||
|
||||
private static <T extends Entity> EntityEntry<T> contraption(String name, EntityFactory<T> factory,
|
||||
NonNullSupplier<NonNullFunction<EntityRendererProvider.Context, EntityRenderer<? super T>>> renderer,
|
||||
int range, int updateFrequency, boolean sendVelocity) {
|
||||
NonNullSupplier<NonNullFunction<EntityRendererProvider.Context, EntityRenderer<? super T>>> renderer, int range,
|
||||
int updateFrequency, boolean sendVelocity) {
|
||||
return register(name, factory, renderer, MobCategory.MISC, range, updateFrequency, sendVelocity, true,
|
||||
AbstractContraptionEntity::build).register();
|
||||
}
|
||||
|
||||
private static <T extends Entity> CreateEntityBuilder<T, ?> register(String name, EntityFactory<T> factory,
|
||||
NonNullSupplier<NonNullFunction<EntityRendererProvider.Context, EntityRenderer<? super T>>> renderer,
|
||||
MobCategory group, int range, int updateFrequency, boolean sendVelocity, boolean immuneToFire,
|
||||
NonNullConsumer<EntityType.Builder<T>> propertyBuilder) {
|
||||
NonNullSupplier<NonNullFunction<EntityRendererProvider.Context, EntityRenderer<? super T>>> renderer,
|
||||
MobCategory group, int range, int updateFrequency, boolean sendVelocity, boolean immuneToFire,
|
||||
NonNullConsumer<EntityType.Builder<T>> propertyBuilder) {
|
||||
String id = Lang.asId(name);
|
||||
return (CreateEntityBuilder<T, ?>) Create.registrate()
|
||||
.entity(id, factory, group)
|
||||
|
|
|
@ -41,6 +41,7 @@ import com.simibubi.create.content.curiosities.weapons.PotatoCannonItem;
|
|||
import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperItem;
|
||||
import com.simibubi.create.content.logistics.item.LinkedControllerItem;
|
||||
import com.simibubi.create.content.logistics.item.filter.FilterItem;
|
||||
import com.simibubi.create.content.logistics.trains.management.ScheduleItem;
|
||||
import com.simibubi.create.content.schematics.item.SchematicAndQuillItem;
|
||||
import com.simibubi.create.content.schematics.item.SchematicItem;
|
||||
import com.simibubi.create.foundation.data.AssetLookup;
|
||||
|
@ -327,6 +328,9 @@ public class AllItems {
|
|||
.model(AssetLookup.existingItemModel())
|
||||
.register();
|
||||
|
||||
public static final ItemEntry<ScheduleItem> SCHEDULE = REGISTRATE.item("schedule", ScheduleItem::new)
|
||||
.register();
|
||||
|
||||
// Schematics
|
||||
|
||||
static {
|
||||
|
|
|
@ -29,6 +29,7 @@ public class AllShapes {
|
|||
CASING_12PX = shape(0, 0, 0, 16, 12, 16).forDirectional(),
|
||||
CASING_11PX = shape(0, 0, 0, 16, 11, 16).forDirectional(),
|
||||
MOTOR_BLOCK = shape(3, 0, 3, 13, 14, 13).forDirectional(),
|
||||
TRACK = shape(0, 0, 0, 16, 4, 16).forDirectional(),
|
||||
FOUR_VOXEL_POLE = shape(6, 0, 6, 10, 16, 10).forAxis(), SIX_VOXEL_POLE = shape(5, 0, 5, 11, 16, 11).forAxis(),
|
||||
EIGHT_VOXEL_POLE = shape(4, 0, 4, 12, 16, 12).forAxis(),
|
||||
FURNACE_ENGINE = shape(1, 1, 0, 15, 15, 16).add(0, 0, 9, 16, 16, 14)
|
||||
|
@ -118,7 +119,12 @@ public class AllShapes {
|
|||
BELL_DOUBLE_WALL = shape(5, 5, 0, 11, 11, 16).add(3, 1, 3, 13, 13, 13)
|
||||
.forHorizontal(SOUTH),
|
||||
BELL_CEILING = shape(0, 5, 5, 16, 16, 11).add(3, 1, 3, 13, 13, 13)
|
||||
.forHorizontal(SOUTH)
|
||||
.forHorizontal(SOUTH),
|
||||
|
||||
STATION = shape(0, 0, 0, 16, 5, 16).add(2, 4, 0, 14, 16, 4)
|
||||
.forHorizontal(NORTH),
|
||||
CONTROLS = shape(0, 0, 4, 16, 8, 16).add(0, 0, 6, 16, 14, 16)
|
||||
.forHorizontal(NORTH)
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -167,6 +167,12 @@ import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchTileE
|
|||
import com.simibubi.create.content.logistics.block.vault.ItemVaultTileEntity;
|
||||
import com.simibubi.create.content.logistics.item.LecternControllerRenderer;
|
||||
import com.simibubi.create.content.logistics.item.LecternControllerTileEntity;
|
||||
import com.simibubi.create.content.logistics.trains.IBogeyTileEntityRenderer;
|
||||
import com.simibubi.create.content.logistics.trains.management.StationRenderer;
|
||||
import com.simibubi.create.content.logistics.trains.management.StationTileEntity;
|
||||
import com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity;
|
||||
import com.simibubi.create.content.logistics.trains.track.TrackRenderer;
|
||||
import com.simibubi.create.content.logistics.trains.track.TrackTileEntity;
|
||||
import com.simibubi.create.content.schematics.block.SchematicTableTileEntity;
|
||||
import com.simibubi.create.content.schematics.block.SchematicannonInstance;
|
||||
import com.simibubi.create.content.schematics.block.SchematicannonRenderer;
|
||||
|
@ -722,5 +728,23 @@ public class AllTileEntities {
|
|||
.renderer(() -> ToolboxRenderer::new)
|
||||
.register();
|
||||
|
||||
public static final BlockEntityEntry<TrackTileEntity> TRACK = Create.registrate()
|
||||
.tileEntity("track", TrackTileEntity::new)
|
||||
.renderer(() -> TrackRenderer::new)
|
||||
.validBlocks(AllBlocks.TRACK)
|
||||
.register();
|
||||
|
||||
public static final BlockEntityEntry<StandardBogeyTileEntity> BOGEY = Create.registrate()
|
||||
.tileEntity("bogey", StandardBogeyTileEntity::new)
|
||||
.renderer(() -> IBogeyTileEntityRenderer::new)
|
||||
.validBlocks(AllBlocks.SMALL_BOGEY, AllBlocks.LARGE_BOGEY)
|
||||
.register();
|
||||
|
||||
public static final BlockEntityEntry<StationTileEntity> TRACK_STATION = Create.registrate()
|
||||
.tileEntity("track_station", StationTileEntity::new)
|
||||
.renderer(() -> StationRenderer::new)
|
||||
.validBlocks(AllBlocks.TRACK_STATION)
|
||||
.register();
|
||||
|
||||
public static void register() {}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.simibubi.create.content.contraptions.TorquePropagator;
|
|||
import com.simibubi.create.content.contraptions.components.flywheel.engine.FurnaceEngineInteractions;
|
||||
import com.simibubi.create.content.curiosities.weapons.BuiltinPotatoProjectileTypes;
|
||||
import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler;
|
||||
import com.simibubi.create.content.logistics.trains.GlobalRailwayManager;
|
||||
import com.simibubi.create.content.palettes.AllPaletteBlocks;
|
||||
import com.simibubi.create.content.palettes.PalettesItemGroup;
|
||||
import com.simibubi.create.content.schematics.SchematicProcessor;
|
||||
|
@ -71,6 +72,7 @@ public class Create {
|
|||
public static final ServerSchematicLoader SCHEMATIC_RECEIVER = new ServerSchematicLoader();
|
||||
public static final RedstoneLinkNetworkHandler REDSTONE_LINK_NETWORK_HANDLER = new RedstoneLinkNetworkHandler();
|
||||
public static final TorquePropagator TORQUE_PROPAGATOR = new TorquePropagator();
|
||||
public static final GlobalRailwayManager RAILWAYS = new GlobalRailwayManager();
|
||||
public static final ServerLagger LAGGER = new ServerLagger();
|
||||
public static final Random RANDOM = new Random();
|
||||
|
||||
|
@ -115,8 +117,7 @@ public class Create {
|
|||
modEventBus.addGenericListener(ParticleType.class, AllParticleTypes::register);
|
||||
modEventBus.addGenericListener(SoundEvent.class, AllSoundEvents::register);
|
||||
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
|
||||
() -> () -> CreateClient.onCtorClient(modEventBus, forgeEventBus));
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.onCtorClient(modEventBus, forgeEventBus));
|
||||
}
|
||||
|
||||
public static void init(final FMLCommonSetupEvent event) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import com.simibubi.create.content.curiosities.tools.BlueprintOverlayRenderer;
|
|||
import com.simibubi.create.content.curiosities.weapons.PotatoCannonRenderHandler;
|
||||
import com.simibubi.create.content.curiosities.zapper.ZapperRenderHandler;
|
||||
import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler;
|
||||
import com.simibubi.create.content.logistics.trains.GlobalRailwayManager;
|
||||
import com.simibubi.create.content.schematics.ClientSchematicLoader;
|
||||
import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler;
|
||||
import com.simibubi.create.content.schematics.client.SchematicHandler;
|
||||
|
@ -57,6 +58,7 @@ public class CreateClient {
|
|||
public static final ZapperRenderHandler ZAPPER_RENDER_HANDLER = new ZapperRenderHandler();
|
||||
public static final PotatoCannonRenderHandler POTATO_CANNON_RENDER_HANDLER = new PotatoCannonRenderHandler();
|
||||
public static final SoulPulseEffectHandler SOUL_PULSE_EFFECT_HANDLER = new SoulPulseEffectHandler();
|
||||
public static final GlobalRailwayManager RAILWAYS = new GlobalRailwayManager();
|
||||
|
||||
public static final ClientResourceReloadListener RESOURCE_RELOAD_LISTENER = new ClientResourceReloadListener();
|
||||
|
||||
|
|
|
@ -73,6 +73,10 @@ public class AssemblyException extends Exception {
|
|||
public static AssemblyException noPistonPoles() {
|
||||
return new AssemblyException("noPistonPoles");
|
||||
}
|
||||
|
||||
public static AssemblyException invalidBogeyCount() {
|
||||
return new AssemblyException("invalidBogeyCount");
|
||||
}
|
||||
|
||||
public static AssemblyException notEnoughSails(int sails) {
|
||||
return new AssemblyException("not_enough_sails", sails, AllConfigs.SERVER.kinetics.minimumWindmillSails.get());
|
||||
|
|
|
@ -32,6 +32,7 @@ import com.simibubi.create.content.contraptions.fluids.tank.FluidTankConnectivit
|
|||
import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkBlock;
|
||||
import com.simibubi.create.content.logistics.block.vault.ItemVaultBlock;
|
||||
import com.simibubi.create.content.logistics.block.vault.ItemVaultConnectivityHandler;
|
||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
||||
import com.simibubi.create.foundation.config.ContraptionMovementSetting;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
@ -340,6 +341,9 @@ public class BlockMovementChecks {
|
|||
return direction == state.getValue(StickerBlock.FACING)
|
||||
&& !isNotSupportive(world.getBlockState(pos.relative(direction)), direction.getOpposite());
|
||||
}
|
||||
if (block instanceof IBogeyBlock bogey)
|
||||
return bogey.getStickySurfaces(world, pos, state)
|
||||
.contains(direction);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.cha
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueHandler;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonHeadBlock;
|
||||
|
@ -56,6 +57,7 @@ import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
|
|||
import com.simibubi.create.content.logistics.block.inventories.CreativeCrateTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock;
|
||||
import com.simibubi.create.content.logistics.block.vault.ItemVaultTileEntity;
|
||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
|
||||
import com.simibubi.create.foundation.tileEntity.IMultiTileContainer;
|
||||
|
@ -345,6 +347,12 @@ public abstract class Contraption {
|
|||
frontier.add(attached);
|
||||
}
|
||||
|
||||
// Bogeys tend to have sticky sides
|
||||
if (state.getBlock() instanceof IBogeyBlock bogey)
|
||||
for (Direction d : bogey.getStickySurfaces(world, pos, state))
|
||||
if (!visited.contains(pos.relative(d)))
|
||||
frontier.add(pos.relative(d));
|
||||
|
||||
// Bearings potentially create stabilized sub-contraptions
|
||||
if (AllBlocks.MECHANICAL_BEARING.has(state))
|
||||
moveBearing(pos, frontier, visited, state);
|
||||
|
@ -603,6 +611,8 @@ public abstract class Contraption {
|
|||
BlockState blockstate = world.getBlockState(pos);
|
||||
if (AllBlocks.REDSTONE_CONTACT.has(blockstate))
|
||||
blockstate = blockstate.setValue(RedstoneContactBlock.POWERED, true);
|
||||
if (AllBlocks.CONTROLS.has(blockstate))
|
||||
blockstate = blockstate.setValue(ControlsBlock.OPEN, true);
|
||||
if (blockstate.getBlock() instanceof ButtonBlock) {
|
||||
blockstate = blockstate.setValue(ButtonBlock.POWERED, false);
|
||||
world.scheduleTick(pos, blockstate.getBlock(), -1);
|
||||
|
|
|
@ -12,6 +12,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.gan
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonContraption;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyContraption;
|
||||
import com.simibubi.create.content.logistics.trains.entity.CarriageContraption;
|
||||
|
||||
public class ContraptionType {
|
||||
|
||||
|
@ -23,7 +24,8 @@ public class ContraptionType {
|
|||
CLOCKWORK = register("clockwork", ClockworkContraption::new),
|
||||
MOUNTED = register("mounted", MountedContraption::new),
|
||||
STABILIZED = register("stabilized", StabilizedContraption::new),
|
||||
GANTRY = register("gantry", GantryContraption::new);
|
||||
GANTRY = register("gantry", GantryContraption::new),
|
||||
CARRIAGE = register("carriage", CarriageContraption::new);
|
||||
|
||||
Supplier<? extends Contraption> factory;
|
||||
String id;
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls;
|
||||
|
||||
import com.simibubi.create.AllShapes;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionWorld;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
public class ControlsBlock extends HorizontalDirectionalBlock {
|
||||
|
||||
public static final BooleanProperty OPEN = BooleanProperty.create("open");
|
||||
|
||||
public ControlsBlock(Properties p_54120_) {
|
||||
super(p_54120_);
|
||||
registerDefaultState(defaultBlockState().setValue(OPEN, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(Builder<Block, BlockState> pBuilder) {
|
||||
super.createBlockStateDefinition(pBuilder.add(FACING, OPEN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState,
|
||||
LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) {
|
||||
return pState.setValue(OPEN, pLevel instanceof ContraptionWorld);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
BlockState state = super.getStateForPlacement(pContext);
|
||||
Direction horizontalDirection = pContext.getHorizontalDirection();
|
||||
Player player = pContext.getPlayer();
|
||||
|
||||
state = state.setValue(FACING, horizontalDirection.getOpposite());
|
||||
if (player != null && player.isSteppingCarefully())
|
||||
state = state.setValue(FACING, horizontalDirection);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
|
||||
return AllShapes.CONTROLS.get(pState.getValue(FACING));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls;
|
||||
|
||||
import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
|
||||
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public class ControlsMovementBehaviour extends MovementBehaviour {
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
|
||||
ContraptionMatrices matrices, MultiBufferSource buffer) {
|
||||
ControlsRenderer.render(context, renderWorld, matrices, buffer);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls;
|
||||
|
||||
import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld;
|
||||
import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class ControlsRenderer {
|
||||
|
||||
public static void render(MovementContext context, VirtualRenderWorld renderWorld, ContraptionMatrices matrices,
|
||||
MultiBufferSource buffer) {
|
||||
BlockState state = context.state;
|
||||
Direction facing = state.getValue(ControlsBlock.FACING);
|
||||
|
||||
SuperByteBuffer cover = CachedBufferer.partial(AllBlockPartials.TRAIN_CONTROLS_COVER, state);
|
||||
float hAngle = 180 + AngleHelper.horizontalAngle(facing);
|
||||
cover.transform(matrices.getModel())
|
||||
.centre()
|
||||
.rotateY(hAngle)
|
||||
.unCentre()
|
||||
.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
|
||||
.renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid()));
|
||||
|
||||
for (boolean first : Iterate.trueAndFalse) {
|
||||
SuperByteBuffer lever = CachedBufferer.partial(AllBlockPartials.TRAIN_CONTROLS_LEVER, state);
|
||||
lever.transform(matrices.getModel())
|
||||
.centre()
|
||||
.rotateY(hAngle)
|
||||
.unCentre()
|
||||
.translate(first ? 0 : 6 / 16f, 0, 0)
|
||||
.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
|
||||
.renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,253 @@
|
|||
package com.simibubi.create.content.logistics.trains;
|
||||
|
||||
import com.jozufozu.flywheel.repack.joml.Math;
|
||||
import com.simibubi.create.foundation.utility.Couple;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class BezierConnection {
|
||||
|
||||
public Couple<BlockPos> tePositions;
|
||||
public Couple<Boolean> trackEnds;
|
||||
public Couple<Vec3> starts;
|
||||
public Couple<Vec3> axes;
|
||||
public Couple<Vec3> normals;
|
||||
public boolean primary;
|
||||
|
||||
// runtime
|
||||
|
||||
Vec3 finish1;
|
||||
Vec3 finish2;
|
||||
private boolean resolved;
|
||||
private double length;
|
||||
private float[] stepLUT;
|
||||
private int segments;
|
||||
|
||||
private double radius;
|
||||
private double handleLength;
|
||||
|
||||
public BezierConnection(Couple<BlockPos> positions, Couple<Vec3> starts, Couple<Vec3> axes, Couple<Vec3> normals,
|
||||
Couple<Boolean> targets, boolean primary) {
|
||||
tePositions = positions;
|
||||
this.starts = starts;
|
||||
this.axes = axes;
|
||||
this.normals = normals;
|
||||
this.trackEnds = targets;
|
||||
this.primary = primary;
|
||||
resolved = false;
|
||||
}
|
||||
|
||||
public BezierConnection secondary() {
|
||||
return new BezierConnection(tePositions.swap(), starts.swap(), axes.swap(), normals.swap(), trackEnds.swap(),
|
||||
false);
|
||||
}
|
||||
|
||||
public BezierConnection(CompoundTag compound) {
|
||||
this(Couple.deserializeEach(compound.getList("Positions", Tag.TAG_COMPOUND), NbtUtils::readBlockPos),
|
||||
Couple.deserializeEach(compound.getList("Starts", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
|
||||
Couple.deserializeEach(compound.getList("Axes", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
|
||||
Couple.deserializeEach(compound.getList("Normals", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
|
||||
Couple.create(compound.getBoolean("TrackEnd1"), compound.getBoolean("TrackEnd2")),
|
||||
compound.getBoolean("Primary"));
|
||||
}
|
||||
|
||||
public CompoundTag write() {
|
||||
CompoundTag compound = new CompoundTag();
|
||||
compound.putBoolean("Primary", primary);
|
||||
compound.putBoolean("TrackEnd1", trackEnds.getFirst());
|
||||
compound.putBoolean("TrackEnd2", trackEnds.getSecond());
|
||||
compound.put("Positions", tePositions.serializeEach(NbtUtils::writeBlockPos));
|
||||
compound.put("Starts", starts.serializeEach(VecHelper::writeNBTCompound));
|
||||
compound.put("Axes", axes.serializeEach(VecHelper::writeNBTCompound));
|
||||
compound.put("Normals", normals.serializeEach(VecHelper::writeNBTCompound));
|
||||
return compound;
|
||||
}
|
||||
|
||||
public BezierConnection(FriendlyByteBuf buffer) {
|
||||
this(Couple.create(buffer::readBlockPos), Couple.create(() -> VecHelper.read(buffer)),
|
||||
Couple.create(() -> VecHelper.read(buffer)), Couple.create(() -> VecHelper.read(buffer)),
|
||||
Couple.create(buffer::readBoolean), buffer.readBoolean());
|
||||
}
|
||||
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
tePositions.forEach(buffer::writeBlockPos);
|
||||
starts.forEach(v -> VecHelper.write(v, buffer));
|
||||
axes.forEach(v -> VecHelper.write(v, buffer));
|
||||
normals.forEach(v -> VecHelper.write(v, buffer));
|
||||
trackEnds.forEach(buffer::writeBoolean);
|
||||
buffer.writeBoolean(primary);
|
||||
}
|
||||
|
||||
public BlockPos getKey() {
|
||||
return tePositions.getSecond();
|
||||
}
|
||||
|
||||
public boolean isPrimary() {
|
||||
return primary;
|
||||
}
|
||||
|
||||
// Runtime information
|
||||
|
||||
public double getLength() {
|
||||
resolve();
|
||||
return length;
|
||||
}
|
||||
|
||||
public float[] getStepLUT() {
|
||||
resolve();
|
||||
return stepLUT;
|
||||
}
|
||||
|
||||
public int getSegmentCount() {
|
||||
resolve();
|
||||
return segments;
|
||||
}
|
||||
|
||||
public Vec3 getPosition(double t) {
|
||||
resolve();
|
||||
return VecHelper.bezier(starts.getFirst(), starts.getSecond(), finish1, finish2, (float) t);
|
||||
}
|
||||
|
||||
public double getRadius() {
|
||||
resolve();
|
||||
return radius;
|
||||
}
|
||||
|
||||
public double getHandleLength() {
|
||||
resolve();
|
||||
return handleLength;
|
||||
}
|
||||
|
||||
public double incrementT(double currentT, double distance) {
|
||||
resolve();
|
||||
double dx =
|
||||
VecHelper.bezierDerivative(starts.getFirst(), starts.getSecond(), finish1, finish2, (float) currentT)
|
||||
.length() / getLength();
|
||||
return currentT + distance / dx;
|
||||
|
||||
}
|
||||
|
||||
public Vec3 getNormal(double t) {
|
||||
resolve();
|
||||
Vec3 end1 = starts.getFirst();
|
||||
Vec3 end2 = starts.getSecond();
|
||||
Vec3 fn1 = normals.getFirst();
|
||||
Vec3 fn2 = normals.getSecond();
|
||||
|
||||
Vec3 derivative = VecHelper.bezierDerivative(end1, end2, finish1, finish2, (float) t)
|
||||
.normalize();
|
||||
Vec3 faceNormal = fn1.equals(fn2) ? fn1 : VecHelper.slerp((float) t, fn1, fn2);
|
||||
Vec3 normal = faceNormal.cross(derivative)
|
||||
.normalize();
|
||||
return derivative.cross(normal);
|
||||
}
|
||||
|
||||
private void resolve() {
|
||||
if (resolved)
|
||||
return;
|
||||
resolved = true;
|
||||
|
||||
Vec3 end1 = starts.getFirst();
|
||||
Vec3 end2 = starts.getSecond();
|
||||
Vec3 axis1 = axes.getFirst()
|
||||
.normalize();
|
||||
Vec3 axis2 = axes.getSecond()
|
||||
.normalize();
|
||||
|
||||
determineHandles(end1, end2, axis1, axis2);
|
||||
|
||||
finish1 = axis1.scale(handleLength)
|
||||
.add(end1);
|
||||
finish2 = axis2.scale(handleLength)
|
||||
.add(end2);
|
||||
|
||||
int scanCount = 16;
|
||||
length = 0;
|
||||
|
||||
{
|
||||
Vec3 previous = end1;
|
||||
for (int i = 0; i <= scanCount; i++) {
|
||||
float t = i / (float) scanCount;
|
||||
Vec3 result = VecHelper.bezier(end1, end2, finish1, finish2, t);
|
||||
if (previous != null)
|
||||
length += result.distanceTo(previous);
|
||||
previous = result;
|
||||
}
|
||||
}
|
||||
|
||||
segments = (int) (length * 2);
|
||||
stepLUT = new float[segments + 1];
|
||||
stepLUT[0] = 1;
|
||||
float combinedDistance = 0;
|
||||
|
||||
// determine step lut
|
||||
{
|
||||
Vec3 previous = end1;
|
||||
for (int i = 0; i <= segments; i++) {
|
||||
float t = i / (float) segments;
|
||||
Vec3 result = VecHelper.bezier(end1, end2, finish1, finish2, t);
|
||||
if (i > 0) {
|
||||
combinedDistance += result.distanceTo(previous) / length;
|
||||
stepLUT[i] = (float) (t / combinedDistance);
|
||||
}
|
||||
previous = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void determineHandles(Vec3 end1, Vec3 end2, Vec3 axis1, Vec3 axis2) {
|
||||
Vec3 cross1 = axis1.cross(new Vec3(0, 1, 0));
|
||||
Vec3 cross2 = axis2.cross(new Vec3(0, 1, 0));
|
||||
|
||||
radius = 0;
|
||||
double a1 = Mth.atan2(-axis2.z, -axis2.x);
|
||||
double a2 = Mth.atan2(axis1.z, axis1.x);
|
||||
double angle = a1 - a2;
|
||||
|
||||
float circle = 2 * Mth.PI;
|
||||
angle = (angle + circle) % circle;
|
||||
if (Math.abs(circle - angle) < Math.abs(angle))
|
||||
angle = circle - angle;
|
||||
|
||||
if (Mth.equal(angle, 0)) {
|
||||
double[] intersect = VecHelper.intersect(end1, end2, axis1, cross2, Axis.Y);
|
||||
if (intersect != null) {
|
||||
double t = Math.abs(intersect[0]);
|
||||
double u = Math.abs(intersect[1]);
|
||||
double min = Math.min(t, u);
|
||||
double max = Math.max(t, u);
|
||||
|
||||
if (min > 1.2 && max / min > 1 && max / min < 3) {
|
||||
handleLength = (max - min);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
handleLength = end2.distanceTo(end1) / 3;
|
||||
return;
|
||||
}
|
||||
|
||||
double n = circle / angle;
|
||||
double factor = 4 / 3d * Math.tan(Math.PI / (2 * n));
|
||||
double[] intersect = VecHelper.intersect(end1, end2, cross1, cross2, Axis.Y);
|
||||
|
||||
if (intersect == null) {
|
||||
handleLength = end2.distanceTo(end1) / 3;
|
||||
return;
|
||||
}
|
||||
|
||||
radius = Math.abs(intersect[1]);
|
||||
handleLength = radius * factor;
|
||||
if (Mth.equal(handleLength, 0))
|
||||
handleLength = 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
package com.simibubi.create.content.logistics.trains;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.content.contraptions.KineticDebugger;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Carriage;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
|
||||
public class GlobalRailwayManager {
|
||||
|
||||
public Map<UUID, TrackGraph> trackNetworks;
|
||||
private TrackSavedData trackData;
|
||||
|
||||
public Map<UUID, Train> trains;
|
||||
public Map<Integer, Carriage> carriageById;
|
||||
|
||||
public TrackGraphSync sync;
|
||||
|
||||
//
|
||||
|
||||
public GlobalRailwayManager() {
|
||||
cleanUp();
|
||||
}
|
||||
|
||||
public void playerLogin(Player player) {
|
||||
if (player instanceof ServerPlayer serverPlayer) {
|
||||
loadTrackData(serverPlayer.getServer());
|
||||
trackNetworks.values()
|
||||
.forEach(g -> sync.sendFullGraphTo(g, serverPlayer));
|
||||
}
|
||||
}
|
||||
|
||||
public void levelLoaded(LevelAccessor level) {
|
||||
MinecraftServer server = level.getServer();
|
||||
if (server == null || server.overworld() != level)
|
||||
return;
|
||||
cleanUp();
|
||||
trackData = null;
|
||||
loadTrackData(server);
|
||||
}
|
||||
|
||||
private void loadTrackData(MinecraftServer server) {
|
||||
if (trackData != null)
|
||||
return;
|
||||
trackData = TrackSavedData.load(server);
|
||||
trackNetworks = trackData.getTrackNetworks();
|
||||
}
|
||||
|
||||
public void levelUnloaded(LevelAccessor level) {
|
||||
// MinecraftServer server = level.getServer();
|
||||
// if (server == null || server.overworld() != level)
|
||||
// return;
|
||||
// cleanUp();
|
||||
}
|
||||
|
||||
public void cleanUp() {
|
||||
trackNetworks = new HashMap<>();
|
||||
trains = new HashMap<>();
|
||||
carriageById = new HashMap<>();
|
||||
sync = new TrackGraphSync();
|
||||
}
|
||||
|
||||
public void markTracksDirty() {
|
||||
if (trackData != null)
|
||||
trackData.setDirty();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public TrackGraph getOrCreateGraph(UUID graphID) {
|
||||
return trackNetworks.computeIfAbsent(graphID, uid -> new TrackGraph(graphID));
|
||||
}
|
||||
|
||||
public void putGraph(TrackGraph graph) {
|
||||
trackNetworks.put(graph.id, graph);
|
||||
markTracksDirty();
|
||||
}
|
||||
|
||||
public void removeGraph(TrackGraph railGraph) {
|
||||
trackNetworks.remove(railGraph.id);
|
||||
markTracksDirty();
|
||||
}
|
||||
|
||||
public void updateSplitGraph(TrackGraph graph) {
|
||||
Set<TrackGraph> disconnected = graph.findDisconnectedGraphs(null);
|
||||
disconnected.forEach(this::putGraph);
|
||||
if (!disconnected.isEmpty()) {
|
||||
sync.graphSplit(graph, disconnected);
|
||||
markTracksDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TrackGraph getGraph(LevelAccessor level, TrackNodeLocation vertex) {
|
||||
if (trackNetworks == null)
|
||||
return null;
|
||||
for (TrackGraph railGraph : trackNetworks.values())
|
||||
if (railGraph.locateNode(vertex) != null)
|
||||
return railGraph;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void tick(Level level) {
|
||||
ResourceLocation location2 = DimensionType.OVERWORLD_LOCATION.location();
|
||||
ResourceLocation location = level.dimension()
|
||||
.location();
|
||||
if (!location.equals(location2))
|
||||
return;
|
||||
|
||||
for (Train train : trains.values())
|
||||
train.tick(level);
|
||||
}
|
||||
|
||||
public void clientTick() {
|
||||
if (KineticDebugger.isActive()) {
|
||||
trackNetworks.values()
|
||||
.forEach(TrackGraph::debugViewNodes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package com.simibubi.create.content.logistics.trains;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
||||
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
public interface IBogeyBlock extends IWrenchable {
|
||||
|
||||
static final List<ResourceLocation> BOGEYS = new ArrayList<>();
|
||||
|
||||
public static void register(ResourceLocation block) {
|
||||
BOGEYS.add(block);
|
||||
}
|
||||
|
||||
public EnumSet<Direction> getStickySurfaces(BlockGetter world, BlockPos pos, BlockState state);
|
||||
|
||||
public double getWheelPointSpacing();
|
||||
|
||||
public double getWheelRadius();
|
||||
|
||||
public boolean allowsSingleBogeyCarriage();
|
||||
|
||||
public Vec3 getConnectorAnchorOffset();
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void render(@Nullable BlockState state, float wheelAngle, PoseStack ms, float partialTicks,
|
||||
MultiBufferSource buffers, int light, int overlay);
|
||||
|
||||
public default Direction getBogeyUpDirection() {
|
||||
return Direction.UP;
|
||||
}
|
||||
|
||||
public boolean isTrackAxisAlongFirstCoordinate(BlockState state);
|
||||
|
||||
@Nullable
|
||||
public BlockState getMatchingBogey(Direction upDirection, boolean axisAlongFirst);
|
||||
|
||||
@Override
|
||||
default BlockState getRotatedBlockState(BlockState state, Direction targetedFace) {
|
||||
Block block = state.getBlock();
|
||||
int indexOf = BOGEYS.indexOf(block.getRegistryName());
|
||||
if (indexOf == -1)
|
||||
return state;
|
||||
|
||||
int index = (indexOf + 1) % BOGEYS.size();
|
||||
Direction bogeyUpDirection = getBogeyUpDirection();
|
||||
boolean trackAxisAlongFirstCoordinate = isTrackAxisAlongFirstCoordinate(state);
|
||||
|
||||
while (index != indexOf) {
|
||||
ResourceLocation id = BOGEYS.get(index);
|
||||
Block newBlock = ForgeRegistries.BLOCKS.getValue(id);
|
||||
if (newBlock instanceof IBogeyBlock bogey) {
|
||||
BlockState matchingBogey = bogey.getMatchingBogey(bogeyUpDirection, trackAxisAlongFirstCoordinate);
|
||||
if (matchingBogey != null)
|
||||
return matchingBogey;
|
||||
}
|
||||
index = (index + 1) % BOGEYS.size();
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.simibubi.create.content.logistics.trains;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
||||
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class IBogeyTileEntityRenderer<T extends BlockEntity> extends SafeTileEntityRenderer<T> {
|
||||
|
||||
public IBogeyTileEntityRenderer(BlockEntityRendererProvider.Context context) {}
|
||||
|
||||
@Override
|
||||
protected void renderSafe(T te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light,
|
||||
int overlay) {
|
||||
BlockState blockState = te.getBlockState();
|
||||
if (blockState.getBlock()instanceof IBogeyBlock bogey)
|
||||
bogey.render(blockState, 0, ms, partialTicks, buffer, light, overlay);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.simibubi.create.content.logistics.trains;
|
||||
|
||||
import com.jozufozu.flywheel.core.PartialModel;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.AxisDirection;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public interface ITrackBlock {
|
||||
|
||||
public Vec3 getUpNormal(BlockGetter world, BlockPos pos, BlockState state);
|
||||
|
||||
public Vec3 getTrackAxis(BlockGetter world, BlockPos pos, BlockState state);
|
||||
|
||||
public Vec3 getCurveStart(BlockGetter world, BlockPos pos, BlockState state, Vec3 axis);
|
||||
|
||||
public BlockState getBogeyAnchor(BlockGetter world, BlockPos pos, BlockState state); // should be on bogey side
|
||||
|
||||
public boolean trackEquals(BlockState state1, BlockState state2);
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public PartialModel prepareStationOverlay(BlockGetter world, BlockPos pos, BlockState state,
|
||||
AxisDirection direction, PoseStack transform);
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public PartialModel prepareAssemblyOverlay(BlockGetter world, BlockPos pos, BlockState state, Direction direction,
|
||||
PoseStack ms);
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.simibubi.create.content.logistics.trains;
|
||||
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class TrackEdge {
|
||||
|
||||
BezierConnection turn;
|
||||
|
||||
public TrackEdge(BezierConnection turn) {
|
||||
this.turn = turn;
|
||||
}
|
||||
|
||||
public boolean isTurn() {
|
||||
return turn != null;
|
||||
}
|
||||
|
||||
public BezierConnection getTurn() {
|
||||
return turn;
|
||||
}
|
||||
|
||||
public Vec3 getDirection(TrackNode node1, TrackNode node2, boolean fromFirst) {
|
||||
return getPosition(node1, node2, fromFirst ? 0.25f : 1)
|
||||
.subtract(getPosition(node1, node2, fromFirst ? 0 : 0.75f))
|
||||
.normalize();
|
||||
}
|
||||
|
||||
public double getLength(TrackNode node1, TrackNode node2) {
|
||||
return isTurn() ? turn.getLength()
|
||||
: node1.location.getLocation()
|
||||
.distanceTo(node2.location.getLocation());
|
||||
}
|
||||
|
||||
public double incrementT(TrackNode node1, TrackNode node2, double currentT, double distance) {
|
||||
distance = distance / getLength(node1, node2);
|
||||
return isTurn() ? turn.incrementT(currentT, distance) : currentT + distance;
|
||||
}
|
||||
|
||||
public Vec3 getPosition(TrackNode node1, TrackNode node2, double t) {
|
||||
return isTurn() ? turn.getPosition(Mth.clamp(t, 0, 1))
|
||||
: VecHelper.lerp((float) t, node1.location.getLocation(), node2.location.getLocation());
|
||||
}
|
||||
|
||||
public Vec3 getNormal(TrackNode node1, TrackNode node2, double t) {
|
||||
return isTurn() ? turn.getNormal(Mth.clamp(t, 0, 1)) : node1.getNormal();
|
||||
}
|
||||
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeBoolean(isTurn());
|
||||
if (isTurn())
|
||||
turn.write(buffer);
|
||||
}
|
||||
|
||||
public static TrackEdge read(FriendlyByteBuf buffer) {
|
||||
return new TrackEdge(buffer.readBoolean() ? new BezierConnection(buffer) : null);
|
||||
}
|
||||
|
||||
public CompoundTag write() {
|
||||
return isTurn() ? turn.write() : new CompoundTag();
|
||||
}
|
||||
|
||||
public static TrackEdge read(CompoundTag tag) {
|
||||
return new TrackEdge(tag.contains("Positions") ? new BezierConnection(tag) : null);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,375 @@
|
|||
package com.simibubi.create.content.logistics.trains;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
|
||||
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
||||
import com.simibubi.create.foundation.utility.Color;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class TrackGraph {
|
||||
|
||||
public static final AtomicInteger netIdGenerator = new AtomicInteger();
|
||||
|
||||
UUID id;
|
||||
Color color;
|
||||
|
||||
Map<TrackNodeLocation, TrackNode> nodes;
|
||||
Map<Integer, TrackNode> nodesById;
|
||||
Map<TrackNode, Map<TrackNode, TrackEdge>> connectionsByNode;
|
||||
|
||||
Map<UUID, GlobalStation> stations;
|
||||
|
||||
public TrackGraph() {
|
||||
this(UUID.randomUUID());
|
||||
}
|
||||
|
||||
public TrackGraph(UUID graphID) {
|
||||
id = graphID;
|
||||
nodes = new HashMap<>();
|
||||
nodesById = new HashMap<>();
|
||||
connectionsByNode = new IdentityHashMap<>();
|
||||
color = Color.rainbowColor(new Random().nextInt());
|
||||
stations = new HashMap<>();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Nullable
|
||||
public GlobalStation getStation(UUID id) {
|
||||
return stations.get(id);
|
||||
}
|
||||
|
||||
public Collection<GlobalStation> getStations() {
|
||||
return stations.values();
|
||||
}
|
||||
|
||||
public void removeStation(UUID id) {
|
||||
stations.remove(id);
|
||||
markDirty();
|
||||
}
|
||||
|
||||
public void addStation(GlobalStation station) {
|
||||
stations.put(station.id, station);
|
||||
markDirty();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public TrackNode locateNode(Vec3 position) {
|
||||
return locateNode(new TrackNodeLocation(position));
|
||||
}
|
||||
|
||||
public TrackNode locateNode(TrackNodeLocation position) {
|
||||
return nodes.get(position);
|
||||
}
|
||||
|
||||
public TrackNode getNode(int netId) {
|
||||
return nodesById.get(netId);
|
||||
}
|
||||
|
||||
public boolean createNode(DiscoveredLocation location) {
|
||||
if (!createSpecificNode(location, nextNodeId(), location.normal))
|
||||
return false;
|
||||
Create.RAILWAYS.sync.nodeAdded(this, nodes.get(location));
|
||||
markDirty();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean createSpecificNode(TrackNodeLocation location, int netId, Vec3 normal) {
|
||||
return addNode(new TrackNode(location, netId, normal));
|
||||
}
|
||||
|
||||
public boolean addNode(TrackNode node) {
|
||||
if (nodes.putIfAbsent(node.getLocation(), node) != null)
|
||||
return false;
|
||||
nodesById.put(node.getNetId(), node);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean removeNode(TrackNodeLocation location) {
|
||||
TrackNode removed = nodes.remove(location);
|
||||
if (removed == null)
|
||||
return false;
|
||||
|
||||
nodesById.remove(removed.netId);
|
||||
if (!connectionsByNode.containsKey(removed))
|
||||
return true;
|
||||
|
||||
Map<TrackNode, TrackEdge> connections = connectionsByNode.remove(removed);
|
||||
for (TrackNode railNode : connections.keySet())
|
||||
if (connectionsByNode.containsKey(railNode))
|
||||
connectionsByNode.get(railNode)
|
||||
.remove(removed);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int nextNodeId() {
|
||||
return netIdGenerator.incrementAndGet();
|
||||
}
|
||||
|
||||
public void transferAll(TrackGraph toOther) {
|
||||
toOther.nodes.putAll(nodes);
|
||||
toOther.nodesById.putAll(nodesById);
|
||||
toOther.connectionsByNode.putAll(connectionsByNode);
|
||||
|
||||
nodesById.forEach((id, node) -> Create.RAILWAYS.sync.nodeAdded(toOther, node));
|
||||
connectionsByNode.forEach(
|
||||
(node1, map) -> map.forEach((node2, edge) -> Create.RAILWAYS.sync.edgeAdded(toOther, node1, node2, edge)));
|
||||
markDirty();
|
||||
|
||||
nodes.clear();
|
||||
nodesById.clear();
|
||||
connectionsByNode.clear();
|
||||
}
|
||||
|
||||
public Set<TrackGraph> findDisconnectedGraphs(@Nullable Map<Integer, UUID> preAssignedIds) {
|
||||
Set<TrackGraph> dicovered = new HashSet<>();
|
||||
Set<TrackNodeLocation> vertices = new HashSet<>(nodes.keySet());
|
||||
List<TrackNodeLocation> frontier = new ArrayList<>();
|
||||
TrackGraph target = null;
|
||||
|
||||
while (!vertices.isEmpty()) {
|
||||
if (target != null)
|
||||
dicovered.add(target);
|
||||
|
||||
TrackNodeLocation start = vertices.stream()
|
||||
.findFirst()
|
||||
.get();
|
||||
frontier.add(start);
|
||||
vertices.remove(start);
|
||||
|
||||
while (!frontier.isEmpty()) {
|
||||
TrackNodeLocation current = frontier.remove(0);
|
||||
TrackNode currentNode = locateNode(current);
|
||||
|
||||
Map<TrackNode, TrackEdge> connections = getConnectionsFrom(currentNode);
|
||||
for (TrackNode connected : connections.keySet())
|
||||
if (vertices.remove(connected.getLocation()))
|
||||
frontier.add(connected.getLocation());
|
||||
|
||||
if (target != null) {
|
||||
transfer(currentNode, target);
|
||||
if (preAssignedIds != null && preAssignedIds.containsKey(currentNode.getNetId()))
|
||||
target.id = preAssignedIds.get(currentNode.getNetId());
|
||||
}
|
||||
}
|
||||
|
||||
frontier.clear();
|
||||
target = new TrackGraph();
|
||||
}
|
||||
|
||||
return dicovered;
|
||||
}
|
||||
|
||||
public void transfer(TrackNode node, TrackGraph target) {
|
||||
target.addNode(node);
|
||||
|
||||
Map<TrackNode, TrackEdge> connections = getConnectionsFrom(node);
|
||||
if (!connections.isEmpty())
|
||||
target.connectionsByNode.put(node, connections);
|
||||
|
||||
nodes.remove(node.getLocation());
|
||||
nodesById.remove(node.getNetId());
|
||||
connectionsByNode.remove(node);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return nodes.isEmpty();
|
||||
}
|
||||
|
||||
public Map<TrackNode, TrackEdge> getConnectionsFrom(TrackNode node) {
|
||||
return connectionsByNode.getOrDefault(node, new HashMap<>());
|
||||
}
|
||||
|
||||
public void connectNodes(TrackNodeLocation location, TrackNodeLocation location2, TrackEdge edge) {
|
||||
TrackNode node1 = nodes.get(location);
|
||||
TrackNode node2 = nodes.get(location2);
|
||||
TrackEdge edge2 = new TrackEdge(edge.turn != null ? edge.turn.secondary() : null);
|
||||
|
||||
putConnection(node1, node2, edge);
|
||||
putConnection(node2, node1, edge2);
|
||||
|
||||
Create.RAILWAYS.sync.edgeAdded(this, node1, node2, edge);
|
||||
Create.RAILWAYS.sync.edgeAdded(this, node2, node1, edge2);
|
||||
markDirty();
|
||||
}
|
||||
|
||||
public void disconnectNodes(TrackNode node1, TrackNode node2) {
|
||||
Map<TrackNode, TrackEdge> map1 = connectionsByNode.get(node1);
|
||||
Map<TrackNode, TrackEdge> map2 = connectionsByNode.get(node2);
|
||||
if (map1 != null)
|
||||
map1.remove(node2);
|
||||
if (map2 != null)
|
||||
map2.remove(node1);
|
||||
}
|
||||
|
||||
public void putConnection(TrackNode node1, TrackNode node2, TrackEdge edge) {
|
||||
connectionsByNode.computeIfAbsent(node1, n -> new IdentityHashMap<>())
|
||||
.put(node2, edge);
|
||||
}
|
||||
|
||||
public void markDirty() {
|
||||
Create.RAILWAYS.markTracksDirty();
|
||||
}
|
||||
|
||||
public CompoundTag write() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putUUID("Id", id);
|
||||
tag.putInt("Color", color.getRGB());
|
||||
|
||||
Map<TrackNode, Integer> indexTracker = new HashMap<>();
|
||||
ListTag nodesList = new ListTag();
|
||||
|
||||
int i = 0;
|
||||
for (TrackNode railNode : nodes.values()) {
|
||||
indexTracker.put(railNode, i);
|
||||
CompoundTag nodeTag = new CompoundTag();
|
||||
nodeTag.put("Location", NbtUtils.writeBlockPos(new BlockPos(railNode.getLocation())));
|
||||
nodeTag.put("Normal", VecHelper.writeNBT(railNode.getNormal()));
|
||||
nodesList.add(nodeTag);
|
||||
i++;
|
||||
}
|
||||
|
||||
connectionsByNode.forEach((node1, map) -> {
|
||||
Integer index1 = indexTracker.get(node1);
|
||||
if (index1 == null)
|
||||
return;
|
||||
CompoundTag nodeTag = (CompoundTag) nodesList.get(index1);
|
||||
ListTag connectionsList = new ListTag();
|
||||
map.forEach((node2, edge) -> {
|
||||
CompoundTag connectionTag = new CompoundTag();
|
||||
Integer index2 = indexTracker.get(node2);
|
||||
if (index2 == null)
|
||||
return;
|
||||
connectionTag.putInt("To", index2);
|
||||
connectionTag.put("EdgeData", edge.write());
|
||||
connectionsList.add(connectionTag);
|
||||
});
|
||||
nodeTag.put("Connections", connectionsList);
|
||||
});
|
||||
|
||||
tag.put("Nodes", nodesList);
|
||||
tag.put("Stations", NBTHelper.writeCompoundList(stations.values(), GlobalStation::write));
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static TrackGraph read(CompoundTag tag) {
|
||||
TrackGraph graph = new TrackGraph(tag.getUUID("Id"));
|
||||
graph.color = new Color(tag.getInt("Color"));
|
||||
|
||||
Map<Integer, TrackNode> indexTracker = new HashMap<>();
|
||||
ListTag nodesList = tag.getList("Nodes", Tag.TAG_COMPOUND);
|
||||
|
||||
int i = 0;
|
||||
for (Tag t : nodesList) {
|
||||
CompoundTag nodeTag = (CompoundTag) t;
|
||||
TrackNodeLocation location =
|
||||
TrackNodeLocation.fromPackedPos(NbtUtils.readBlockPos(nodeTag.getCompound("Location")));
|
||||
Vec3 normal = VecHelper.readNBT(nodeTag.getList("Normal", Tag.TAG_DOUBLE));
|
||||
graph.createSpecificNode(location, nextNodeId(), normal);
|
||||
indexTracker.put(i, graph.locateNode(location));
|
||||
i++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (Tag t : nodesList) {
|
||||
CompoundTag nodeTag = (CompoundTag) t;
|
||||
TrackNode node1 = indexTracker.get(i);
|
||||
i++;
|
||||
|
||||
if (!nodeTag.contains("Connections"))
|
||||
continue;
|
||||
NBTHelper.iterateCompoundList(nodeTag.getList("Connections", Tag.TAG_COMPOUND), c -> {
|
||||
TrackNode node2 = indexTracker.get(c.getInt("To"));
|
||||
TrackEdge edge = TrackEdge.read(c.getCompound("EdgeData"));
|
||||
graph.putConnection(node1, node2, edge);
|
||||
});
|
||||
}
|
||||
|
||||
NBTHelper.readCompoundList(tag.getList("Stations", Tag.TAG_COMPOUND), GlobalStation::new)
|
||||
.forEach(s -> graph.stations.put(s.id, s));
|
||||
return graph;
|
||||
}
|
||||
|
||||
public void debugViewNodes() {
|
||||
Entity cameraEntity = Minecraft.getInstance().cameraEntity;
|
||||
if (cameraEntity == null)
|
||||
return;
|
||||
Vec3 camera = cameraEntity.getEyePosition();
|
||||
for (Entry<TrackNodeLocation, TrackNode> nodeEntry : nodes.entrySet()) {
|
||||
TrackNodeLocation nodeLocation = nodeEntry.getKey();
|
||||
TrackNode node = nodeEntry.getValue();
|
||||
if (nodeLocation == null)
|
||||
continue;
|
||||
|
||||
Vec3 location = nodeLocation.getLocation();
|
||||
if (location.distanceTo(camera) > 50)
|
||||
continue;
|
||||
|
||||
Vec3 v1 = location.add(0, 3 / 16f, 0);
|
||||
Vec3 v2 = v1.add(node.normal.scale(0.75f));
|
||||
CreateClient.OUTLINER.showLine(Integer.valueOf(node.netId), v1, v2)
|
||||
.colored(Color.mixColors(Color.WHITE, color, .5f))
|
||||
.lineWidth(1 / 8f);
|
||||
|
||||
Map<TrackNode, TrackEdge> map = connectionsByNode.get(node);
|
||||
if (map == null)
|
||||
continue;
|
||||
|
||||
int hashCode = node.hashCode();
|
||||
for (Entry<TrackNode, TrackEdge> entry : map.entrySet()) {
|
||||
TrackNode other = entry.getKey();
|
||||
|
||||
if (other.hashCode() > hashCode)
|
||||
continue;
|
||||
|
||||
TrackEdge edge = entry.getValue();
|
||||
if (!edge.isTurn()) {
|
||||
CreateClient.OUTLINER
|
||||
.showLine(edge, edge.getPosition(node, other, 0), edge.getPosition(node, other, 1))
|
||||
.colored(color)
|
||||
.lineWidth(1 / 16f);
|
||||
continue;
|
||||
}
|
||||
|
||||
Vec3 previous = null;
|
||||
BezierConnection turn = edge.getTurn();
|
||||
for (int i = 0; i <= turn.getSegmentCount(); i++) {
|
||||
Vec3 current = edge.getPosition(node, other, i * 1f / turn.getSegmentCount());
|
||||
if (previous != null)
|
||||
CreateClient.OUTLINER.showLine(previous, previous, current)
|
||||
.colored(color)
|
||||
.lineWidth(1 / 16f);
|
||||
previous = current;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
package com.simibubi.create.content.logistics.trains;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
import com.simibubi.create.foundation.utility.Couple;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.network.NetworkEvent.Context;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
public class TrackGraphSync {
|
||||
|
||||
//
|
||||
|
||||
public void nodeAdded(TrackGraph graph, TrackNode node) {
|
||||
flushPacket(graph.id);
|
||||
currentPacket.addedNodes.put(node.getNetId(), Pair.of(node.getLocation(), node.getNormal()));
|
||||
}
|
||||
|
||||
public void edgeAdded(TrackGraph graph, TrackNode node1, TrackNode node2, TrackEdge edge) {
|
||||
flushPacket(graph.id);
|
||||
currentPacket.addedEdges.add(Pair.of(Couple.create(node1.getNetId(), node2.getNetId()), edge));
|
||||
}
|
||||
|
||||
public void nodeRemoved(TrackGraph graph, TrackNode node) {
|
||||
flushPacket(graph.id);
|
||||
if (currentPacket.addedNodes.remove(node.getNetId()) == null)
|
||||
currentPacket.removedNodes.add(node.getNetId());
|
||||
}
|
||||
|
||||
public void graphSplit(TrackGraph graph, Set<TrackGraph> additional) {
|
||||
flushPacket(graph.id);
|
||||
additional.forEach(rg -> currentPacket.splitSubGraphs.put(rg.nodesById.keySet()
|
||||
.stream()
|
||||
.findFirst()
|
||||
.get(), rg.id));
|
||||
}
|
||||
|
||||
public void graphRemoved(TrackGraph graph) {
|
||||
flushPacket(graph.id);
|
||||
currentPacket.delete = true;
|
||||
}
|
||||
|
||||
public void finish() {
|
||||
flushPacket(null);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private RailGraphSyncPacket currentPacket;
|
||||
|
||||
public void sendFullGraphTo(TrackGraph graph, ServerPlayer player) {
|
||||
// TODO ensure packet size limit
|
||||
|
||||
RailGraphSyncPacket packet = new RailGraphSyncPacket(graph.id);
|
||||
for (TrackNode node : graph.nodes.values()) {
|
||||
packet.addedNodes.put(node.getNetId(), Pair.of(node.getLocation(), node.getNormal()));
|
||||
if (!graph.connectionsByNode.containsKey(node))
|
||||
continue;
|
||||
graph.connectionsByNode.get(node)
|
||||
.forEach((node2, edge) -> packet.addedEdges
|
||||
.add(Pair.of(Couple.create(node.getNetId(), node2.getNetId()), edge)));
|
||||
}
|
||||
|
||||
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), packet);
|
||||
}
|
||||
|
||||
private void flushPacket(@Nullable UUID graphId) {
|
||||
if (currentPacket != null) {
|
||||
if (currentPacket.graphId.equals(graphId))
|
||||
return;
|
||||
AllPackets.channel.send(PacketDistributor.ALL.noArg(), currentPacket);
|
||||
currentPacket = null;
|
||||
}
|
||||
|
||||
if (graphId != null)
|
||||
currentPacket = new RailGraphSyncPacket(graphId);
|
||||
}
|
||||
|
||||
public static class RailGraphSyncPacket extends SimplePacketBase {
|
||||
|
||||
UUID graphId;
|
||||
Map<Integer, Pair<TrackNodeLocation, Vec3>> addedNodes;
|
||||
List<Pair<Couple<Integer>, TrackEdge>> addedEdges;
|
||||
List<Integer> removedNodes;
|
||||
Map<Integer, UUID> splitSubGraphs;
|
||||
boolean delete;
|
||||
|
||||
public RailGraphSyncPacket(UUID graphId) {
|
||||
this.graphId = graphId;
|
||||
addedNodes = new HashMap<>();
|
||||
addedEdges = new ArrayList<>();
|
||||
removedNodes = new ArrayList<>();
|
||||
splitSubGraphs = new HashMap<>();
|
||||
delete = false;
|
||||
}
|
||||
|
||||
public RailGraphSyncPacket(FriendlyByteBuf buffer) {
|
||||
int size;
|
||||
|
||||
graphId = buffer.readUUID();
|
||||
delete = buffer.readBoolean();
|
||||
|
||||
if (delete)
|
||||
return;
|
||||
|
||||
addedNodes = new HashMap<>();
|
||||
addedEdges = new ArrayList<>();
|
||||
removedNodes = new ArrayList<>();
|
||||
splitSubGraphs = new HashMap<>();
|
||||
|
||||
size = buffer.readVarInt();
|
||||
for (int i = 0; i < size; i++)
|
||||
removedNodes.add(buffer.readVarInt());
|
||||
|
||||
size = buffer.readVarInt();
|
||||
for (int i = 0; i < size; i++)
|
||||
addedNodes.put(buffer.readVarInt(),
|
||||
Pair.of(TrackNodeLocation.fromPackedPos(buffer.readBlockPos()), VecHelper.read(buffer)));
|
||||
|
||||
size = buffer.readVarInt();
|
||||
for (int i = 0; i < size; i++)
|
||||
addedEdges.add(Pair.of(Couple.create(buffer::readVarInt), TrackEdge.read(buffer)));
|
||||
|
||||
size = buffer.readVarInt();
|
||||
for (int i = 0; i < size; i++)
|
||||
splitSubGraphs.put(buffer.readVarInt(), buffer.readUUID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeUUID(graphId);
|
||||
buffer.writeBoolean(delete);
|
||||
if (delete)
|
||||
return;
|
||||
|
||||
buffer.writeVarInt(removedNodes.size());
|
||||
removedNodes.forEach(buffer::writeVarInt);
|
||||
|
||||
buffer.writeVarInt(addedNodes.size());
|
||||
addedNodes.forEach((node, loc) -> {
|
||||
buffer.writeVarInt(node);
|
||||
buffer.writeBlockPos(new BlockPos(loc.getFirst()));
|
||||
VecHelper.write(loc.getSecond(), buffer);
|
||||
});
|
||||
|
||||
buffer.writeVarInt(addedEdges.size());
|
||||
addedEdges.forEach(pair -> {
|
||||
pair.getFirst()
|
||||
.forEach(buffer::writeVarInt);
|
||||
pair.getSecond()
|
||||
.write(buffer);
|
||||
});
|
||||
|
||||
buffer.writeVarInt(splitSubGraphs.size());
|
||||
splitSubGraphs.forEach((node, uuid) -> {
|
||||
buffer.writeVarInt(node);
|
||||
buffer.writeUUID(uuid);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Supplier<Context> context) {
|
||||
context.get()
|
||||
.enqueueWork(() -> {
|
||||
GlobalRailwayManager manager = CreateClient.RAILWAYS;
|
||||
TrackGraph railGraph = manager.getOrCreateGraph(graphId);
|
||||
|
||||
if (delete) {
|
||||
manager.removeGraph(railGraph);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int nodeId : removedNodes) {
|
||||
TrackNode node = railGraph.getNode(nodeId);
|
||||
if (node != null)
|
||||
railGraph.removeNode(node.getLocation());
|
||||
}
|
||||
|
||||
for (Entry<Integer, Pair<TrackNodeLocation, Vec3>> entry : addedNodes.entrySet())
|
||||
railGraph.createSpecificNode(entry.getValue()
|
||||
.getFirst(), entry.getKey(),
|
||||
entry.getValue()
|
||||
.getSecond());
|
||||
|
||||
for (Pair<Couple<Integer>, TrackEdge> pair : addedEdges) {
|
||||
Couple<TrackNode> nodes = pair.getFirst()
|
||||
.map(railGraph::getNode);
|
||||
if (nodes.getFirst() != null && nodes.getSecond() != null)
|
||||
railGraph.putConnection(nodes.getFirst(), nodes.getSecond(), pair.getSecond());
|
||||
}
|
||||
|
||||
if (!splitSubGraphs.isEmpty())
|
||||
railGraph.findDisconnectedGraphs(splitSubGraphs)
|
||||
.forEach(manager::putGraph);
|
||||
|
||||
});
|
||||
context.get()
|
||||
.setPacketHandled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.simibubi.create.content.logistics.trains;
|
||||
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class TrackNode {
|
||||
|
||||
int netId;
|
||||
Vec3 normal;
|
||||
TrackNodeLocation location;
|
||||
|
||||
public TrackNode(TrackNodeLocation location, int netId, Vec3 normal) {
|
||||
this.location = location;
|
||||
this.netId = netId;
|
||||
this.normal = normal;
|
||||
}
|
||||
|
||||
public TrackNodeLocation getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public int getNetId() {
|
||||
return netId;
|
||||
}
|
||||
|
||||
public Vec3 getNormal() {
|
||||
return normal;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package com.simibubi.create.content.logistics.trains;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class TrackNodeLocation extends Vec3i {
|
||||
|
||||
public TrackNodeLocation(Vec3 vec) {
|
||||
this(vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
public TrackNodeLocation(double p_121865_, double p_121866_, double p_121867_) {
|
||||
super(Math.round(p_121865_ * 2), Math.floor(p_121866_ * 2), Math.round(p_121867_ * 2));
|
||||
}
|
||||
|
||||
public static TrackNodeLocation fromPackedPos(BlockPos bufferPos) {
|
||||
return new TrackNodeLocation(bufferPos);
|
||||
}
|
||||
|
||||
private TrackNodeLocation(BlockPos readBlockPos) {
|
||||
super(readBlockPos.getX(), readBlockPos.getY(), readBlockPos.getZ());
|
||||
}
|
||||
|
||||
public Vec3 getLocation() {
|
||||
return new Vec3(getX() / 2f, getY() / 2f, getZ() / 2f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object pOther) {
|
||||
return super.equals(pOther);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (this.getY() + this.getZ() * 31) * 31 + this.getX();
|
||||
}
|
||||
|
||||
public static class DiscoveredLocation extends TrackNodeLocation {
|
||||
|
||||
BezierConnection turn = null;
|
||||
Vec3 normal;
|
||||
|
||||
public DiscoveredLocation(double p_121865_, double p_121866_, double p_121867_) {
|
||||
super(p_121865_, p_121866_, p_121867_);
|
||||
}
|
||||
|
||||
public DiscoveredLocation(Vec3 vec) {
|
||||
super(vec);
|
||||
}
|
||||
|
||||
public DiscoveredLocation viaTurn(BezierConnection turn) {
|
||||
this.turn = turn;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DiscoveredLocation withNormal(Vec3 normal) {
|
||||
this.normal = normal;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean connectedViaTurn() {
|
||||
return turn != null;
|
||||
}
|
||||
|
||||
public BezierConnection getTurn() {
|
||||
return turn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,374 @@
|
|||
package com.simibubi.create.content.logistics.trains;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
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.TrackBlock;
|
||||
import com.simibubi.create.content.logistics.trains.track.TrackBlock.TrackShape;
|
||||
import com.simibubi.create.content.logistics.trains.track.TrackTileEntity;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class TrackPropagator {
|
||||
|
||||
static class FrontierEntry {
|
||||
BlockPos prevPos;
|
||||
DiscoveredLocation prevNode;
|
||||
BlockPos currentPos;
|
||||
DiscoveredLocation currentNode;
|
||||
DiscoveredLocation parentNode;
|
||||
|
||||
public FrontierEntry(BlockPos previousPos, BlockPos pos, DiscoveredLocation location) {
|
||||
this(null, previousPos, null, pos, location);
|
||||
}
|
||||
|
||||
public FrontierEntry(DiscoveredLocation parent, BlockPos previousPos, DiscoveredLocation previousNode,
|
||||
BlockPos pos, DiscoveredLocation location) {
|
||||
parentNode = parent;
|
||||
prevPos = previousPos;
|
||||
prevNode = previousNode;
|
||||
currentPos = pos;
|
||||
currentNode = location;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void onRailRemoved(LevelAccessor reader, BlockPos pos, BlockState state) {
|
||||
List<Pair<BlockPos, DiscoveredLocation>> ends = getEnds(reader, pos, state, null, false);
|
||||
TrackGraph foundGraph = null;
|
||||
GlobalRailwayManager manager = Create.RAILWAYS;
|
||||
TrackGraphSync sync = manager.sync;
|
||||
|
||||
for (Pair<BlockPos, DiscoveredLocation> removedEnd : ends) {
|
||||
DiscoveredLocation removedLocation = removedEnd.getSecond();
|
||||
if (foundGraph == null)
|
||||
foundGraph = manager.getGraph(reader, removedLocation);
|
||||
if (foundGraph != null) {
|
||||
TrackNode removedNode = foundGraph.locateNode(removedLocation);
|
||||
if (removedNode != null) {
|
||||
foundGraph.removeNode(removedLocation);
|
||||
sync.nodeRemoved(foundGraph, removedNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (foundGraph != null && foundGraph.isEmpty()) {
|
||||
manager.removeGraph(foundGraph);
|
||||
sync.graphRemoved(foundGraph);
|
||||
}
|
||||
|
||||
Set<TrackGraph> toUpdate = new HashSet<>();
|
||||
for (Pair<BlockPos, DiscoveredLocation> removedEnd : ends) {
|
||||
BlockPos adjPos = removedEnd.getFirst();
|
||||
BlockState adjState = reader.getBlockState(adjPos);
|
||||
|
||||
if (!getEnds(reader, adjPos, adjState, removedEnd.getSecond(), true).isEmpty())
|
||||
toUpdate.add(onRailAdded(reader, adjPos, adjState));
|
||||
}
|
||||
|
||||
for (TrackGraph railGraph : toUpdate)
|
||||
manager.updateSplitGraph(railGraph);
|
||||
|
||||
sync.finish();
|
||||
manager.markTracksDirty();
|
||||
}
|
||||
|
||||
public static TrackGraph onRailAdded(LevelAccessor reader, BlockPos pos, BlockState state) {
|
||||
// 1. Remove all immediately reachable node locations
|
||||
|
||||
GlobalRailwayManager manager = Create.RAILWAYS;
|
||||
TrackGraphSync sync = manager.sync;
|
||||
List<FrontierEntry> frontier = new ArrayList<>();
|
||||
Set<DiscoveredLocation> visited = new HashSet<>();
|
||||
Set<TrackGraph> connectedGraphs = new HashSet<>();
|
||||
addInitialEndsOf(reader, pos, state, frontier, false);
|
||||
|
||||
int emergencyExit = 1000;
|
||||
while (!frontier.isEmpty()) {
|
||||
if (emergencyExit-- == 0)
|
||||
break;
|
||||
|
||||
FrontierEntry entry = frontier.remove(0);
|
||||
List<Pair<BlockPos, DiscoveredLocation>> ends = findReachableEnds(reader, entry);
|
||||
TrackGraph graph = manager.getGraph(reader, entry.currentNode);
|
||||
if (graph != null) {
|
||||
TrackNode node = graph.locateNode(entry.currentNode);
|
||||
graph.removeNode(entry.currentNode);
|
||||
sync.nodeRemoved(graph, node);
|
||||
connectedGraphs.add(graph);
|
||||
continue;
|
||||
}
|
||||
|
||||
continueSearch(frontier, visited, entry, ends);
|
||||
}
|
||||
|
||||
frontier.clear();
|
||||
visited.clear();
|
||||
|
||||
TrackGraph graph = null;
|
||||
|
||||
// Remove empty graphs
|
||||
for (Iterator<TrackGraph> iterator = connectedGraphs.iterator(); iterator.hasNext();) {
|
||||
TrackGraph railGraph = iterator.next();
|
||||
if (!railGraph.isEmpty() || connectedGraphs.size() == 1)
|
||||
continue;
|
||||
manager.removeGraph(railGraph);
|
||||
sync.graphRemoved(railGraph);
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
// Merge graphs if more than 1
|
||||
if (connectedGraphs.size() > 1) {
|
||||
for (TrackGraph other : connectedGraphs)
|
||||
if (graph == null)
|
||||
graph = other;
|
||||
else {
|
||||
other.transferAll(graph);
|
||||
manager.removeGraph(other);
|
||||
sync.graphRemoved(other);
|
||||
}
|
||||
} else if (connectedGraphs.size() == 1) {
|
||||
graph = connectedGraphs.stream()
|
||||
.findFirst()
|
||||
.get();
|
||||
} else
|
||||
manager.putGraph(graph = new TrackGraph());
|
||||
|
||||
DiscoveredLocation startNode = null;
|
||||
List<BlockPos> startPositions = new ArrayList<>();
|
||||
|
||||
// 2. Find the first graph node candidate nearby
|
||||
|
||||
addInitialEndsOf(reader, pos, state, frontier, true);
|
||||
|
||||
emergencyExit = 1000;
|
||||
while (!frontier.isEmpty()) {
|
||||
if (emergencyExit-- == 0)
|
||||
break;
|
||||
|
||||
FrontierEntry entry = frontier.remove(0);
|
||||
|
||||
// CreateClient.OUTLINER
|
||||
// .showAABB(entry.currentNode, new AABB(entry.currentNode.getLocation(), entry.currentNode.getLocation()
|
||||
// .add(0, 2, 0)), 120)
|
||||
// .colored(Color.GREEN)
|
||||
// .lineWidth(1 / 16f);
|
||||
// CreateClient.OUTLINER.showAABB(entry.currentPos, new AABB(entry.currentPos).contract(0, 1, 0), 120)
|
||||
// .colored(0x7777ff)
|
||||
// .lineWidth(1 / 16f);
|
||||
// if (entry.prevPos != null) {
|
||||
// CreateClient.OUTLINER.showAABB(entry.prevPos, new AABB(entry.prevPos).contract(0, 1, 0), 120)
|
||||
// .colored(0x3333aa)
|
||||
// .lineWidth(1 / 16f);
|
||||
// }
|
||||
|
||||
List<Pair<BlockPos, DiscoveredLocation>> ends = findReachableEnds(reader, entry);
|
||||
if (isValidGraphNodeLocation(entry.currentNode, ends)) {
|
||||
startNode = entry.currentNode;
|
||||
startPositions.add(entry.prevPos);
|
||||
startPositions.add(entry.currentPos);
|
||||
break;
|
||||
}
|
||||
|
||||
continueSearch(frontier, visited, entry, ends);
|
||||
}
|
||||
|
||||
frontier.clear();
|
||||
if (graph.createNode(startNode))
|
||||
sync.nodeAdded(graph, graph.locateNode(startNode));
|
||||
|
||||
// CreateClient.OUTLINER.showAABB(graph, new AABB(startNode.getLocation(), startNode.getLocation()
|
||||
// .add(0, 2, 0)), 20)
|
||||
// .lineWidth(1 / 32f);
|
||||
|
||||
for (BlockPos position : startPositions)
|
||||
frontier.add(new FrontierEntry(startNode, null, null, position, startNode));
|
||||
|
||||
// 3. Build up the graph via all connected nodes
|
||||
|
||||
emergencyExit = 1000;
|
||||
while (!frontier.isEmpty()) {
|
||||
if (emergencyExit-- == 0)
|
||||
break;
|
||||
|
||||
FrontierEntry entry = frontier.remove(0);
|
||||
DiscoveredLocation parentNode = entry.parentNode;
|
||||
List<Pair<BlockPos, DiscoveredLocation>> ends = findReachableEnds(reader, entry);
|
||||
|
||||
if (isValidGraphNodeLocation(entry.currentNode, ends) && entry.currentNode != startNode) {
|
||||
boolean nodeIsNew = graph.createNode(entry.currentNode);
|
||||
if (nodeIsNew)
|
||||
sync.nodeAdded(graph, graph.locateNode(entry.currentNode));
|
||||
graph.connectNodes(parentNode, entry.currentNode, new TrackEdge(entry.currentNode.getTurn()));
|
||||
parentNode = entry.currentNode;
|
||||
if (!nodeIsNew)
|
||||
continue;
|
||||
}
|
||||
|
||||
continueSearchWithParent(frontier, entry, parentNode, ends);
|
||||
}
|
||||
|
||||
sync.finish();
|
||||
manager.markTracksDirty();
|
||||
return graph;
|
||||
}
|
||||
|
||||
private static void addInitialEndsOf(LevelAccessor reader, BlockPos pos, BlockState state,
|
||||
List<FrontierEntry> frontier, boolean ignoreTurns) {
|
||||
for (Pair<BlockPos, DiscoveredLocation> initial : getEnds(reader, pos, state, null, ignoreTurns))
|
||||
frontier.add(new FrontierEntry(initial.getFirst(), pos, initial.getSecond()));
|
||||
}
|
||||
|
||||
private static List<Pair<BlockPos, DiscoveredLocation>> findReachableEnds(LevelAccessor reader,
|
||||
FrontierEntry entry) {
|
||||
BlockState currentState = reader.getBlockState(entry.currentPos);
|
||||
List<Pair<BlockPos, DiscoveredLocation>> ends = new ArrayList<>();
|
||||
|
||||
if (entry.prevNode != null) {
|
||||
BlockPos prevPos = entry.prevPos;
|
||||
|
||||
// PrevPos correction after a turn
|
||||
if (entry.currentNode.connectedViaTurn()) {
|
||||
boolean slope = false;
|
||||
if (currentState.getBlock() instanceof ITrackBlock track)
|
||||
slope = track.getTrackAxis(reader, entry.currentPos, currentState).y != 0;
|
||||
BlockPos offset = new BlockPos(VecHelper.getCenterOf(entry.currentPos)
|
||||
.subtract(entry.currentNode.getLocation()
|
||||
.add(0, slope ? 0 : .5f, 0))
|
||||
.scale(-2));
|
||||
prevPos = entry.currentPos.offset(offset);
|
||||
}
|
||||
|
||||
for (Pair<BlockPos, DiscoveredLocation> pair : getEnds(reader, prevPos, reader.getBlockState(prevPos),
|
||||
entry.currentNode, false))
|
||||
if (!pair.getSecond()
|
||||
.equals(entry.prevNode))
|
||||
ends.add(pair);
|
||||
}
|
||||
|
||||
ends.addAll(getEnds(reader, entry.currentPos, currentState, entry.currentNode, false));
|
||||
return ends;
|
||||
}
|
||||
|
||||
private static void continueSearch(List<FrontierEntry> frontier, Set<DiscoveredLocation> visited,
|
||||
FrontierEntry entry, List<Pair<BlockPos, DiscoveredLocation>> ends) {
|
||||
for (Pair<BlockPos, DiscoveredLocation> pair : ends)
|
||||
if (visited.add(pair.getSecond()))
|
||||
frontier.add(
|
||||
new FrontierEntry(null, entry.currentPos, entry.currentNode, pair.getFirst(), pair.getSecond()));
|
||||
}
|
||||
|
||||
private static void continueSearchWithParent(List<FrontierEntry> frontier, FrontierEntry entry,
|
||||
DiscoveredLocation parentNode, List<Pair<BlockPos, DiscoveredLocation>> ends) {
|
||||
for (Pair<BlockPos, DiscoveredLocation> pair : ends)
|
||||
frontier.add(
|
||||
new FrontierEntry(parentNode, entry.currentPos, entry.currentNode, pair.getFirst(), pair.getSecond()));
|
||||
}
|
||||
|
||||
public static boolean isValidGraphNodeLocation(DiscoveredLocation location,
|
||||
List<Pair<BlockPos, DiscoveredLocation>> next) {
|
||||
if (next.size() != 1)
|
||||
return true;
|
||||
if (location.connectedViaTurn())
|
||||
return true;
|
||||
|
||||
DiscoveredLocation nextLocation = next.iterator()
|
||||
.next()
|
||||
.getSecond();
|
||||
|
||||
if (nextLocation.connectedViaTurn())
|
||||
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));
|
||||
if (centeredX && !centeredZ)
|
||||
return ((int) Math.round(vec.z)) % 16 == 0;
|
||||
return ((int) Math.round(vec.x)) % 16 == 0;
|
||||
}
|
||||
|
||||
// TODO ITrackBlock
|
||||
public static List<Pair<BlockPos, DiscoveredLocation>> getEnds(LevelReader reader, BlockPos pos, BlockState state,
|
||||
@Nullable DiscoveredLocation fromEnd, boolean ignoreTurns) {
|
||||
Vec3 center = VecHelper.getCenterOf(pos);
|
||||
List<Pair<BlockPos, DiscoveredLocation>> list = new ArrayList<>();
|
||||
|
||||
if (!(state.getBlock() instanceof TrackBlock))
|
||||
return list;
|
||||
|
||||
BlockEntity blockEntity = reader.getBlockEntity(pos);
|
||||
if (state.getValue(TrackBlock.HAS_TURN) && blockEntity instanceof TrackTileEntity && !ignoreTurns) {
|
||||
TrackTileEntity trackTileEntity = (TrackTileEntity) blockEntity;
|
||||
trackTileEntity.getConnections()
|
||||
.forEach(map -> map.forEach((connectedPos, bc) -> addToSet(fromEnd, list,
|
||||
(d, b) -> d == 1 ? Vec3.atLowerCornerOf(bc.tePositions.get(b)) : bc.starts.get(b), bc.normals::get,
|
||||
bc)));
|
||||
}
|
||||
|
||||
TrackShape shape = state.getValue(TrackBlock.SHAPE);
|
||||
if (shape != TrackShape.NONE)
|
||||
addToSet(fromEnd, list, (d, b) -> shape.getAxis()
|
||||
.scale(b ? d : -d)
|
||||
.add(center)
|
||||
.add(0, shape.getAxis().y == 0 ? -.5 : 0, 0), b -> shape.getNormal(), null);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void addToSet(DiscoveredLocation fromEnd, List<Pair<BlockPos, DiscoveredLocation>> list,
|
||||
BiFunction<Double, Boolean, Vec3> offsetFactory, Function<Boolean, Vec3> normalFactory,
|
||||
BezierConnection viaTurn) {
|
||||
|
||||
DiscoveredLocation firstLocation = new DiscoveredLocation(offsetFactory.apply(0.5d, true));
|
||||
DiscoveredLocation secondLocation = new DiscoveredLocation(offsetFactory.apply(0.5d, false));
|
||||
|
||||
Pair<BlockPos, DiscoveredLocation> firstNode =
|
||||
Pair.of(new BlockPos(offsetFactory.apply(1.0d, true)), firstLocation.viaTurn(viaTurn)
|
||||
.withNormal(normalFactory.apply(true)));
|
||||
Pair<BlockPos, DiscoveredLocation> secondNode =
|
||||
Pair.of(new BlockPos(offsetFactory.apply(1.0d, false)), secondLocation.viaTurn(viaTurn)
|
||||
.withNormal(normalFactory.apply(false)));
|
||||
|
||||
boolean skipFirst = false;
|
||||
boolean skipSecond = false;
|
||||
|
||||
if (fromEnd != null) {
|
||||
boolean equalsFirst = firstNode.getSecond()
|
||||
.equals(fromEnd);
|
||||
boolean equalsSecond = secondNode.getSecond()
|
||||
.equals(fromEnd);
|
||||
|
||||
// not reachable from this end, crossover rail
|
||||
if (!equalsFirst && !equalsSecond)
|
||||
return;
|
||||
|
||||
if (equalsFirst)
|
||||
skipFirst = true;
|
||||
if (equalsSecond)
|
||||
skipSecond = true;
|
||||
}
|
||||
|
||||
if (!skipFirst)
|
||||
list.add(firstNode);
|
||||
if (!skipSecond)
|
||||
list.add(secondNode);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.simibubi.create.content.logistics.trains;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.level.saveddata.SavedData;
|
||||
|
||||
public class TrackSavedData extends SavedData {
|
||||
|
||||
private Map<UUID, TrackGraph> trackNetworks = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public CompoundTag save(CompoundTag nbt) {
|
||||
nbt.put("RailGraphs", NBTHelper.writeCompoundList(Create.RAILWAYS.trackNetworks.values(), TrackGraph::write));
|
||||
return nbt;
|
||||
}
|
||||
|
||||
private static TrackSavedData load(CompoundTag nbt) {
|
||||
TrackSavedData sd = new TrackSavedData();
|
||||
sd.trackNetworks = new HashMap<>();
|
||||
NBTHelper.iterateCompoundList(nbt.getList("RailGraphs", Tag.TAG_COMPOUND), c -> {
|
||||
TrackGraph graph = TrackGraph.read(c);
|
||||
sd.trackNetworks.put(graph.id, graph);
|
||||
});
|
||||
return sd;
|
||||
}
|
||||
|
||||
public Map<UUID, TrackGraph> getTrackNetworks() {
|
||||
return trackNetworks;
|
||||
}
|
||||
|
||||
private TrackSavedData() {}
|
||||
|
||||
public static TrackSavedData load(MinecraftServer server) {
|
||||
return server.overworld()
|
||||
.getDataStorage()
|
||||
.computeIfAbsent(TrackSavedData::load, TrackSavedData::new, "create_tracks");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,272 @@
|
|||
package com.simibubi.create.content.logistics.trains.entity;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang3.mutable.MutableDouble;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
|
||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
||||
import com.simibubi.create.content.logistics.trains.entity.MovingPoint.ITrackSelector;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.Couple;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class Carriage {
|
||||
|
||||
public static final AtomicInteger netIdGenerator = new AtomicInteger();
|
||||
|
||||
public Train train;
|
||||
public CarriageContraption contraption;
|
||||
public int bogeySpacing;
|
||||
public int id;
|
||||
|
||||
WeakReference<CarriageContraptionEntity> entity;
|
||||
Couple<CarriageBogey> bogeys;
|
||||
|
||||
public Carriage(CarriageBogey bogey1, @Nullable CarriageBogey bogey2, int bogeySpacing) {
|
||||
this.bogeySpacing = bogeySpacing;
|
||||
this.bogeys = Couple.create(bogey1, bogey2);
|
||||
this.entity = new WeakReference<>(null);
|
||||
this.id = netIdGenerator.incrementAndGet();
|
||||
}
|
||||
|
||||
public void setTrain(Train train) {
|
||||
this.train = train;
|
||||
}
|
||||
|
||||
public void setContraption(CarriageContraption contraption) {
|
||||
this.contraption = contraption;
|
||||
contraption.setCarriage(this);
|
||||
}
|
||||
|
||||
public double travel(Level level, double distance, @Nullable Function<MovingPoint, ITrackSelector> control) {
|
||||
Vec3 leadingAnchor = leadingBogey().anchorPosition;
|
||||
Vec3 trailingAnchor = trailingBogey().anchorPosition;
|
||||
boolean onTwoBogeys = isOnTwoBogeys();
|
||||
double stress = onTwoBogeys ? bogeySpacing - leadingAnchor.distanceTo(trailingAnchor) : 0;
|
||||
|
||||
// positive stress: points should move apart
|
||||
// negative stress: points should move closer
|
||||
|
||||
double leadingBogeyModifier = 0.5d;
|
||||
double trailingBogeyModifier = -0.5d;
|
||||
double leadingPointModifier = 0.5d;
|
||||
double trailingPointModifier = -0.5d;
|
||||
|
||||
MutableObject<MovingPoint> previous = new MutableObject<>();
|
||||
MutableDouble distanceMoved = new MutableDouble(distance);
|
||||
|
||||
bogeys.forEachWithContext((bogey, firstBogey) -> {
|
||||
if (!firstBogey && !onTwoBogeys)
|
||||
return;
|
||||
|
||||
double bogeyCorrection = stress * (firstBogey ? leadingBogeyModifier : trailingBogeyModifier);
|
||||
double bogeyStress = bogey.getStress();
|
||||
|
||||
bogey.points.forEachWithContext((point, first) -> {
|
||||
MovingPoint prevPoint = previous.getValue();
|
||||
ITrackSelector trackSelector =
|
||||
prevPoint == null ? control == null ? point.random() : control.apply(point)
|
||||
: point.follow(prevPoint);
|
||||
|
||||
double correction = bogeyStress * (first ? leadingPointModifier : trailingPointModifier);
|
||||
double toMove = distanceMoved.getValue();
|
||||
double moved = point.travel(toMove, trackSelector);
|
||||
point.travel(correction + bogeyCorrection, trackSelector);
|
||||
|
||||
distanceMoved.setValue(moved);
|
||||
previous.setValue(point);
|
||||
});
|
||||
|
||||
bogey.updateAnchorPosition();
|
||||
});
|
||||
|
||||
tickEntity(level);
|
||||
return distanceMoved.getValue();
|
||||
}
|
||||
|
||||
public void createEntity(Level level) {
|
||||
contraption.startMoving(level);
|
||||
CarriageContraptionEntity entity = CarriageContraptionEntity.create(level, contraption);
|
||||
Vec3 pos = leadingBogey().anchorPosition;
|
||||
entity.setPos(pos);
|
||||
entity.setInitialOrientation(contraption.getAssemblyDirection()
|
||||
.getClockWise());
|
||||
level.addFreshEntity(entity);
|
||||
this.entity = new WeakReference<>(entity);
|
||||
}
|
||||
|
||||
public ChunkPos getChunk() {
|
||||
return new ChunkPos(new BlockPos(leadingBogey().anchorPosition));
|
||||
}
|
||||
|
||||
protected void tickEntity(Level level) {
|
||||
CarriageContraptionEntity entity = this.entity.get();
|
||||
if (entity == null) {
|
||||
if (CarriageEntityHandler.isActiveChunk(level, getChunk()))
|
||||
createEntity(level);
|
||||
} else {
|
||||
CarriageEntityHandler.validateCarriageEntity(entity);
|
||||
if (!entity.isAlive()) {
|
||||
this.entity.clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
entity = this.entity.get();
|
||||
if (entity == null)
|
||||
return;
|
||||
if (!entity.level.isClientSide)
|
||||
moveEntity(entity);
|
||||
}
|
||||
|
||||
public void moveEntity(CarriageContraptionEntity entity) {
|
||||
Vec3 positionVec = isOnTwoBogeys() ? leadingBogey().anchorPosition
|
||||
: leadingBogey().leading()
|
||||
.getPosition();
|
||||
Vec3 coupledVec = isOnTwoBogeys() ? trailingBogey().anchorPosition
|
||||
: leadingBogey().trailing()
|
||||
.getPosition();
|
||||
|
||||
double diffX = positionVec.x - coupledVec.x;
|
||||
double diffY = positionVec.y - coupledVec.y;
|
||||
double diffZ = positionVec.z - coupledVec.z;
|
||||
|
||||
entity.setPos(leadingBogey().anchorPosition);
|
||||
entity.prevYaw = entity.yaw;
|
||||
entity.prevPitch = entity.pitch;
|
||||
entity.yaw = (float) (Mth.atan2(diffZ, diffX) * 180 / Math.PI) + 180;
|
||||
entity.pitch = (float) (Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ)) * 180 / Math.PI) * -1;
|
||||
}
|
||||
|
||||
public void discardEntity() {
|
||||
CarriageContraptionEntity entity = this.entity.get();
|
||||
if (entity == null)
|
||||
return;
|
||||
entity.discard();
|
||||
}
|
||||
|
||||
public MovingPoint getLeadingPoint() {
|
||||
return leadingBogey().leading();
|
||||
}
|
||||
|
||||
public MovingPoint getTrailingPoint() {
|
||||
return trailingBogey().trailing();
|
||||
}
|
||||
|
||||
public CarriageBogey leadingBogey() {
|
||||
return bogeys.getFirst();
|
||||
}
|
||||
|
||||
public CarriageBogey trailingBogey() {
|
||||
return isOnTwoBogeys() ? bogeys.getSecond() : leadingBogey();
|
||||
}
|
||||
|
||||
public boolean isOnTwoBogeys() {
|
||||
return bogeys.getSecond() != null;
|
||||
}
|
||||
|
||||
public static class CarriageBogey {
|
||||
|
||||
IBogeyBlock type;
|
||||
Couple<MovingPoint> points;
|
||||
Vec3 anchorPosition;
|
||||
|
||||
LerpedFloat wheelAngle;
|
||||
LerpedFloat yaw;
|
||||
LerpedFloat pitch;
|
||||
|
||||
public Vec3 leadingCouplingAnchor;
|
||||
public Vec3 trailingCouplingAnchor;
|
||||
|
||||
public CarriageBogey(IBogeyBlock type, MovingPoint point, MovingPoint point2) {
|
||||
this.type = type;
|
||||
points = Couple.create(point, point2);
|
||||
wheelAngle = LerpedFloat.angular();
|
||||
yaw = LerpedFloat.angular();
|
||||
pitch = LerpedFloat.angular();
|
||||
updateAnchorPosition();
|
||||
}
|
||||
|
||||
public void updateAngles(double distanceMoved) {
|
||||
double angleDiff = 360 * distanceMoved / (Math.PI * 2 * type.getWheelRadius());
|
||||
Vec3 positionVec = leading().getPosition();
|
||||
Vec3 coupledVec = trailing().getPosition();
|
||||
double diffX = positionVec.x - coupledVec.x;
|
||||
double diffY = positionVec.y - coupledVec.y;
|
||||
double diffZ = positionVec.z - coupledVec.z;
|
||||
float yRot = AngleHelper.deg(Mth.atan2(diffZ, diffX)) + 90;
|
||||
float xRot = AngleHelper.deg(Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ)));
|
||||
wheelAngle.setValue((wheelAngle.getValue() - angleDiff) % 360);
|
||||
pitch.setValue(xRot);
|
||||
yaw.setValue(-yRot);
|
||||
}
|
||||
|
||||
public MovingPoint leading() {
|
||||
return points.getFirst();
|
||||
}
|
||||
|
||||
public MovingPoint trailing() {
|
||||
return points.getSecond();
|
||||
}
|
||||
|
||||
public double getStress() {
|
||||
return type.getWheelPointSpacing() - leading().getPosition()
|
||||
.distanceTo(trailing().getPosition());
|
||||
}
|
||||
|
||||
public void updateAnchorPosition() {
|
||||
anchorPosition = points.getFirst()
|
||||
.getPosition()
|
||||
.add(points.getSecond()
|
||||
.getPosition())
|
||||
.scale(.5);
|
||||
}
|
||||
|
||||
public void updateCouplingAnchor(Vec3 entityPos, float entityXRot, float entityYRot, int bogeySpacing,
|
||||
float partialTicks, boolean leading) {
|
||||
Vec3 thisOffset = type.getConnectorAnchorOffset();
|
||||
thisOffset = thisOffset.multiply(1, 1, leading ? -1 : 1);
|
||||
|
||||
// msr.rotateY(viewYRot + 90)
|
||||
// .rotateX(-viewXRot)
|
||||
// .rotateY(180)
|
||||
// .translate(0, 0, first ? 0 : -bogeySpacing)
|
||||
// .rotateY(-180)
|
||||
// .rotateX(viewXRot)
|
||||
// .rotateY(-viewYRot - 90)
|
||||
// .rotateY(bogey.yaw.getValue(partialTicks))
|
||||
// .rotateX(bogey.pitch.getValue(partialTicks))
|
||||
|
||||
thisOffset = VecHelper.rotate(thisOffset, pitch.getValue(partialTicks), Axis.X);
|
||||
thisOffset = VecHelper.rotate(thisOffset, yaw.getValue(partialTicks), Axis.Y);
|
||||
thisOffset = VecHelper.rotate(thisOffset, -entityYRot - 90, Axis.Y);
|
||||
thisOffset = VecHelper.rotate(thisOffset, entityXRot, Axis.X);
|
||||
thisOffset = VecHelper.rotate(thisOffset, -180, Axis.Y);
|
||||
thisOffset = thisOffset.add(0, 0, leading ? 0 : -bogeySpacing);
|
||||
thisOffset = VecHelper.rotate(thisOffset, 180, Axis.Y);
|
||||
thisOffset = VecHelper.rotate(thisOffset, -entityXRot, Axis.X);
|
||||
thisOffset = VecHelper.rotate(thisOffset, entityYRot + 90, Axis.Y);
|
||||
|
||||
if (leading)
|
||||
leadingCouplingAnchor = entityPos.add(thisOffset);
|
||||
else {
|
||||
trailingCouplingAnchor = entityPos.add(thisOffset);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package com.simibubi.create.content.logistics.trains.entity;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.NonStationaryLighter;
|
||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
||||
|
||||
public class CarriageContraption extends Contraption {
|
||||
|
||||
private Direction assemblyDirection;
|
||||
|
||||
private boolean controls;
|
||||
private int bogeys;
|
||||
private BlockPos secondBogeyPos;
|
||||
|
||||
private Carriage carriage;
|
||||
public int temporaryCarriageIdHolder = -1;
|
||||
|
||||
public CarriageContraption() {}
|
||||
|
||||
public CarriageContraption(Direction assemblyDirection) {
|
||||
this.assemblyDirection = assemblyDirection;
|
||||
this.bogeys = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assemble(Level world, BlockPos pos) throws AssemblyException {
|
||||
if (!searchMovedStructure(world, pos, null))
|
||||
return false;
|
||||
if (blocks.size() == 0)
|
||||
return false;
|
||||
if (bogeys > 2 || bogeys == 0)
|
||||
throw AssemblyException.invalidBogeyCount();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAnchoringBlockAt(BlockPos pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pair<StructureBlockInfo, BlockEntity> capture(Level world, BlockPos pos) {
|
||||
BlockState blockState = world.getBlockState(pos);
|
||||
|
||||
if (blockState.getBlock() instanceof IBogeyBlock) {
|
||||
bogeys++;
|
||||
if (bogeys == 2)
|
||||
secondBogeyPos = pos;
|
||||
return Pair.of(new StructureBlockInfo(pos, blockState, null), null);
|
||||
}
|
||||
|
||||
if (AllBlocks.CONTROLS.has(blockState))
|
||||
controls = true;
|
||||
|
||||
return super.capture(world, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag writeNBT(boolean spawnPacket) {
|
||||
CompoundTag tag = super.writeNBT(spawnPacket);
|
||||
NBTHelper.writeEnum(tag, "AssemblyDirection", getAssemblyDirection());
|
||||
if (spawnPacket)
|
||||
tag.putInt("CarriageId", carriage.id);
|
||||
tag.putBoolean("Controls", hasControls());
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readNBT(Level world, CompoundTag nbt, boolean spawnData) {
|
||||
assemblyDirection = NBTHelper.readEnum(nbt, "AssemblyDirection", Direction.class);
|
||||
if (spawnData)
|
||||
temporaryCarriageIdHolder = nbt.getInt("CarriageId");
|
||||
controls = nbt.getBoolean("Controls");
|
||||
super.readNBT(world, nbt, spawnData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeStabilized(Direction facing, BlockPos localPos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ContraptionType getType() {
|
||||
return ContraptionType.CARRIAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContraptionLighter<?> makeLighter() {
|
||||
return new NonStationaryLighter<>(this);
|
||||
}
|
||||
|
||||
public Direction getAssemblyDirection() {
|
||||
return assemblyDirection;
|
||||
}
|
||||
|
||||
public void setCarriage(Carriage carriage) {
|
||||
this.carriage = carriage;
|
||||
temporaryCarriageIdHolder = carriage.id;
|
||||
}
|
||||
|
||||
public Carriage getCarriage() {
|
||||
return carriage;
|
||||
}
|
||||
|
||||
public boolean hasControls() {
|
||||
return controls;
|
||||
}
|
||||
|
||||
public BlockPos getSecondBogeyPos() {
|
||||
return secondBogeyPos;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package com.simibubi.create.content.logistics.trains.entity;
|
||||
|
||||
import com.simibubi.create.AllEntityTypes;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
||||
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
||||
|
||||
public CarriageContraptionEntity(EntityType<?> type, Level world) {
|
||||
super(type, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isControlledByLocalInstance() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static CarriageContraptionEntity create(Level world, CarriageContraption contraption) {
|
||||
CarriageContraptionEntity entity =
|
||||
new CarriageContraptionEntity(AllEntityTypes.CARRIAGE_CONTRAPTION.get(), world);
|
||||
entity.setContraption(contraption);
|
||||
entity.setInitialOrientation(contraption.getAssemblyDirection());
|
||||
entity.startAtInitialYaw();
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tickContraption() {
|
||||
if (!(contraption instanceof CarriageContraption))
|
||||
return;
|
||||
int id = ((CarriageContraption) contraption).temporaryCarriageIdHolder;
|
||||
Carriage carriage = Create.RAILWAYS.carriageById.get(id); // TODO: thread breach
|
||||
if (carriage == null) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
if (!level.isClientSide)
|
||||
return;
|
||||
|
||||
xo = getX();
|
||||
yo = getY();
|
||||
zo = getZ();
|
||||
carriage.moveEntity(this);
|
||||
double distanceTo = position().distanceTo(new Vec3(xo, yo, zo));
|
||||
carriage.bogeys.getFirst()
|
||||
.updateAngles(distanceTo);
|
||||
if (carriage.isOnTwoBogeys())
|
||||
carriage.bogeys.getSecond()
|
||||
.updateAngles(distanceTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldBeSaved() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package com.simibubi.create.content.logistics.trains.entity;
|
||||
|
||||
import com.jozufozu.flywheel.util.transform.MatrixTransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntityRenderer;
|
||||
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer<CarriageContraptionEntity> {
|
||||
|
||||
public CarriageContraptionEntityRenderer(EntityRendererProvider.Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRender(CarriageContraptionEntity entity, Frustum clippingHelper, double cameraX,
|
||||
double cameraY, double cameraZ) {
|
||||
if (!super.shouldRender(entity, clippingHelper, cameraX, cameraY, cameraZ))
|
||||
return false;
|
||||
return ((CarriageContraption) entity.getContraption()).temporaryCarriageIdHolder != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(CarriageContraptionEntity entity, float yaw, float partialTicks, PoseStack ms,
|
||||
MultiBufferSource buffers, int overlay) {
|
||||
super.render(entity, yaw, partialTicks, ms, buffers, overlay);
|
||||
|
||||
int id = ((CarriageContraption) entity.getContraption()).temporaryCarriageIdHolder;
|
||||
Carriage carriage = Create.RAILWAYS.carriageById.get(id);
|
||||
if (carriage == null)
|
||||
return;
|
||||
|
||||
Vec3 position = entity.getPosition(partialTicks);
|
||||
|
||||
ms.pushPose();
|
||||
carriage.bogeys.forEachWithContext((bogey, first) -> {
|
||||
if (!first && !carriage.isOnTwoBogeys())
|
||||
return;
|
||||
|
||||
ms.pushPose();
|
||||
MatrixTransformStack msr = new MatrixTransformStack(ms);
|
||||
float viewYRot = entity.getViewYRot(partialTicks);
|
||||
float viewXRot = entity.getViewXRot(partialTicks);
|
||||
int bogeySpacing = carriage.bogeySpacing;
|
||||
msr.rotateY(viewYRot + 90)
|
||||
.rotateX(-viewXRot)
|
||||
.rotateY(180)
|
||||
.translate(0, 0, first ? 0 : -bogeySpacing)
|
||||
.rotateY(-180)
|
||||
.rotateX(viewXRot)
|
||||
.rotateY(-viewYRot - 90)
|
||||
.rotateY(bogey.yaw.getValue(partialTicks))
|
||||
.rotateX(bogey.pitch.getValue(partialTicks))
|
||||
.translate(0, .5f, 0);
|
||||
|
||||
bogey.type.render(null, bogey.wheelAngle.getValue(partialTicks), ms, partialTicks, buffers,
|
||||
getPackedLightCoords(entity, partialTicks), overlay);
|
||||
bogey.updateCouplingAnchor(position, viewXRot, viewYRot, bogeySpacing, partialTicks, first);
|
||||
if (!carriage.isOnTwoBogeys())
|
||||
bogey.updateCouplingAnchor(position, viewXRot, viewYRot, bogeySpacing, partialTicks, !first);
|
||||
|
||||
ms.popPose();
|
||||
});
|
||||
ms.popPose();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package com.simibubi.create.content.logistics.trains.entity;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Carriage.CarriageBogey;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class CarriageCouplingRenderer {
|
||||
|
||||
public static void renderAll(PoseStack ms, MultiBufferSource buffer) {
|
||||
Collection<Train> trains = Create.RAILWAYS.trains.values(); // TODO: thread breach
|
||||
VertexConsumer vb = buffer.getBuffer(RenderType.solid());
|
||||
BlockState air = Blocks.AIR.defaultBlockState();
|
||||
float partialTicks = AnimationTickHolder.getPartialTicks();
|
||||
Entity cameraEntity = Minecraft.getInstance().cameraEntity;
|
||||
if (cameraEntity == null)
|
||||
return;
|
||||
|
||||
Vec3 camera = cameraEntity.getPosition(partialTicks);
|
||||
|
||||
for (Train train : trains) {
|
||||
List<Carriage> carriages = train.carriages;
|
||||
for (int i = 0; i < carriages.size() - 1; i++) {
|
||||
Carriage carriage = carriages.get(i);
|
||||
CarriageContraptionEntity entity = carriage.entity.get();
|
||||
Carriage carriage2 = carriages.get(i + 1);
|
||||
CarriageContraptionEntity entity2 = carriage.entity.get();
|
||||
|
||||
if (entity == null || entity2 == null)
|
||||
continue;
|
||||
|
||||
CarriageBogey bogey1 = carriage.trailingBogey();
|
||||
CarriageBogey bogey2 = carriage2.leadingBogey();
|
||||
Vec3 anchor = bogey1.trailingCouplingAnchor;
|
||||
Vec3 anchor2 = bogey2.leadingCouplingAnchor;
|
||||
|
||||
if (anchor == null || anchor2 == null)
|
||||
continue;
|
||||
if (!anchor.closerThan(camera, 64))
|
||||
continue;
|
||||
|
||||
int lightCoords = getPackedLightCoords(entity, partialTicks);
|
||||
int lightCoords2 = getPackedLightCoords(entity2, partialTicks);
|
||||
|
||||
double diffX = anchor2.x - anchor.x;
|
||||
double diffY = anchor2.y - anchor.y;
|
||||
double diffZ = anchor2.z - anchor.z;
|
||||
float yRot = AngleHelper.deg(Mth.atan2(diffZ, diffX)) + 90;
|
||||
float xRot = AngleHelper.deg(Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ)));
|
||||
|
||||
Vec3 position = entity.getPosition(partialTicks);
|
||||
Vec3 position2 = entity2.getPosition(partialTicks);
|
||||
|
||||
ms.pushPose();
|
||||
ms.pushPose();
|
||||
ms.translate(anchor.x, anchor.y, anchor.z);
|
||||
CachedBufferer.partial(AllBlockPartials.TRAIN_COUPLING_HEAD, air)
|
||||
.rotateY(-yRot)
|
||||
.rotateX(xRot)
|
||||
.light(lightCoords)
|
||||
.renderInto(ms, vb);
|
||||
|
||||
float margin = 3 / 16f;
|
||||
double couplingDistance = train.carriageSpacing.get(i) - 2 * margin
|
||||
- bogey1.type.getConnectorAnchorOffset().z - bogey2.type.getConnectorAnchorOffset().z;
|
||||
int couplingSegments = (int) Math.round(couplingDistance * 4);
|
||||
double stretch = ((anchor2.distanceTo(anchor) - 2 * margin) * 4) / couplingSegments;
|
||||
for (int j = 0; j < couplingSegments; j++) {
|
||||
CachedBufferer.partial(AllBlockPartials.TRAIN_COUPLING_CABLE, air)
|
||||
.rotateY(-yRot + 180)
|
||||
.rotateX(-xRot)
|
||||
.translate(0, 0, margin + 2 / 16f)
|
||||
.scale(1, 1, (float) stretch)
|
||||
.translate(0, 0, j / 4f)
|
||||
.light(lightCoords)
|
||||
.renderInto(ms, vb);
|
||||
}
|
||||
|
||||
ms.popPose();
|
||||
|
||||
ms.pushPose();
|
||||
ms.translate(-position.x, -position.y, -position.z);
|
||||
ms.translate(position2.x, position2.y, position2.z);
|
||||
ms.translate(anchor2.x, anchor2.y, anchor2.z);
|
||||
CachedBufferer.partial(AllBlockPartials.TRAIN_COUPLING_HEAD, air)
|
||||
.rotateY(-yRot + 180)
|
||||
.rotateX(-xRot)
|
||||
.light(lightCoords2)
|
||||
.renderInto(ms, vb);
|
||||
ms.popPose();
|
||||
ms.popPose();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static int getPackedLightCoords(Entity pEntity, float pPartialTicks) {
|
||||
BlockPos blockpos = new BlockPos(pEntity.getLightProbePosition(pPartialTicks));
|
||||
return LightTexture.pack(getBlockLightLevel(pEntity, blockpos), getSkyLightLevel(pEntity, blockpos));
|
||||
}
|
||||
|
||||
protected static int getSkyLightLevel(Entity pEntity, BlockPos pPos) {
|
||||
return pEntity.level.getBrightness(LightLayer.SKY, pPos);
|
||||
}
|
||||
|
||||
protected static int getBlockLightLevel(Entity pEntity, BlockPos pPos) {
|
||||
return pEntity.isOnFire() ? 15 : pEntity.level.getBrightness(LightLayer.BLOCK, pPos);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package com.simibubi.create.content.logistics.trains.entity;
|
||||
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.event.entity.EntityEvent;
|
||||
|
||||
/**
|
||||
* Removes all Carriage entities in chunks that aren't ticking
|
||||
*/
|
||||
public class CarriageEntityHandler {
|
||||
|
||||
public static void onEntityEnterSection(EntityEvent.EnteringSection event) {
|
||||
if (!event.didChunkChange())
|
||||
return;
|
||||
Entity entity = event.getEntity();
|
||||
if (!(entity instanceof CarriageContraptionEntity))
|
||||
return;
|
||||
SectionPos newPos = event.getNewPos();
|
||||
Level level = entity.getLevel();
|
||||
if (level.isClientSide)
|
||||
return;
|
||||
if (!isActiveChunk(level, newPos.chunk()))
|
||||
entity.discard();
|
||||
}
|
||||
|
||||
public static void validateCarriageEntity(CarriageContraptionEntity entity) {
|
||||
if (!entity.isAlive())
|
||||
return;
|
||||
Level level = entity.getLevel();
|
||||
if (level.isClientSide)
|
||||
return;
|
||||
if (!isActiveChunk(level, entity.chunkPosition()))
|
||||
entity.discard();
|
||||
}
|
||||
|
||||
public static boolean isActiveChunk(Level level, ChunkPos chunk) {
|
||||
if (level instanceof ServerLevel serverLevel)
|
||||
return serverLevel.isPositionEntityTicking(chunk);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
package com.simibubi.create.content.logistics.trains.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.logistics.trains.TrackEdge;
|
||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||
import com.simibubi.create.content.logistics.trains.TrackNode;
|
||||
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class MovingPoint {
|
||||
|
||||
TrackGraph graph;
|
||||
TrackNode node1, node2;
|
||||
TrackEdge edge;
|
||||
double position;
|
||||
|
||||
public static enum SteerDirection {
|
||||
NONE(0), LEFT(-1), RIGHT(1);
|
||||
|
||||
float targetDot;
|
||||
|
||||
private SteerDirection(float targetDot) {
|
||||
this.targetDot = targetDot;
|
||||
}
|
||||
}
|
||||
|
||||
public static interface ITrackSelector
|
||||
extends Function<List<Entry<TrackNode, TrackEdge>>, Entry<TrackNode, TrackEdge>> {
|
||||
};
|
||||
|
||||
public MovingPoint(TrackGraph graph, TrackNode node1, TrackNode node2, TrackEdge edge, double position) {
|
||||
this.graph = graph;
|
||||
this.node1 = node1;
|
||||
this.node2 = node2;
|
||||
this.edge = edge;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public ITrackSelector random() {
|
||||
return validTargets -> validTargets.get(Create.RANDOM.nextInt(validTargets.size()));
|
||||
}
|
||||
|
||||
public ITrackSelector follow(MovingPoint other) {
|
||||
return validTargets -> {
|
||||
TrackNode target = other.node1;
|
||||
|
||||
for (Entry<TrackNode, TrackEdge> entry : validTargets)
|
||||
if (entry.getKey() == target || entry.getKey() == other.node2)
|
||||
return entry;
|
||||
|
||||
Vector<List<Entry<TrackNode, TrackEdge>>> frontiers = new Vector<>(validTargets.size());
|
||||
Vector<Set<TrackEdge>> visiteds = new Vector<>(validTargets.size());
|
||||
|
||||
for (int j = 0; j < validTargets.size(); j++) {
|
||||
ArrayList<Entry<TrackNode, TrackEdge>> e = new ArrayList<>();
|
||||
Entry<TrackNode, TrackEdge> entry = validTargets.get(j);
|
||||
e.add(entry);
|
||||
frontiers.add(e);
|
||||
HashSet<TrackEdge> e2 = new HashSet<>();
|
||||
e2.add(entry.getValue());
|
||||
visiteds.add(e2);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
for (int j = 0; j < validTargets.size(); j++) {
|
||||
Entry<TrackNode, TrackEdge> entry = validTargets.get(j);
|
||||
List<Entry<TrackNode, TrackEdge>> frontier = frontiers.get(j);
|
||||
if (frontier.isEmpty())
|
||||
continue;
|
||||
|
||||
Entry<TrackNode, TrackEdge> currentEntry = frontier.remove(0);
|
||||
for (Entry<TrackNode, TrackEdge> nextEntry : graph.getConnectionsFrom(currentEntry.getKey())
|
||||
.entrySet()) {
|
||||
TrackEdge nextEdge = nextEntry.getValue();
|
||||
if (!visiteds.get(j)
|
||||
.add(nextEdge))
|
||||
continue;
|
||||
|
||||
TrackNode nextNode = nextEntry.getKey();
|
||||
if (nextNode == target)
|
||||
return entry;
|
||||
|
||||
frontier.add(nextEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Create.LOGGER.warn("Couldn't find follow target, choosing first");
|
||||
return validTargets.get(0);
|
||||
};
|
||||
}
|
||||
|
||||
public ITrackSelector steer(SteerDirection direction, Vec3 upNormal) {
|
||||
return validTargets -> {
|
||||
double closest = Double.MAX_VALUE;
|
||||
Entry<TrackNode, TrackEdge> best = null;
|
||||
|
||||
for (Entry<TrackNode, TrackEdge> entry : validTargets) {
|
||||
Vec3 trajectory = edge.getDirection(node1, node2, false);
|
||||
Vec3 entryTrajectory = entry.getValue()
|
||||
.getDirection(node2, entry.getKey(), true);
|
||||
Vec3 normal = trajectory.cross(upNormal);
|
||||
double dot = normal.dot(entryTrajectory);
|
||||
double diff = Math.abs(direction.targetDot - dot);
|
||||
if (diff > closest)
|
||||
continue;
|
||||
|
||||
closest = diff;
|
||||
best = entry;
|
||||
}
|
||||
|
||||
if (best == null) {
|
||||
Create.LOGGER.warn("Couldn't find steer target, choosing first");
|
||||
return validTargets.get(0);
|
||||
}
|
||||
|
||||
return best;
|
||||
};
|
||||
}
|
||||
|
||||
public double travel(double distance, ITrackSelector trackSelector) {
|
||||
double edgeLength = edge.getLength(node1, node2);
|
||||
if (distance == 0)
|
||||
return 0;
|
||||
|
||||
double traveled = distance;
|
||||
|
||||
double currentT = position / edgeLength;
|
||||
double incrementT = edge.incrementT(node1, node2, currentT, distance);
|
||||
position = incrementT * edgeLength;
|
||||
|
||||
List<Entry<TrackNode, TrackEdge>> validTargets = new ArrayList<>();
|
||||
while (position > edgeLength) {
|
||||
validTargets.clear();
|
||||
|
||||
for (Entry<TrackNode, TrackEdge> entry : graph.getConnectionsFrom(node2)
|
||||
.entrySet()) {
|
||||
TrackNode newNode = entry.getKey();
|
||||
if (newNode == node1)
|
||||
continue;
|
||||
|
||||
TrackEdge newEdge = entry.getValue();
|
||||
Vec3 currentDirection = edge.getDirection(node1, node2, false);
|
||||
Vec3 newDirection = newEdge.getDirection(node2, newNode, true);
|
||||
if (currentDirection.dot(newDirection) < 0)
|
||||
continue;
|
||||
|
||||
validTargets.add(entry);
|
||||
}
|
||||
|
||||
if (validTargets.isEmpty()) {
|
||||
traveled -= position - edgeLength;
|
||||
position = edgeLength;
|
||||
break;
|
||||
}
|
||||
|
||||
Entry<TrackNode, TrackEdge> entry =
|
||||
validTargets.size() == 1 ? validTargets.get(0) : trackSelector.apply(validTargets);
|
||||
|
||||
node1 = node2;
|
||||
node2 = entry.getKey();
|
||||
edge = entry.getValue();
|
||||
position -= edgeLength;
|
||||
edgeLength = edge.getLength(node1, node2);
|
||||
}
|
||||
|
||||
return traveled;
|
||||
}
|
||||
|
||||
public void reverse() {
|
||||
TrackNode n = node1;
|
||||
node1 = node2;
|
||||
node2 = n;
|
||||
position = edge.getLength(node1, node2) - position;
|
||||
edge = graph.getConnectionsFrom(node1)
|
||||
.get(node2);
|
||||
}
|
||||
|
||||
public Vec3 getPosition() {
|
||||
double t = position / edge.getLength(node1, node2);
|
||||
return edge.getPosition(node1, node2, t)
|
||||
.add(edge.getNormal(node1, node2, t)
|
||||
.scale(1));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
package com.simibubi.create.content.logistics.trains.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Set;
|
||||
|
||||
import com.simibubi.create.content.logistics.trains.TrackEdge;
|
||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||
import com.simibubi.create.content.logistics.trains.TrackNode;
|
||||
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
|
||||
import com.simibubi.create.content.logistics.trains.entity.MovingPoint.ITrackSelector;
|
||||
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
||||
import com.simibubi.create.foundation.utility.Couple;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class Navigation {
|
||||
|
||||
TrackGraph graph;
|
||||
Train train;
|
||||
|
||||
public GlobalStation destination;
|
||||
public double distanceToDestination;
|
||||
|
||||
List<TrackEdge> path;
|
||||
|
||||
public Navigation(Train train, TrackGraph graph) {
|
||||
this.train = train;
|
||||
this.graph = graph;
|
||||
path = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void tick(Level level) {
|
||||
if (destination == null)
|
||||
return;
|
||||
|
||||
destination.reserveFor(train);
|
||||
|
||||
if (distanceToDestination < 1 / 32f) {
|
||||
distanceToDestination = 0;
|
||||
train.speed = 0;
|
||||
path.clear();
|
||||
train.arriveAt(destination);
|
||||
destination = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (distanceToDestination - train.speed < 1 / 32f) {
|
||||
train.speed = distanceToDestination;
|
||||
return;
|
||||
}
|
||||
|
||||
if (distanceToDestination < 10) {
|
||||
double target = Train.topSpeed * ((distanceToDestination) / 10);
|
||||
if (target < train.speed) {
|
||||
train.speed += (target - train.speed) * .5f;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
double brakingDistance = (train.speed * train.speed) / (2 * Train.acceleration);
|
||||
train.targetSpeed = distanceToDestination > brakingDistance ? Train.topSpeed : 0;
|
||||
|
||||
if (Mth.equal(train.targetSpeed, train.speed))
|
||||
return;
|
||||
|
||||
if (train.speed < train.targetSpeed)
|
||||
train.speed = Math.min(train.speed + Train.acceleration, train.targetSpeed);
|
||||
else if (train.speed > train.targetSpeed)
|
||||
train.speed = Math.max(train.speed - Train.acceleration, train.targetSpeed);
|
||||
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return destination != null;
|
||||
}
|
||||
|
||||
public ITrackSelector control(MovingPoint mp) {
|
||||
return list -> {
|
||||
if (!path.isEmpty()) {
|
||||
TrackEdge target = path.get(0);
|
||||
for (Entry<TrackNode, TrackEdge> entry : list) {
|
||||
if (entry.getValue() == target) {
|
||||
path.remove(0);
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return list.get(0);
|
||||
};
|
||||
}
|
||||
|
||||
public void cancelNavigation() {
|
||||
distanceToDestination = 0;
|
||||
path.clear();
|
||||
if (destination == null)
|
||||
return;
|
||||
destination.cancelReservation(train);
|
||||
}
|
||||
|
||||
public void setDestination(GlobalStation destination) {
|
||||
findPathTo(destination);
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
train.leave();
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
private void findPathTo(GlobalStation destination) {
|
||||
path.clear();
|
||||
this.distanceToDestination = 0;
|
||||
Couple<TrackNodeLocation> target = destination.edgeLocation;
|
||||
PriorityQueue<Pair<Double, Pair<Couple<TrackNode>, TrackEdge>>> frontier =
|
||||
new PriorityQueue<>((p1, p2) -> Double.compare(p1.getFirst(), p2.getFirst()));
|
||||
|
||||
MovingPoint leadingPoint = train.carriages.get(0)
|
||||
.getLeadingPoint();
|
||||
Set<TrackEdge> visited = new HashSet<>();
|
||||
Map<TrackEdge, Pair<Boolean, TrackEdge>> reachedVia = new IdentityHashMap<>();
|
||||
|
||||
TrackEdge initialEdge = leadingPoint.edge;
|
||||
TrackNode initialNode1 = leadingPoint.node1;
|
||||
TrackNode initialNode2 = leadingPoint.node2;
|
||||
double distanceToNode2 = initialEdge.getLength(initialNode1, initialNode2) - leadingPoint.position;
|
||||
frontier.add(Pair.of(distanceToNode2, Pair.of(Couple.create(initialNode1, initialNode2), initialEdge)));
|
||||
|
||||
while (!frontier.isEmpty()) {
|
||||
Pair<Double, Pair<Couple<TrackNode>, TrackEdge>> poll = frontier.poll();
|
||||
double distance = poll.getFirst();
|
||||
Pair<Couple<TrackNode>, TrackEdge> currentEntry = poll.getSecond();
|
||||
List<Entry<TrackNode, TrackEdge>> validTargets = new ArrayList<>();
|
||||
TrackEdge edge = currentEntry.getSecond();
|
||||
TrackNode node1 = currentEntry.getFirst()
|
||||
.getFirst();
|
||||
TrackNode node2 = currentEntry.getFirst()
|
||||
.getSecond();
|
||||
|
||||
TrackNodeLocation loc1 = node1.getLocation();
|
||||
TrackNodeLocation loc2 = node2.getLocation();
|
||||
boolean enteringBackward = loc2.equals(target.getFirst()) && loc1.equals(target.getSecond());
|
||||
boolean enteringForward = loc1.equals(target.getFirst()) && loc2.equals(target.getSecond());
|
||||
|
||||
if (enteringForward || train.doubleEnded && enteringBackward) {
|
||||
Pair<Boolean, TrackEdge> backTrack = reachedVia.get(edge);
|
||||
TrackEdge toReach = edge;
|
||||
while (backTrack != null && toReach != initialEdge) {
|
||||
if (backTrack.getFirst())
|
||||
path.add(0, toReach);
|
||||
toReach = backTrack.getSecond();
|
||||
backTrack = reachedVia.get(backTrack.getSecond());
|
||||
}
|
||||
|
||||
distanceToDestination = distance;
|
||||
double position = destination.position;
|
||||
if (enteringForward)
|
||||
position = edge.getLength(node1, node2) - position;
|
||||
else
|
||||
distanceToDestination += train.getTotalLength() + 2;
|
||||
distanceToDestination -= position;
|
||||
return;
|
||||
}
|
||||
|
||||
for (Entry<TrackNode, TrackEdge> entry : graph.getConnectionsFrom(node2)
|
||||
.entrySet()) {
|
||||
TrackNode newNode = entry.getKey();
|
||||
TrackEdge newEdge = entry.getValue();
|
||||
Vec3 currentDirection = edge.getDirection(node1, node2, false);
|
||||
Vec3 newDirection = newEdge.getDirection(node2, newNode, true);
|
||||
if (currentDirection.dot(newDirection) < 0)
|
||||
continue;
|
||||
if (!visited.add(entry.getValue()))
|
||||
continue;
|
||||
validTargets.add(entry);
|
||||
}
|
||||
|
||||
if (validTargets.isEmpty())
|
||||
continue;
|
||||
|
||||
for (Entry<TrackNode, TrackEdge> entry : validTargets) {
|
||||
TrackNode newNode = entry.getKey();
|
||||
TrackEdge newEdge = entry.getValue();
|
||||
reachedVia.put(newEdge, Pair.of(validTargets.size() > 1, edge));
|
||||
frontier.add(Pair.of(newEdge.getLength(node2, newNode) + distance,
|
||||
Pair.of(Couple.create(node2, newNode), newEdge)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
package com.simibubi.create.content.logistics.trains.entity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||
import com.simibubi.create.content.logistics.trains.entity.MovingPoint.ITrackSelector;
|
||||
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
||||
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class Train {
|
||||
|
||||
public static final double acceleration = 0.005f;
|
||||
public static final double topSpeed = 1.2f;
|
||||
|
||||
public double speed = 0;
|
||||
public double targetSpeed = 0;
|
||||
|
||||
public UUID id;
|
||||
public TrackGraph graph;
|
||||
public Navigation navigation;
|
||||
public GlobalStation currentStation;
|
||||
public ScheduleRuntime runtime;
|
||||
public TrainIconType icon;
|
||||
public Component name;
|
||||
|
||||
public boolean doubleEnded;
|
||||
public List<Carriage> carriages;
|
||||
public List<Integer> carriageSpacing;
|
||||
|
||||
double[] stress;
|
||||
|
||||
public Train(UUID id, TrackGraph graph, List<Carriage> carriages, List<Integer> carriageSpacing) {
|
||||
this.id = id;
|
||||
this.graph = graph;
|
||||
this.carriages = carriages;
|
||||
this.carriageSpacing = carriageSpacing;
|
||||
this.icon = TrainIconType.getDefault();
|
||||
this.stress = new double[carriageSpacing.size()];
|
||||
this.name = Lang.translate("train.unnamed");
|
||||
|
||||
carriages.forEach(c -> {
|
||||
c.setTrain(this);
|
||||
Create.RAILWAYS.carriageById.put(c.id, c);
|
||||
});
|
||||
|
||||
doubleEnded = carriages.size() > 1 && carriages.get(carriages.size() - 1).contraption.hasControls();
|
||||
navigation = new Navigation(this, graph);
|
||||
runtime = new ScheduleRuntime(this);
|
||||
}
|
||||
|
||||
public void tick(Level level) {
|
||||
runtime.tick(level);
|
||||
navigation.tick(level);
|
||||
|
||||
double distance = speed;
|
||||
Carriage previousCarriage = null;
|
||||
|
||||
for (int i = 0; i < carriages.size(); i++) {
|
||||
Carriage carriage = carriages.get(i);
|
||||
if (previousCarriage != null) {
|
||||
int target = carriageSpacing.get(i - 1);
|
||||
Vec3 leadingAnchor = carriage.leadingBogey().anchorPosition;
|
||||
Vec3 trailingAnchor = previousCarriage.trailingBogey().anchorPosition;
|
||||
double actual = leadingAnchor.distanceTo(trailingAnchor);
|
||||
stress[i - 1] = target - actual;
|
||||
}
|
||||
previousCarriage = carriage;
|
||||
}
|
||||
|
||||
// positive stress: carriages should move apart
|
||||
// negative stress: carriages should move closer
|
||||
|
||||
boolean approachingStation = navigation.distanceToDestination < 5;
|
||||
double leadingModifier = approachingStation ? -0.75d : -0.5d;
|
||||
double trailingModifier = approachingStation ? 0d : 0.125d;
|
||||
|
||||
MovingPoint previous = null;
|
||||
for (int i = 0; i < carriages.size(); i++) {
|
||||
double leadingStress = i == 0 ? 0 : stress[i - 1] * leadingModifier;
|
||||
double trailingStress = i == stress.length ? 0 : stress[i] * trailingModifier;
|
||||
|
||||
Carriage carriage = carriages.get(i);
|
||||
MovingPoint toFollow = previous;
|
||||
Function<MovingPoint, ITrackSelector> control =
|
||||
previous == null ? navigation::control : mp -> mp.follow(toFollow);
|
||||
double actualDistance = carriage.travel(level, distance + leadingStress + trailingStress, control);
|
||||
|
||||
if (i == 0)
|
||||
distance = actualDistance;
|
||||
previous = carriage.getTrailingPoint();
|
||||
}
|
||||
|
||||
if (navigation.destination != null) {
|
||||
navigation.distanceToDestination -= distance;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean disassemble(Direction assemblyDirection, BlockPos pos) {
|
||||
for (Carriage carriage : carriages) {
|
||||
CarriageContraptionEntity entity = carriage.entity.get();
|
||||
if (entity == null)
|
||||
return false;
|
||||
if (!Mth.equal(entity.pitch, 0))
|
||||
return false;
|
||||
if (!Mth.equal(((entity.yaw % 90) + 360) % 90, 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
int offset = 1;
|
||||
for (int i = 0; i < carriages.size(); i++) {
|
||||
|
||||
Carriage carriage = carriages.get(i);
|
||||
CarriageContraptionEntity entity = carriage.entity.get();
|
||||
if (entity == null)
|
||||
return false;
|
||||
|
||||
entity.setPos(Vec3.atLowerCornerOf(pos.relative(assemblyDirection, offset)));
|
||||
entity.disassemble();
|
||||
Create.RAILWAYS.carriageById.remove(carriage.id);
|
||||
CreateClient.RAILWAYS.carriageById.remove(carriage.id);
|
||||
|
||||
offset += carriage.bogeySpacing;
|
||||
if (i < carriageSpacing.size())
|
||||
offset += carriageSpacing.get(i);
|
||||
}
|
||||
|
||||
if (currentStation != null)
|
||||
currentStation.cancelReservation(this);
|
||||
|
||||
Create.RAILWAYS.trains.remove(id);
|
||||
CreateClient.RAILWAYS.trains.remove(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getTotalLength() {
|
||||
int length = 0;
|
||||
for (int i = 0; i < carriages.size(); i++) {
|
||||
length += carriages.get(i).bogeySpacing;
|
||||
if (i < carriageSpacing.size())
|
||||
length += carriageSpacing.get(i);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
public void leave() {
|
||||
currentStation.trainDeparted(this);
|
||||
currentStation = null;
|
||||
}
|
||||
|
||||
public void arriveAt(GlobalStation station) {
|
||||
currentStation = station;
|
||||
runtime.destinationReached();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package com.simibubi.create.content.logistics.trains.entity;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.Create;
|
||||
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public class TrainIconType {
|
||||
|
||||
public static Map<ResourceLocation, TrainIconType> REGISTRY = new HashMap<>();
|
||||
|
||||
public static void register(ResourceLocation id, ResourceLocation sheet, int x, int y) {
|
||||
REGISTRY.put(id, new TrainIconType(id, sheet, x, y));
|
||||
}
|
||||
|
||||
static {
|
||||
ResourceLocation sheet = Create.asResource("textures/gui/assemble.png");
|
||||
register(Create.asResource("traditional"), sheet, 2, 205);
|
||||
register(Create.asResource("electric"), sheet, 2, 216);
|
||||
register(Create.asResource("modern"), sheet, 2, 227);
|
||||
}
|
||||
|
||||
ResourceLocation sheet;
|
||||
ResourceLocation id;
|
||||
int x, y;
|
||||
|
||||
public TrainIconType(ResourceLocation id, ResourceLocation sheet, int x, int y) {
|
||||
this.id = id;
|
||||
this.sheet = sheet;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public static TrainIconType byId(ResourceLocation id) {
|
||||
return REGISTRY.getOrDefault(id, getDefault());
|
||||
}
|
||||
|
||||
public static TrainIconType getDefault() {
|
||||
return REGISTRY.get(Create.asResource("traditional"));
|
||||
}
|
||||
|
||||
public ResourceLocation getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static final int ENGINE = -1;
|
||||
public static final int FLIPPED_ENGINE = -2;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public int render(int lengthOrEngine, PoseStack ms, int x, int y) {
|
||||
int offset = getIconOffset(lengthOrEngine);
|
||||
int width = getIconWidth(lengthOrEngine);
|
||||
RenderSystem.setShaderTexture(0, sheet);
|
||||
GuiComponent.blit(ms, x, y, 0, this.x + offset, this.y, width, 10, 256, 256);
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getIconWidth(int lengthOrEngine) {
|
||||
if (lengthOrEngine == FLIPPED_ENGINE)
|
||||
return 19;
|
||||
if (lengthOrEngine == ENGINE)
|
||||
return 19;
|
||||
if (lengthOrEngine < 3)
|
||||
return 7;
|
||||
if (lengthOrEngine < 9)
|
||||
return 13;
|
||||
return 19;
|
||||
}
|
||||
|
||||
public int getIconOffset(int lengthOrEngine) {
|
||||
if (lengthOrEngine == FLIPPED_ENGINE)
|
||||
return 0;
|
||||
if (lengthOrEngine == ENGINE)
|
||||
return 62;
|
||||
if (lengthOrEngine < 3)
|
||||
return 34;
|
||||
if (lengthOrEngine < 9)
|
||||
return 20;
|
||||
return 42;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Carriage;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||
import com.simibubi.create.content.logistics.trains.entity.TrainIconType;
|
||||
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
|
||||
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
import com.simibubi.create.foundation.gui.element.GuiGameElement;
|
||||
import com.simibubi.create.foundation.gui.widget.IconButton;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
|
||||
public abstract class AbstractStationScreen extends AbstractSimiScreen {
|
||||
|
||||
protected AllGuiTextures background;
|
||||
protected StationTileEntity te;
|
||||
protected GlobalStation station;
|
||||
|
||||
protected WeakReference<Train> displayedTrain;
|
||||
|
||||
private IconButton confirmButton;
|
||||
|
||||
public AbstractStationScreen(StationTileEntity te, GlobalStation station) {
|
||||
super(new TextComponent("Station"));
|
||||
this.te = te;
|
||||
this.station = station;
|
||||
displayedTrain = new WeakReference<>(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
setWindowSize(background.width, background.height);
|
||||
setWindowOffset(-20, 0);
|
||||
super.init();
|
||||
clearWidgets();
|
||||
|
||||
int x = guiLeft;
|
||||
int y = guiTop;
|
||||
|
||||
confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM);
|
||||
confirmButton.withCallback(this::onClose);
|
||||
addRenderableWidget(confirmButton);
|
||||
}
|
||||
|
||||
public int getTrainIconWidth(Train train) {
|
||||
TrainIconType icon = train.icon;
|
||||
List<Carriage> carriages = train.carriages;
|
||||
|
||||
int w = icon.getIconWidth(TrainIconType.ENGINE);
|
||||
if (carriages.size() == 1)
|
||||
return w;
|
||||
|
||||
for (int i = 1; i < carriages.size(); i++) {
|
||||
if (i == carriages.size() - 1 && train.doubleEnded) {
|
||||
w += icon.getIconWidth(TrainIconType.FLIPPED_ENGINE) + 1;
|
||||
break;
|
||||
}
|
||||
Carriage carriage = carriages.get(i);
|
||||
w += icon.getIconWidth(carriage.bogeySpacing) + 1;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||
int x = guiLeft;
|
||||
int y = guiTop;
|
||||
|
||||
background.render(ms, x, y, this);
|
||||
|
||||
ms.pushPose();
|
||||
TransformStack.cast(ms)
|
||||
.pushPose()
|
||||
.translate(x + 200, y + background.height + 20, 100)
|
||||
.scale(40)
|
||||
.rotateX(-22)
|
||||
.rotateY(63);
|
||||
GuiGameElement.of(te.getBlockState()
|
||||
.setValue(StationBlock.FACING, Direction.EAST))
|
||||
.render(ms);
|
||||
ms.popPose();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,220 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Carriage;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||
import com.simibubi.create.content.logistics.trains.entity.TrainIconType;
|
||||
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
import com.simibubi.create.foundation.gui.UIRenderHelper;
|
||||
import com.simibubi.create.foundation.gui.widget.IconButton;
|
||||
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;
|
||||
|
||||
public class AssemblyScreen extends AbstractStationScreen {
|
||||
|
||||
private IconButton quitAssembly;
|
||||
private IconButton toggleAssemblyButton;
|
||||
private IconButton completeAssembly;
|
||||
|
||||
private List<ResourceLocation> iconTypes;
|
||||
private ScrollInput iconTypeScroll;
|
||||
|
||||
public AssemblyScreen(StationTileEntity te, GlobalStation station) {
|
||||
super(te, station);
|
||||
background = AllGuiTextures.STATION_ASSEMBLING;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
int x = guiLeft;
|
||||
int y = guiTop;
|
||||
int by = y + background.height - 24;
|
||||
|
||||
Widget widget = renderables.get(0);
|
||||
if (widget instanceof IconButton ib) {
|
||||
ib.setIcon(AllIcons.I_PRIORITY_VERY_LOW);
|
||||
ib.setToolTip(new TextComponent("Close Window"));
|
||||
}
|
||||
|
||||
iconTypes = TrainIconType.REGISTRY.keySet()
|
||||
.stream()
|
||||
.toList();
|
||||
iconTypeScroll = new ScrollInput(x + 4, y + 17, 184, 14).titled(new TextComponent("Icon Type"));
|
||||
iconTypeScroll.withRange(0, iconTypes.size());
|
||||
iconTypeScroll.withStepFunction(ctx -> -iconTypeScroll.standardStep()
|
||||
.apply(ctx));
|
||||
iconTypeScroll.calling(s -> {
|
||||
Train train = displayedTrain.get();
|
||||
if (train != null)
|
||||
train.icon = TrainIconType.byId(iconTypes.get(s));
|
||||
});
|
||||
iconTypeScroll.active = iconTypeScroll.visible = false;
|
||||
addRenderableWidget(iconTypeScroll);
|
||||
|
||||
toggleAssemblyButton = new WideIconButton(x + 83, by, AllGuiTextures.I_ASSEMBLE_TRAIN);
|
||||
toggleAssemblyButton.active = false;
|
||||
toggleAssemblyButton.setToolTip(new TextComponent("Assemble Train"));
|
||||
toggleAssemblyButton.withCallback(() -> {
|
||||
AllPackets.channel.sendToServer(StationEditPacket.tryAssemble(te.getBlockPos()));
|
||||
});
|
||||
|
||||
quitAssembly = new IconButton(x + 62, by, AllIcons.I_DISABLE);
|
||||
quitAssembly.active = true;
|
||||
quitAssembly.setToolTip(new TextComponent("Cancel Assembly"));
|
||||
quitAssembly.withCallback(() -> {
|
||||
AllPackets.channel.sendToServer(StationEditPacket.configure(te.getBlockPos(), false, station.name));
|
||||
minecraft.setScreen(new StationScreen(te, station));
|
||||
});
|
||||
|
||||
completeAssembly = new IconButton(x + 112, by, AllIcons.I_CONFIRM);
|
||||
completeAssembly.active = false;
|
||||
completeAssembly.setToolTip(new TextComponent("Complete Assembly"));
|
||||
completeAssembly.withCallback(() -> {
|
||||
AllPackets.channel.sendToServer(StationEditPacket.configure(te.getBlockPos(), false, station.name));
|
||||
minecraft.setScreen(new StationScreen(te, station));
|
||||
});
|
||||
|
||||
addRenderableWidget(toggleAssemblyButton);
|
||||
addRenderableWidget(quitAssembly);
|
||||
addRenderableWidget(completeAssembly);
|
||||
|
||||
tickTrainDisplay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
tickTrainDisplay();
|
||||
Train train = displayedTrain.get();
|
||||
toggleAssemblyButton.active = te.bogeyCount > 0 || train != null;
|
||||
}
|
||||
|
||||
private void tickTrainDisplay() {
|
||||
Train train = displayedTrain.get();
|
||||
Train imminentTrain = station.getPresentTrain();
|
||||
|
||||
if (train == null) {
|
||||
if (imminentTrain != null) {
|
||||
displayedTrain = new WeakReference<>(imminentTrain);
|
||||
completeAssembly.active = true;
|
||||
quitAssembly.active = false;
|
||||
iconTypeScroll.active = iconTypeScroll.visible = true;
|
||||
toggleAssemblyButton.setToolTip(new TextComponent("Disassemble Train"));
|
||||
toggleAssemblyButton.setIcon(AllGuiTextures.I_DISASSEMBLE_TRAIN);
|
||||
toggleAssemblyButton.withCallback(() -> {
|
||||
AllPackets.channel.sendToServer(StationEditPacket.tryDisassemble(te.getBlockPos()));
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (imminentTrain == null) {
|
||||
displayedTrain = new WeakReference<>(null);
|
||||
completeAssembly.active = false;
|
||||
quitAssembly.active = true;
|
||||
iconTypeScroll.active = iconTypeScroll.visible = false;
|
||||
toggleAssemblyButton.setToolTip(new TextComponent("Assemble Train"));
|
||||
toggleAssemblyButton.setIcon(AllGuiTextures.I_ASSEMBLE_TRAIN);
|
||||
toggleAssemblyButton.withCallback(() -> {
|
||||
AllPackets.channel.sendToServer(StationEditPacket.tryAssemble(te.getBlockPos()));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||
super.renderWindow(ms, mouseX, mouseY, partialTicks);
|
||||
int x = guiLeft;
|
||||
int y = guiTop;
|
||||
|
||||
TextComponent header = new TextComponent("Train Assembly");
|
||||
font.draw(ms, header, x + background.width / 2 - font.width(header) / 2, y + 4, 0x0E2233);
|
||||
|
||||
Train train = displayedTrain.get();
|
||||
if (train != null) {
|
||||
|
||||
TrainIconType icon = train.icon;
|
||||
int offset = 0;
|
||||
int position = background.width / 2 - getTrainIconWidth(train) / 2;
|
||||
|
||||
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;
|
||||
}
|
||||
Carriage carriage = carriages.get(i);
|
||||
offset += icon.render(carriage.bogeySpacing, ms, x + offset + position, y + 20) + 1;
|
||||
}
|
||||
offset += icon.render(TrainIconType.ENGINE, ms, x + offset + position, y + 20);
|
||||
|
||||
UIRenderHelper.drawStretched(ms, x + 21, y + 43, 150, 96, -100, AllGuiTextures.STATION_TEXTBOX_MIDDLE);
|
||||
AllGuiTextures.STATION_TEXTBOX_TOP.render(ms, x + 21, y + 42);
|
||||
AllGuiTextures.STATION_TEXTBOX_BOTTOM.render(ms, x + 21, y + 136);
|
||||
AllGuiTextures.STATION_TEXTBOX_SPEECH.render(ms, x + offset + position - 12, y + 38);
|
||||
|
||||
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"),
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
AssemblyException lastAssemblyException = te.getLastAssemblyException();
|
||||
if (lastAssemblyException != null) {
|
||||
TextComponent text = new TextComponent("Assembly Failed");
|
||||
font.draw(ms, text, x + 97 - font.width(text) / 2, y + 47, 0x775B5B);
|
||||
int offset = 0;
|
||||
if (te.failedCarriageIndex != -1) {
|
||||
font.draw(ms, new TextComponent("Carriage " + te.failedCarriageIndex + ":"), x + 30, y + 67, 0x7A7A7A);
|
||||
offset += 10;
|
||||
}
|
||||
font.drawWordWrap(lastAssemblyException.component, x + 30, y + 67 + offset, 134, 0x775B5B);
|
||||
offset += font.split(lastAssemblyException.component, 134)
|
||||
.size() * 9 + 5;
|
||||
font.drawWordWrap(new TextComponent("Resolve this and retry"), x + 30, y + 67 + offset, 134, 0x7A7A7A);
|
||||
return;
|
||||
}
|
||||
|
||||
int bogeyCount = te.bogeyCount;
|
||||
|
||||
TextComponent text =
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed() {
|
||||
super.removed();
|
||||
Train train = displayedTrain.get();
|
||||
if (train != null) {
|
||||
ResourceLocation iconId = iconTypes.get(iconTypeScroll.getState());
|
||||
train.icon = TrainIconType.byId(iconId);
|
||||
AllPackets.channel.sendToServer(new TrainEditPacket(train.id, "", iconId));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.content.logistics.trains.TrackNode;
|
||||
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||
import com.simibubi.create.foundation.utility.Couple;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
public class GlobalStation {
|
||||
|
||||
public UUID id;
|
||||
public Couple<TrackNodeLocation> edgeLocation;
|
||||
public double position;
|
||||
public String name;
|
||||
public BlockPos stationPos;
|
||||
|
||||
public WeakReference<Train> nearestTrain;
|
||||
|
||||
public GlobalStation(UUID id, Couple<TrackNode> nodes, double position, BlockPos stationPos) {
|
||||
this.id = id;
|
||||
this.stationPos = stationPos;
|
||||
this.position = position;
|
||||
name = "Track Station";
|
||||
edgeLocation = nodes.map(TrackNode::getLocation);
|
||||
nearestTrain = new WeakReference<Train>(null);
|
||||
}
|
||||
|
||||
public GlobalStation(CompoundTag nbt) {
|
||||
id = nbt.getUUID("Id");
|
||||
name = nbt.getString("Name");
|
||||
position = nbt.getDouble("Position");
|
||||
stationPos = NbtUtils.readBlockPos(nbt.getCompound("StationPos"));
|
||||
nearestTrain = new WeakReference<Train>(null);
|
||||
edgeLocation = Couple.deserializeEach(nbt.getList("Edge", Tag.TAG_COMPOUND),
|
||||
tag -> TrackNodeLocation.fromPackedPos(NbtUtils.readBlockPos(tag)));
|
||||
}
|
||||
|
||||
public void reserveFor(Train train) {
|
||||
Train nearestTrain = this.nearestTrain.get();
|
||||
if (nearestTrain == null
|
||||
|| nearestTrain.navigation.distanceToDestination > train.navigation.distanceToDestination)
|
||||
this.nearestTrain = new WeakReference<>(train);
|
||||
}
|
||||
|
||||
public void cancelReservation(Train train) {
|
||||
if (nearestTrain.get() == train)
|
||||
nearestTrain = new WeakReference<>(null);
|
||||
}
|
||||
|
||||
public void trainDeparted(Train train) {
|
||||
cancelReservation(train);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Train getPresentTrain() {
|
||||
Train nearestTrain = this.nearestTrain.get();
|
||||
if (nearestTrain == null || nearestTrain.currentStation != this)
|
||||
return null;
|
||||
return nearestTrain;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Train getImminentTrain() {
|
||||
Train nearestTrain = this.nearestTrain.get();
|
||||
if (nearestTrain == null)
|
||||
return nearestTrain;
|
||||
if (nearestTrain.currentStation == this)
|
||||
return nearestTrain;
|
||||
if (!nearestTrain.navigation.isActive())
|
||||
return null;
|
||||
if (nearestTrain.navigation.distanceToDestination > 30)
|
||||
return null;
|
||||
return nearestTrain;
|
||||
}
|
||||
|
||||
public CompoundTag write() {
|
||||
CompoundTag nbt = new CompoundTag();
|
||||
nbt.putUUID("Id", id);
|
||||
nbt.putString("Name", name);
|
||||
nbt.put("StationPos", NbtUtils.writeBlockPos(stationPos));
|
||||
nbt.putDouble("Position", position);
|
||||
nbt.put("Edge", edgeLocation.serializeEach(loc -> NbtUtils.writeBlockPos(new BlockPos(loc))));
|
||||
return nbt;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix4f;
|
||||
|
||||
import net.minecraft.client.StringSplitter;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.font.FontSet;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.FormattedText;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.FormattedCharSequence;
|
||||
|
||||
public class NoShadowFontWrapper extends Font {
|
||||
|
||||
private Font wrapped;
|
||||
|
||||
public NoShadowFontWrapper(Font wrapped) {
|
||||
super(null);
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
public FontSet getFontSet(ResourceLocation pFontLocation) {
|
||||
return wrapped.getFontSet(pFontLocation);
|
||||
}
|
||||
|
||||
public int drawShadow(PoseStack pPoseStack, String pText, float pX, float pY, int pColor) {
|
||||
return wrapped.draw(pPoseStack, pText, pX, pY, pColor);
|
||||
}
|
||||
|
||||
public int drawShadow(PoseStack pPoseStack, String pText, float pX, float pY, int pColor, boolean pTransparent) {
|
||||
return wrapped.draw(pPoseStack, pText, pX, pY, pColor);
|
||||
}
|
||||
|
||||
public int draw(PoseStack pPoseStack, String pText, float pX, float pY, int pColor) {
|
||||
return wrapped.draw(pPoseStack, pText, pX, pY, pColor);
|
||||
}
|
||||
|
||||
public int drawShadow(PoseStack pPoseStack, FormattedCharSequence pText, float pX, float pY, int pColor) {
|
||||
return wrapped.draw(pPoseStack, pText, pX, pY, pColor);
|
||||
}
|
||||
|
||||
public int drawShadow(PoseStack pPoseStack, Component pText, float pX, float pY, int pColor) {
|
||||
return wrapped.draw(pPoseStack, pText, pX, pY, pColor);
|
||||
}
|
||||
|
||||
public int draw(PoseStack pPoseStack, FormattedCharSequence pText, float pX, float pY, int pColor) {
|
||||
return wrapped.draw(pPoseStack, pText, pX, pY, pColor);
|
||||
|
||||
}
|
||||
|
||||
public int draw(PoseStack pPoseStack, Component pText, float pX, float pY, int pColor) {
|
||||
return wrapped.draw(pPoseStack, pText, pX, pY, pColor);
|
||||
}
|
||||
|
||||
public String bidirectionalShaping(String pText) {
|
||||
return wrapped.bidirectionalShaping(pText);
|
||||
}
|
||||
|
||||
public int drawInBatch(String pText, float pX, float pY, int pColor, boolean pDropShadow, Matrix4f pMatrix,
|
||||
MultiBufferSource pBuffer, boolean pTransparent, int pBackgroundColor, int pPackedLight) {
|
||||
return wrapped.drawInBatch(pText, pX, pY, pColor, pDropShadow, pMatrix, pBuffer, pTransparent, pBackgroundColor,
|
||||
pPackedLight);
|
||||
}
|
||||
|
||||
public int drawInBatch(String pText, float pX, float pY, int pColor, boolean pDropShadow, Matrix4f pMatrix,
|
||||
MultiBufferSource pBuffer, boolean pTransparent, int pBackgroundColor, int pPackedLight, boolean pBidiFlag) {
|
||||
return wrapped.drawInBatch(pText, pX, pY, pColor, pDropShadow, pMatrix, pBuffer, pTransparent, pBackgroundColor,
|
||||
pPackedLight, pBidiFlag);
|
||||
}
|
||||
|
||||
public int drawInBatch(Component pText, float pX, float pY, int pColor, boolean pDropShadow, Matrix4f pMatrix,
|
||||
MultiBufferSource pBuffer, boolean pTransparent, int pBackgroundColor, int pPackedLight) {
|
||||
return wrapped.drawInBatch(pText, pX, pY, pColor, pDropShadow, pMatrix, pBuffer, pTransparent, pBackgroundColor,
|
||||
pPackedLight);
|
||||
}
|
||||
|
||||
public int drawInBatch(FormattedCharSequence pText, float pX, float pY, int pColor, boolean pDropShadow,
|
||||
Matrix4f pMatrix, MultiBufferSource pBuffer, boolean pTransparent, int pBackgroundColor, int pPackedLight) {
|
||||
return wrapped.drawInBatch(pText, pX, pY, pColor, pDropShadow, pMatrix, pBuffer, pTransparent, pBackgroundColor,
|
||||
pPackedLight);
|
||||
}
|
||||
|
||||
public void drawInBatch8xOutline(FormattedCharSequence pText, float pX, float pY, int pColor, int pBackgroundColor,
|
||||
Matrix4f pMatrix, MultiBufferSource pBuffer, int pPackedLightCoords) {
|
||||
wrapped.drawInBatch8xOutline(pText, pX, pY, pColor, pBackgroundColor, pMatrix, pBuffer, pPackedLightCoords);
|
||||
}
|
||||
|
||||
public int width(String pText) {
|
||||
return wrapped.width(pText);
|
||||
}
|
||||
|
||||
public int width(FormattedText pText) {
|
||||
return wrapped.width(pText);
|
||||
}
|
||||
|
||||
public int width(FormattedCharSequence pText) {
|
||||
return wrapped.width(pText);
|
||||
}
|
||||
|
||||
public String plainSubstrByWidth(String p_92838_, int p_92839_, boolean p_92840_) {
|
||||
return wrapped.plainSubstrByWidth(p_92838_, p_92839_, p_92840_);
|
||||
}
|
||||
|
||||
public String plainSubstrByWidth(String pText, int pMaxWidth) {
|
||||
return wrapped.plainSubstrByWidth(pText, pMaxWidth);
|
||||
}
|
||||
|
||||
public FormattedText substrByWidth(FormattedText pText, int pMaxWidth) {
|
||||
return wrapped.substrByWidth(pText, pMaxWidth);
|
||||
}
|
||||
|
||||
public void drawWordWrap(FormattedText pText, int pX, int pY, int pMaxWidth, int pColor) {
|
||||
wrapped.drawWordWrap(pText, pX, pY, pMaxWidth, pColor);
|
||||
}
|
||||
|
||||
public int wordWrapHeight(String pStr, int pMaxWidth) {
|
||||
return wrapped.wordWrapHeight(pStr, pMaxWidth);
|
||||
}
|
||||
|
||||
public List<FormattedCharSequence> split(FormattedText pText, int pMaxWidth) {
|
||||
return wrapped.split(pText, pMaxWidth);
|
||||
}
|
||||
|
||||
public boolean isBidirectional() {
|
||||
return wrapped.isBidirectional();
|
||||
}
|
||||
|
||||
public StringSplitter getSplitter() {
|
||||
return wrapped.getSplitter();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
public class RunningScheduleScreen {
|
||||
|
||||
/**
|
||||
* use the same rendering and mouse handling from schedule screen but add
|
||||
* progress of train based on ScheduleRuntime
|
||||
*/
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import com.simibubi.create.foundation.gui.container.GhostItemContainer;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.ClickType;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.SlotItemHandler;
|
||||
|
||||
public class ScheduleContainer extends GhostItemContainer<ItemStack> {
|
||||
|
||||
public boolean slotsActive = true;
|
||||
public boolean targetSlotActive = true;
|
||||
|
||||
public ScheduleContainer(MenuType<?> type, int id, Inventory inv, FriendlyByteBuf extraData) {
|
||||
super(type, id, inv, extraData);
|
||||
}
|
||||
|
||||
public ScheduleContainer(MenuType<?> type, int id, Inventory inv, ItemStack contentHolder) {
|
||||
super(type, id, inv, contentHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemStackHandler createGhostInventory() {
|
||||
return new ItemStackHandler(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) {
|
||||
if (slotId != playerInventory.selected || clickTypeIn == ClickType.THROW)
|
||||
super.clicked(slotId, dragType, clickTypeIn, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean allowRepeats() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemStack createOnClient(FriendlyByteBuf extraData) {
|
||||
return extraData.readItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addSlots() {
|
||||
addPlayerSlots(46, 140);
|
||||
addSlot(new InactiveItemHandlerSlot(ghostInventory, 0, 54, 88));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addPlayerSlots(int x, int y) {
|
||||
for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot)
|
||||
this.addSlot(new InactiveSlot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58));
|
||||
for (int row = 0; row < 3; ++row)
|
||||
for (int col = 0; col < 9; ++col)
|
||||
this.addSlot(new InactiveSlot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveData(ItemStack contentHolder) {}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(Player player) {
|
||||
return playerInventory.getSelected() == contentHolder;
|
||||
}
|
||||
|
||||
class InactiveSlot extends Slot {
|
||||
|
||||
public InactiveSlot(Container pContainer, int pIndex, int pX, int pY) {
|
||||
super(pContainer, pIndex, pX, pY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return slotsActive;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class InactiveItemHandlerSlot extends SlotItemHandler {
|
||||
|
||||
public InactiveItemHandlerSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) {
|
||||
super(itemHandler, index, xPosition, yPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return slotsActive && targetSlotActive;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import com.simibubi.create.AllContainerTypes;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||
import com.simibubi.create.content.logistics.trains.entity.CarriageContraption;
|
||||
import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
|
||||
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
|
||||
public class ScheduleItem extends Item implements MenuProvider {
|
||||
|
||||
public ScheduleItem(Properties pProperties) {
|
||||
super(pProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useOn(UseOnContext context) {
|
||||
if (context.getPlayer() == null)
|
||||
return InteractionResult.PASS;
|
||||
return use(context.getLevel(), context.getPlayer(), context.getHand()).getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
|
||||
ItemStack heldItem = player.getItemInHand(hand);
|
||||
|
||||
if (!player.isShiftKeyDown() && hand == InteractionHand.MAIN_HAND) {
|
||||
if (!world.isClientSide && player instanceof ServerPlayer)
|
||||
NetworkHooks.openGui((ServerPlayer) player, this, buf -> {
|
||||
buf.writeItem(heldItem);
|
||||
});
|
||||
return InteractionResultHolder.success(heldItem);
|
||||
}
|
||||
return InteractionResultHolder.pass(heldItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult interactLivingEntity(ItemStack pStack, Player pPlayer, LivingEntity pInteractionTarget,
|
||||
InteractionHand pUsedHand) {
|
||||
InteractionResult pass = InteractionResult.PASS;
|
||||
|
||||
if (!pStack.hasTag())
|
||||
return pass;
|
||||
if (!pStack.getTag()
|
||||
.contains("Schedule"))
|
||||
return pass;
|
||||
|
||||
Schedule schedule = Schedule.fromTag(pStack.getTagElement("Schedule"));
|
||||
|
||||
if (pInteractionTarget == null)
|
||||
return pass;
|
||||
Entity rootVehicle = pInteractionTarget.getRootVehicle();
|
||||
if (!(rootVehicle instanceof CarriageContraptionEntity))
|
||||
return pass;
|
||||
if (pPlayer.level.isClientSide)
|
||||
return InteractionResult.SUCCESS;
|
||||
CarriageContraptionEntity entity = (CarriageContraptionEntity) rootVehicle;
|
||||
Contraption contraption = entity.getContraption();
|
||||
if (contraption instanceof CarriageContraption cc)
|
||||
cc.getCarriage().train.runtime.setSchedule(schedule, false);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractContainerMenu createMenu(int id, Inventory inv, Player player) {
|
||||
ItemStack heldItem = player.getMainHandItem();
|
||||
return new ScheduleContainer(AllContainerTypes.SCHEDULE.get(), id, inv, heldItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
return new TranslatableComponent(getDescriptionId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillItemCategory(CreativeModeTab pCategory, NonNullList<ItemStack> pItems) {}
|
||||
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.FilteredDestination;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleDestination;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleEntry;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleWaitCondition;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
public class ScheduleRuntime {
|
||||
|
||||
enum State {
|
||||
PRE_TRANSIT, IN_TRANSIT, POST_TRANSIT
|
||||
}
|
||||
|
||||
Train train;
|
||||
Schedule schedule;
|
||||
|
||||
boolean paused;
|
||||
boolean isAutoSchedule;
|
||||
int currentEntry;
|
||||
State state;
|
||||
|
||||
static final int INTERVAL = 40;
|
||||
int cooldown;
|
||||
List<Integer> conditionProgress;
|
||||
List<CompoundTag> conditionContext;
|
||||
|
||||
public ScheduleRuntime(Train train) {
|
||||
this.train = train;
|
||||
reset();
|
||||
}
|
||||
|
||||
public void destinationReached() {
|
||||
if (state != State.IN_TRANSIT)
|
||||
return;
|
||||
state = State.POST_TRANSIT;
|
||||
conditionProgress.clear();
|
||||
if (currentEntry >= schedule.entries.size())
|
||||
return;
|
||||
List<List<ScheduleWaitCondition>> conditions = schedule.entries.get(currentEntry).conditions;
|
||||
for (int i = 0; i < conditions.size(); i++) {
|
||||
conditionProgress.add(0);
|
||||
conditionContext.add(new CompoundTag());
|
||||
}
|
||||
}
|
||||
|
||||
public void tick(Level level) {
|
||||
if (schedule == null)
|
||||
return;
|
||||
if (paused)
|
||||
return;
|
||||
if (train.navigation.destination != null)
|
||||
return;
|
||||
if (currentEntry >= schedule.entries.size()) {
|
||||
currentEntry = 0;
|
||||
if (!schedule.cyclic)
|
||||
paused = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cooldown-- > 0)
|
||||
return;
|
||||
if (state == State.IN_TRANSIT)
|
||||
return;
|
||||
if (state == State.POST_TRANSIT) {
|
||||
tickConditions(level);
|
||||
return;
|
||||
}
|
||||
|
||||
GlobalStation nextStation = findNextStation();
|
||||
if (nextStation == null) {
|
||||
cooldown = INTERVAL;
|
||||
return;
|
||||
}
|
||||
if (nextStation == train.currentStation) {
|
||||
state = State.IN_TRANSIT;
|
||||
destinationReached();
|
||||
return;
|
||||
}
|
||||
|
||||
train.navigation.setDestination(nextStation);
|
||||
state = State.IN_TRANSIT;
|
||||
}
|
||||
|
||||
public void tickConditions(Level level) {
|
||||
List<List<ScheduleWaitCondition>> conditions = schedule.entries.get(currentEntry).conditions;
|
||||
for (int i = 0; i < conditions.size(); i++) {
|
||||
List<ScheduleWaitCondition> list = conditions.get(i);
|
||||
int progress = conditionProgress.get(i);
|
||||
|
||||
if (progress >= list.size()) {
|
||||
state = State.PRE_TRANSIT;
|
||||
currentEntry++;
|
||||
return;
|
||||
}
|
||||
|
||||
CompoundTag tag = conditionContext.get(i);
|
||||
ScheduleWaitCondition condition = list.get(progress);
|
||||
if (condition.tickCompletion(level, train, tag)) {
|
||||
conditionContext.set(i, new CompoundTag());
|
||||
conditionProgress.set(i, progress + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GlobalStation findNextStation() {
|
||||
ScheduleEntry entry = schedule.entries.get(currentEntry);
|
||||
ScheduleDestination destination = entry.destination;
|
||||
if (destination instanceof FilteredDestination filtered) {
|
||||
for (GlobalStation globalStation : train.graph.getStations()) {
|
||||
if (globalStation.name.equals(filtered.nameFilter))
|
||||
return globalStation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setSchedule(Schedule schedule, boolean auto) {
|
||||
reset();
|
||||
this.schedule = schedule;
|
||||
currentEntry = 0;
|
||||
paused = false;
|
||||
isAutoSchedule = auto;
|
||||
}
|
||||
|
||||
public Schedule getSchedule() {
|
||||
return schedule;
|
||||
}
|
||||
|
||||
public void discardSchedule() {
|
||||
reset();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
paused = true;
|
||||
isAutoSchedule = false;
|
||||
currentEntry = 0;
|
||||
schedule = null;
|
||||
state = State.PRE_TRANSIT;
|
||||
conditionProgress = new ArrayList<>();
|
||||
conditionContext = new ArrayList<>();
|
||||
}
|
||||
|
||||
public CompoundTag write() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putInt("CurrentEntry", currentEntry);
|
||||
tag.putBoolean("AutoSchedule", isAutoSchedule);
|
||||
tag.putBoolean("Paused", paused);
|
||||
if (schedule != null)
|
||||
tag.put("Schedule", schedule.write());
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void read(CompoundTag tag) {
|
||||
reset();
|
||||
paused = tag.getBoolean("Paused");
|
||||
isAutoSchedule = tag.getBoolean("AutoSchedule");
|
||||
currentEntry = tag.getInt("CurrentEntry");
|
||||
if (tag.contains("Schedule"))
|
||||
schedule = Schedule.fromTag(tag.getCompound("Schedule"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,941 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.jozufozu.flywheel.util.transform.MatrixTransformStack;
|
||||
import com.mojang.blaze3d.platform.InputConstants;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.FilteredDestination;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleDestination;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleEditPacket;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleEntry;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleWaitCondition;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduledDelay;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.TimedWaitCondition.TimeUnit;
|
||||
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
import com.simibubi.create.foundation.gui.UIRenderHelper;
|
||||
import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen;
|
||||
import com.simibubi.create.foundation.gui.element.GuiGameElement;
|
||||
import com.simibubi.create.foundation.gui.widget.AbstractSimiWidget;
|
||||
import com.simibubi.create.foundation.gui.widget.IconButton;
|
||||
import com.simibubi.create.foundation.gui.widget.Indicator;
|
||||
import com.simibubi.create.foundation.gui.widget.Indicator.State;
|
||||
import com.simibubi.create.foundation.gui.widget.Label;
|
||||
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.client.gui.components.Widget;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.renderer.Rect2i;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.util.FormattedCharSequence;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraftforge.client.gui.GuiUtils;
|
||||
|
||||
public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContainer> {
|
||||
|
||||
private static final int CARD_HEADER = 22;
|
||||
private static final int CARD_WIDTH = 195;
|
||||
|
||||
private List<Rect2i> extraAreas = Collections.emptyList();
|
||||
|
||||
private List<LerpedFloat> horizontalScrolls = new ArrayList<>();
|
||||
private LerpedFloat scroll = LerpedFloat.linear()
|
||||
.startWithValue(0);
|
||||
|
||||
Schedule schedule;
|
||||
|
||||
private IconButton confirmButton;
|
||||
private IconButton cyclicButton;
|
||||
private Indicator cyclicIndicator;
|
||||
|
||||
private ScheduleDestination editingDestination;
|
||||
private ScheduleWaitCondition editingCondition;
|
||||
private SelectionScrollInput scrollInput;
|
||||
private Label scrollInputLabel;
|
||||
private IconButton editorConfirm, editorDelete;
|
||||
private Consumer<Boolean> onEditorClose;
|
||||
private List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets;
|
||||
private List<Integer> editorDividers;
|
||||
|
||||
public ScheduleScreen(ScheduleContainer container, Inventory inv, Component title) {
|
||||
super(container, inv, title);
|
||||
schedule = new Schedule();
|
||||
CompoundTag tag = container.contentHolder.getOrCreateTag()
|
||||
.getCompound("Schedule");
|
||||
if (!tag.isEmpty())
|
||||
schedule = Schedule.fromTag(tag);
|
||||
container.slotsActive = false;
|
||||
editorSubWidgets = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
AllGuiTextures bg = AllGuiTextures.SCHEDULE;
|
||||
setWindowSize(bg.width, bg.height + 22);
|
||||
super.init();
|
||||
clearWidgets();
|
||||
|
||||
confirmButton = new IconButton(leftPos + bg.width - 42, topPos + bg.height - 24, AllIcons.I_CONFIRM);
|
||||
confirmButton.withCallback(() -> minecraft.player.closeContainer());
|
||||
addRenderableWidget(confirmButton);
|
||||
|
||||
cyclicIndicator = new Indicator(leftPos + 21, topPos + 196, TextComponent.EMPTY);
|
||||
cyclicIndicator.state = schedule.cyclic ? State.ON : State.OFF;
|
||||
addRenderableWidget(cyclicIndicator);
|
||||
|
||||
cyclicButton = new IconButton(leftPos + 21, topPos + 202, AllIcons.I_REFRESH);
|
||||
cyclicButton.withCallback(() -> {
|
||||
schedule.cyclic = !schedule.cyclic;
|
||||
cyclicIndicator.state = schedule.cyclic ? State.ON : State.OFF;
|
||||
});
|
||||
List<Component> tip = cyclicButton.getToolTip();
|
||||
tip.add(Lang.translate("schedule.loop"));
|
||||
tip.add(Lang.translate("schedule.loop1")
|
||||
.withStyle(ChatFormatting.GRAY));
|
||||
tip.add(Lang.translate("schedule.loop2")
|
||||
.withStyle(ChatFormatting.GRAY));
|
||||
|
||||
addRenderableWidget(cyclicButton);
|
||||
|
||||
stopEditing();
|
||||
extraAreas = ImmutableList.of(new Rect2i(leftPos + 255, topPos + 182, 45, 45));
|
||||
horizontalScrolls.clear();
|
||||
for (int i = 0; i < schedule.entries.size(); i++)
|
||||
horizontalScrolls.add(LerpedFloat.linear()
|
||||
.startWithValue(0));
|
||||
}
|
||||
|
||||
protected void startEditing(IScheduleInput field, Consumer<Boolean> onClose, boolean allowDeletion) {
|
||||
onEditorClose = onClose;
|
||||
confirmButton.visible = false;
|
||||
cyclicButton.visible = false;
|
||||
cyclicIndicator.visible = false;
|
||||
scrollInput = new SelectionScrollInput(leftPos + 56, topPos + 65, 143, 16);
|
||||
scrollInputLabel = new Label(leftPos + 59, topPos + 69, new TextComponent("")).withShadow();
|
||||
editorConfirm = new IconButton(leftPos + 56 + 168, topPos + 65 + 22, AllIcons.I_CONFIRM);
|
||||
if (allowDeletion)
|
||||
editorDelete = new IconButton(leftPos + 56 - 45, topPos + 65 + 22, AllIcons.I_TRASH);
|
||||
menu.slotsActive = true;
|
||||
menu.targetSlotActive = field.needsSlot();
|
||||
|
||||
if (field instanceof ScheduleDestination dest) {
|
||||
int startIndex = 0;
|
||||
for (int i = 0; i < Schedule.DESTINATION_TYPES.size(); i++)
|
||||
if (Schedule.DESTINATION_TYPES.get(i)
|
||||
.getFirst()
|
||||
.equals(dest.getId()))
|
||||
startIndex = i;
|
||||
editingDestination = dest;
|
||||
updateEditorSubwidgets(editingDestination);
|
||||
scrollInput.forOptions(Schedule.getTypeOptions(Schedule.DESTINATION_TYPES))
|
||||
.titled(Lang.translate("schedule.destination_type"))
|
||||
.writingTo(scrollInputLabel)
|
||||
.calling(index -> {
|
||||
ScheduleDestination newlyCreated = Schedule.DESTINATION_TYPES.get(index)
|
||||
.getSecond()
|
||||
.get();
|
||||
if (editingDestination.getId()
|
||||
.equals(newlyCreated.getId()))
|
||||
return;
|
||||
editingDestination = newlyCreated;
|
||||
updateEditorSubwidgets(editingDestination);
|
||||
})
|
||||
.setState(startIndex);
|
||||
}
|
||||
|
||||
if (field instanceof ScheduleWaitCondition cond) {
|
||||
int startIndex = 0;
|
||||
for (int i = 0; i < Schedule.CONDITION_TYPES.size(); i++)
|
||||
if (Schedule.CONDITION_TYPES.get(i)
|
||||
.getFirst()
|
||||
.equals(cond.getId()))
|
||||
startIndex = i;
|
||||
editingCondition = cond;
|
||||
updateEditorSubwidgets(editingCondition);
|
||||
scrollInput.forOptions(Schedule.getTypeOptions(Schedule.CONDITION_TYPES))
|
||||
.titled(Lang.translate("schedule.condition_type"))
|
||||
.writingTo(scrollInputLabel)
|
||||
.calling(index -> {
|
||||
ScheduleWaitCondition newlyCreated = Schedule.CONDITION_TYPES.get(index)
|
||||
.getSecond()
|
||||
.get();
|
||||
if (editingCondition.getId()
|
||||
.equals(newlyCreated.getId()))
|
||||
return;
|
||||
editingCondition = newlyCreated;
|
||||
updateEditorSubwidgets(editingCondition);
|
||||
})
|
||||
.setState(startIndex);
|
||||
}
|
||||
|
||||
addRenderableWidget(scrollInput);
|
||||
addRenderableWidget(scrollInputLabel);
|
||||
addRenderableWidget(editorConfirm);
|
||||
if (allowDeletion)
|
||||
addRenderableWidget(editorDelete);
|
||||
}
|
||||
|
||||
protected void stopEditing() {
|
||||
confirmButton.visible = true;
|
||||
cyclicButton.visible = true;
|
||||
cyclicIndicator.visible = true;
|
||||
if (editingCondition == null && editingDestination == null)
|
||||
return;
|
||||
removeWidget(scrollInput);
|
||||
removeWidget(scrollInputLabel);
|
||||
removeWidget(editorConfirm);
|
||||
removeWidget(editorDelete);
|
||||
IScheduleInput editing = editingCondition == null ? editingDestination : editingCondition;
|
||||
editing.setItem(menu.getSlot(36)
|
||||
.getItem());
|
||||
editorSubWidgets.forEach(p -> p.getSecond()
|
||||
.accept(editing, p.getFirst()));
|
||||
editorSubWidgets.forEach(p -> removeWidget(p.getFirst()));
|
||||
editorSubWidgets.clear();
|
||||
editorDividers = null;
|
||||
editingCondition = null;
|
||||
editingDestination = null;
|
||||
editorConfirm = null;
|
||||
editorDelete = null;
|
||||
menu.slotsActive = false;
|
||||
init();
|
||||
}
|
||||
|
||||
protected void updateEditorSubwidgets(IScheduleInput field) {
|
||||
menu.targetSlotActive = field.needsSlot();
|
||||
editorSubWidgets.forEach(p -> removeWidget(p.getFirst()));
|
||||
editorSubWidgets.clear();
|
||||
editorDividers = new ArrayList<>();
|
||||
field.createWidgets(this, editorSubWidgets, editorDividers, leftPos - 2, topPos + 40);
|
||||
if (editorSubWidgets.isEmpty())
|
||||
editorDividers = null;
|
||||
editorSubWidgets.forEach(pair -> {
|
||||
GuiEventListener e = pair.getFirst();
|
||||
if (e instanceof AbstractSimiWidget)
|
||||
addRenderableWidget((AbstractSimiWidget) e);
|
||||
if (e instanceof EditBox)
|
||||
addRenderableWidget((EditBox) e);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void containerTick() {
|
||||
super.containerTick();
|
||||
scroll.tickChaser();
|
||||
for (LerpedFloat lerpedFloat : horizontalScrolls)
|
||||
lerpedFloat.tickChaser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) {
|
||||
partialTicks = minecraft.getFrameTime();
|
||||
|
||||
if (menu.slotsActive)
|
||||
super.render(matrixStack, mouseX, mouseY, partialTicks);
|
||||
else {
|
||||
renderBackground(matrixStack);
|
||||
renderBg(matrixStack, partialTicks, mouseX, mouseY);
|
||||
for (Widget widget : this.renderables)
|
||||
widget.render(matrixStack, mouseX, mouseY, partialTicks);
|
||||
renderForeground(matrixStack, mouseX, mouseY, partialTicks);
|
||||
}
|
||||
}
|
||||
|
||||
protected void renderSchedule(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) {
|
||||
UIRenderHelper.swapAndBlitColor(minecraft.getMainRenderTarget(), UIRenderHelper.framebuffer);
|
||||
UIRenderHelper.drawStretched(matrixStack, leftPos + 33, topPos + 16, 3, 173, -100,
|
||||
AllGuiTextures.SCHEDULE_STRIP_DARK);
|
||||
|
||||
int yOffset = 25;
|
||||
List<ScheduleEntry> entries = schedule.entries;
|
||||
float scrollOffset = -scroll.getValue(partialTicks);
|
||||
|
||||
for (int i = 0; i <= entries.size(); i++) {
|
||||
startStencil(matrixStack, leftPos + 16, topPos + 16, 220, 173);
|
||||
matrixStack.pushPose();
|
||||
matrixStack.translate(0, scrollOffset, 0);
|
||||
if (i == 0 || entries.size() == 0)
|
||||
UIRenderHelper.drawStretched(matrixStack, leftPos + 33, topPos + 16, 3, 10, -100,
|
||||
AllGuiTextures.SCHEDULE_STRIP_LIGHT);
|
||||
|
||||
if (i == entries.size()) {
|
||||
if (i > 0)
|
||||
yOffset += 9;
|
||||
AllGuiTextures.SCHEDULE_STRIP_END.render(matrixStack, leftPos + 29, topPos + yOffset);
|
||||
AllGuiTextures.SCHEDULE_CARD_NEW.render(matrixStack, leftPos + 43, topPos + yOffset);
|
||||
matrixStack.popPose();
|
||||
endStencil();
|
||||
break;
|
||||
}
|
||||
|
||||
ScheduleEntry scheduleEntry = entries.get(i);
|
||||
int cardY = yOffset;
|
||||
int cardHeight = renderScheduleEntry(matrixStack, scheduleEntry, cardY, mouseX, mouseY, partialTicks);
|
||||
yOffset += cardHeight;
|
||||
|
||||
if (i + 1 < entries.size()) {
|
||||
AllGuiTextures.SCHEDULE_STRIP_DOTTED.render(matrixStack, leftPos + 29, topPos + yOffset - 3);
|
||||
yOffset += 10;
|
||||
}
|
||||
|
||||
matrixStack.popPose();
|
||||
endStencil();
|
||||
|
||||
float h = cardHeight - 26;
|
||||
float y1 = cardY + 24 + scrollOffset;
|
||||
float y2 = y1 + h;
|
||||
if (y2 > 189)
|
||||
h -= y2 - 189;
|
||||
if (y1 < 16) {
|
||||
float correction = 16 - y1;
|
||||
y1 += correction;
|
||||
h -= correction;
|
||||
}
|
||||
|
||||
if (h <= 0)
|
||||
continue;
|
||||
|
||||
startStencil(matrixStack, leftPos + 43, topPos + y1, 161, h);
|
||||
|
||||
matrixStack.pushPose();
|
||||
matrixStack.translate(0, scrollOffset, 0);
|
||||
renderScheduleConditions(matrixStack, scheduleEntry, cardY, mouseX, mouseY, partialTicks, cardHeight, i);
|
||||
matrixStack.popPose();
|
||||
endStencil();
|
||||
|
||||
if (isConditionAreaScrollable(scheduleEntry)) {
|
||||
startStencil(matrixStack, leftPos + 16, topPos + 16, 220, 173);
|
||||
matrixStack.pushPose();
|
||||
matrixStack.translate(0, scrollOffset, 0);
|
||||
int center = (cardHeight - 8 + CARD_HEADER) / 2;
|
||||
float chaseTarget = horizontalScrolls.get(i)
|
||||
.getChaseTarget();
|
||||
if (!Mth.equal(chaseTarget, 0))
|
||||
AllGuiTextures.SCHEDULE_SCROLL_LEFT.render(matrixStack, leftPos + 40, topPos + cardY + center);
|
||||
if (!Mth.equal(chaseTarget, scheduleEntry.conditions.size() - 1))
|
||||
AllGuiTextures.SCHEDULE_SCROLL_RIGHT.render(matrixStack, leftPos + 203, topPos + cardY + center);
|
||||
matrixStack.popPose();
|
||||
endStencil();
|
||||
}
|
||||
}
|
||||
|
||||
int zLevel = 200;
|
||||
Matrix4f mat = matrixStack.last()
|
||||
.pose();
|
||||
GuiUtils.drawGradientRect(mat, zLevel, leftPos + 16, topPos + 16, leftPos + 16 + 220, topPos + 16 + 10,
|
||||
0x77000000, 0x00000000);
|
||||
GuiUtils.drawGradientRect(mat, zLevel, leftPos + 16, topPos + 179, leftPos + 16 + 220, topPos + 179 + 10,
|
||||
0x00000000, 0x77000000);
|
||||
UIRenderHelper.swapAndBlitColor(UIRenderHelper.framebuffer, minecraft.getMainRenderTarget());
|
||||
}
|
||||
|
||||
public int renderScheduleEntry(PoseStack matrixStack, ScheduleEntry entry, int yOffset, int mouseX, int mouseY,
|
||||
float partialTicks) {
|
||||
int zLevel = -100;
|
||||
|
||||
AllGuiTextures light = AllGuiTextures.SCHEDULE_CARD_LIGHT;
|
||||
AllGuiTextures medium = AllGuiTextures.SCHEDULE_CARD_MEDIUM;
|
||||
AllGuiTextures dark = AllGuiTextures.SCHEDULE_CARD_DARK;
|
||||
|
||||
int cardWidth = CARD_WIDTH;
|
||||
int cardHeader = CARD_HEADER;
|
||||
int maxRows = 0;
|
||||
for (List<ScheduleWaitCondition> list : entry.conditions)
|
||||
maxRows = Math.max(maxRows, list.size());
|
||||
int cardHeight = cardHeader + 24 + maxRows * 18;
|
||||
|
||||
matrixStack.pushPose();
|
||||
matrixStack.translate(leftPos + 25, topPos + yOffset, 0);
|
||||
|
||||
UIRenderHelper.drawStretched(matrixStack, 0, 1, cardWidth, cardHeight - 2, zLevel, light);
|
||||
UIRenderHelper.drawStretched(matrixStack, 1, 0, cardWidth - 2, cardHeight, zLevel, light);
|
||||
UIRenderHelper.drawStretched(matrixStack, 1, 1, cardWidth - 2, cardHeight - 2, zLevel, dark);
|
||||
UIRenderHelper.drawStretched(matrixStack, 2, 2, cardWidth - 4, cardHeight - 4, zLevel, medium);
|
||||
UIRenderHelper.drawStretched(matrixStack, 2, 2, cardWidth - 4, cardHeader, zLevel, light);
|
||||
|
||||
AllGuiTextures.SCHEDULE_CARD_REMOVE.render(matrixStack, cardWidth - 14, 2);
|
||||
AllGuiTextures.SCHEDULE_CARD_DUPLICATE.render(matrixStack, cardWidth - 14, cardHeight - 14);
|
||||
|
||||
int i = schedule.entries.indexOf(entry);
|
||||
if (i > 0)
|
||||
AllGuiTextures.SCHEDULE_CARD_MOVE_UP.render(matrixStack, cardWidth, cardHeader - 14);
|
||||
if (i < schedule.entries.size() - 1)
|
||||
AllGuiTextures.SCHEDULE_CARD_MOVE_DOWN.render(matrixStack, cardWidth, cardHeader);
|
||||
|
||||
UIRenderHelper.drawStretched(matrixStack, 8, 0, 3, cardHeight + 10, zLevel,
|
||||
AllGuiTextures.SCHEDULE_STRIP_LIGHT);
|
||||
AllGuiTextures.SCHEDULE_STRIP_TRAVEL.render(matrixStack, 4, 6);
|
||||
AllGuiTextures.SCHEDULE_STRIP_WAIT.render(matrixStack, 4, 28);
|
||||
|
||||
Pair<ItemStack, Component> destination = entry.destination.getSummary();
|
||||
renderInput(matrixStack, destination, 26, 5, false, 100);
|
||||
entry.destination.renderSpecialIcon(matrixStack, 30, 5);
|
||||
|
||||
matrixStack.popPose();
|
||||
|
||||
return cardHeight;
|
||||
}
|
||||
|
||||
public void renderScheduleConditions(PoseStack matrixStack, ScheduleEntry entry, int yOffset, int mouseX,
|
||||
int mouseY, float partialTicks, int cardHeight, int entryIndex) {
|
||||
int cardWidth = CARD_WIDTH;
|
||||
int cardHeader = CARD_HEADER;
|
||||
|
||||
matrixStack.pushPose();
|
||||
matrixStack.translate(leftPos + 25, topPos + yOffset, 0);
|
||||
int xOffset = 26;
|
||||
float scrollOffset = getConditionScroll(entry, partialTicks, entryIndex);
|
||||
|
||||
matrixStack.pushPose();
|
||||
matrixStack.translate(-scrollOffset, 0, 0);
|
||||
|
||||
for (List<ScheduleWaitCondition> list : entry.conditions) {
|
||||
int maxWidth = getConditionColumnWidth(list);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
ScheduleWaitCondition scheduleWaitCondition = list.get(i);
|
||||
Math.max(maxWidth, renderInput(matrixStack, scheduleWaitCondition.getSummary(), xOffset, 29 + i * 18,
|
||||
i != 0, maxWidth));
|
||||
scheduleWaitCondition.renderSpecialIcon(matrixStack, xOffset + 4, 29 + i * 18);
|
||||
}
|
||||
|
||||
AllGuiTextures.SCHEDULE_CONDITION_APPEND.render(matrixStack, xOffset + (maxWidth - 10) / 2,
|
||||
29 + list.size() * 18);
|
||||
xOffset += maxWidth + 10;
|
||||
}
|
||||
|
||||
AllGuiTextures.SCHEDULE_CONDITION_NEW.render(matrixStack, xOffset - 3, 29);
|
||||
matrixStack.popPose();
|
||||
|
||||
if (xOffset + 16 > cardWidth - 26) {
|
||||
new MatrixTransformStack(matrixStack).rotateZ(-90);
|
||||
Matrix4f m = matrixStack.last()
|
||||
.pose();
|
||||
GuiUtils.drawGradientRect(m, 200, -cardHeight + 2, 18, -2 - cardHeader, 28, 0x44000000, 0x00000000);
|
||||
GuiUtils.drawGradientRect(m, 200, -cardHeight + 2, cardWidth - 26, -2 - cardHeader, cardWidth - 16,
|
||||
0x00000000, 0x44000000);
|
||||
}
|
||||
|
||||
matrixStack.popPose();
|
||||
}
|
||||
|
||||
private boolean isConditionAreaScrollable(ScheduleEntry entry) {
|
||||
int xOffset = 26;
|
||||
for (List<ScheduleWaitCondition> list : entry.conditions)
|
||||
xOffset += getConditionColumnWidth(list) + 10;
|
||||
return xOffset + 16 > CARD_WIDTH - 26;
|
||||
}
|
||||
|
||||
private float getConditionScroll(ScheduleEntry entry, float partialTicks, int entryIndex) {
|
||||
float scrollOffset = 0;
|
||||
float scrollIndex = horizontalScrolls.get(entryIndex)
|
||||
.getValue(partialTicks);
|
||||
for (List<ScheduleWaitCondition> list : entry.conditions) {
|
||||
int maxWidth = getConditionColumnWidth(list);
|
||||
float partialOfThisColumn = Math.min(1, scrollIndex);
|
||||
scrollOffset += (maxWidth + 10) * partialOfThisColumn;
|
||||
scrollIndex -= partialOfThisColumn;
|
||||
}
|
||||
return scrollOffset;
|
||||
}
|
||||
|
||||
private int getConditionColumnWidth(List<ScheduleWaitCondition> list) {
|
||||
int maxWidth = 0;
|
||||
for (ScheduleWaitCondition scheduleWaitCondition : list)
|
||||
maxWidth = Math.max(maxWidth, getFieldSize(32, scheduleWaitCondition.getSummary()));
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
protected int renderInput(PoseStack matrixStack, Pair<ItemStack, Component> pair, int x, int y, boolean clean,
|
||||
int minSize) {
|
||||
ItemStack stack = pair.getFirst();
|
||||
Component text = pair.getSecond();
|
||||
boolean hasItem = !stack.isEmpty();
|
||||
int fieldSize = getFieldSize(minSize, pair);
|
||||
matrixStack.pushPose();
|
||||
|
||||
AllGuiTextures left =
|
||||
clean ? AllGuiTextures.SCHEDULE_CONDITION_LEFT_CLEAN : AllGuiTextures.SCHEDULE_CONDITION_LEFT;
|
||||
AllGuiTextures middle = AllGuiTextures.SCHEDULE_CONDITION_MIDDLE;
|
||||
AllGuiTextures item = AllGuiTextures.SCHEDULE_CONDITION_ITEM;
|
||||
AllGuiTextures right = AllGuiTextures.SCHEDULE_CONDITION_RIGHT;
|
||||
|
||||
matrixStack.translate(x, y, 0);
|
||||
UIRenderHelper.drawStretched(matrixStack, 0, 0, fieldSize, 16, -100, middle);
|
||||
left.render(matrixStack, clean ? 0 : -3, 0);
|
||||
right.render(matrixStack, fieldSize - 2, 0);
|
||||
if (hasItem)
|
||||
item.render(matrixStack, 3, 0);
|
||||
if (hasItem) {
|
||||
item.render(matrixStack, 3, 0);
|
||||
if (stack.getItem() != Items.STRUCTURE_VOID)
|
||||
GuiGameElement.of(stack)
|
||||
.at(4, 0)
|
||||
.render(matrixStack);
|
||||
}
|
||||
|
||||
if (text != null)
|
||||
font.drawShadow(matrixStack, text, hasItem ? 28 : 8, 4, 0xff_f2f2ee);
|
||||
|
||||
matrixStack.popPose();
|
||||
return fieldSize;
|
||||
}
|
||||
|
||||
private Component clickToEdit = Lang.translate("gui.schedule.lmb_edit")
|
||||
.withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC);
|
||||
private Component rClickToDelete = Lang.translate("gui.schedule.rmb_remove")
|
||||
.withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC);
|
||||
|
||||
public boolean action(PoseStack ms, double mouseX, double mouseY, int click) {
|
||||
if (editingCondition != null || editingDestination != null)
|
||||
return false;
|
||||
|
||||
Component empty = new TextComponent("");
|
||||
|
||||
int mx = (int) mouseX;
|
||||
int my = (int) mouseY;
|
||||
int x = mx - leftPos - 25;
|
||||
int y = my - topPos - 25;
|
||||
if (x < 0 || x >= 205)
|
||||
return false;
|
||||
if (y < 0 || y >= 173)
|
||||
return false;
|
||||
y += scroll.getValue(0);
|
||||
|
||||
List<ScheduleEntry> entries = schedule.entries;
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
ScheduleEntry entry = entries.get(i);
|
||||
int maxRows = 0;
|
||||
for (List<ScheduleWaitCondition> list : entry.conditions)
|
||||
maxRows = Math.max(maxRows, list.size());
|
||||
int cardHeight = CARD_HEADER + 24 + maxRows * 18;
|
||||
|
||||
if (y >= cardHeight) {
|
||||
y -= cardHeight + 10;
|
||||
if (y < 0)
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
int fieldSize = getFieldSize(100, entry.destination.getSummary());
|
||||
if (x > 25 && x <= 25 + fieldSize && y > 4 && y <= 20) {
|
||||
List<Component> components = new ArrayList<>();
|
||||
components.add(Lang.translate("schedule.destination_type")
|
||||
.withStyle(ChatFormatting.GOLD));
|
||||
components.addAll(entry.destination.getTitleAs("destination"));
|
||||
components.add(empty);
|
||||
components.add(clickToEdit);
|
||||
renderTooltip(ms, components, Optional.empty(), mx, my);
|
||||
if (click == 0)
|
||||
startEditing(entry.destination, confirmed -> {
|
||||
if (confirmed)
|
||||
entry.destination = editingDestination;
|
||||
}, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (x > 180 && x <= 192) {
|
||||
if (y > 0 && y <= 14) {
|
||||
renderTooltip(ms, ImmutableList.of(Lang.translate("gui.schedule.remove_entry")), Optional.empty(),
|
||||
mx, my);
|
||||
if (click == 0) {
|
||||
entries.remove(entry);
|
||||
init();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (y > cardHeight - 14) {
|
||||
renderTooltip(ms, ImmutableList.of(Lang.translate("gui.schedule.duplicate")), Optional.empty(), mx,
|
||||
my);
|
||||
if (click == 0) {
|
||||
entries.add(entries.indexOf(entry), entry.clone());
|
||||
init();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (x > 194) {
|
||||
if (y > 7 && y <= 20 && i > 0) {
|
||||
renderTooltip(ms, ImmutableList.of(Lang.translate("gui.schedule.move_up")), Optional.empty(), mx,
|
||||
my);
|
||||
if (click == 0) {
|
||||
entries.remove(entry);
|
||||
entries.add(i - 1, entry);
|
||||
init();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (y > 20 && y <= 33 && i < entries.size() - 1) {
|
||||
renderTooltip(ms, ImmutableList.of(Lang.translate("gui.schedule.move_down")), Optional.empty(), mx,
|
||||
my);
|
||||
if (click == 0) {
|
||||
entries.remove(entry);
|
||||
entries.add(i + 1, entry);
|
||||
init();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int center = (cardHeight - 8 + CARD_HEADER) / 2;
|
||||
if (y > center - 1 && y <= center + 7 && isConditionAreaScrollable(entry)) {
|
||||
float chaseTarget = horizontalScrolls.get(i)
|
||||
.getChaseTarget();
|
||||
if (x > 12 && x <= 19 && !Mth.equal(chaseTarget, 0)) {
|
||||
if (click == 0)
|
||||
horizontalScrolls.get(i)
|
||||
.chase(chaseTarget - 1, 0.5f, Chaser.EXP);
|
||||
return true;
|
||||
}
|
||||
if (x > 177 && x <= 184 && !Mth.equal(chaseTarget, entry.conditions.size() - 1)) {
|
||||
if (click == 0)
|
||||
horizontalScrolls.get(i)
|
||||
.chase(chaseTarget + 1, 0.5f, Chaser.EXP);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
x -= 18;
|
||||
y -= 28;
|
||||
if (x < 0 || y < 0 || x > 160)
|
||||
return false;
|
||||
x += getConditionScroll(entry, 0, i) - 8;
|
||||
|
||||
List<List<ScheduleWaitCondition>> columns = entry.conditions;
|
||||
for (int j = 0; j < columns.size(); j++) {
|
||||
List<ScheduleWaitCondition> conditions = columns.get(j);
|
||||
if (x < 0)
|
||||
return false;
|
||||
int w = getConditionColumnWidth(conditions);
|
||||
if (x >= w) {
|
||||
x -= w + 10;
|
||||
continue;
|
||||
}
|
||||
|
||||
int row = y / 18;
|
||||
if (row < conditions.size() && row >= 0) {
|
||||
boolean canRemove = conditions.size() > 1 || columns.size() > 1;
|
||||
List<Component> components = new ArrayList<>();
|
||||
components.add(Lang.translate("schedule.condition_type")
|
||||
.withStyle(ChatFormatting.GRAY));
|
||||
ScheduleWaitCondition condition = conditions.get(row);
|
||||
components.addAll(condition.getTitleAs("condition"));
|
||||
components.add(empty);
|
||||
components.add(clickToEdit);
|
||||
if (canRemove)
|
||||
components.add(rClickToDelete);
|
||||
renderTooltip(ms, components, Optional.empty(), mx, my);
|
||||
if (canRemove && click == 1) {
|
||||
conditions.remove(row);
|
||||
if (conditions.isEmpty())
|
||||
columns.remove(conditions);
|
||||
}
|
||||
if (click == 0)
|
||||
startEditing(condition, confirmed -> {
|
||||
conditions.remove(row);
|
||||
if (confirmed) {
|
||||
conditions.add(row, editingCondition);
|
||||
return;
|
||||
}
|
||||
if (conditions.isEmpty())
|
||||
columns.remove(conditions);
|
||||
}, canRemove);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (y > 18 * conditions.size() && y <= 18 * conditions.size() + 10 && x >= w / 2 - 5 && x < w / 2 + 5) {
|
||||
renderTooltip(ms, ImmutableList.of(Lang.translate("gui.schedule.add_condition")), Optional.empty(),
|
||||
mx, my);
|
||||
if (click == 0)
|
||||
startEditing(new ScheduledDelay(), confirmed -> {
|
||||
if (confirmed)
|
||||
conditions.add(editingCondition);
|
||||
}, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (x < 0 || x > 15 || y > 20)
|
||||
return false;
|
||||
|
||||
renderTooltip(ms, ImmutableList.of(Lang.translate("gui.schedule.alternative_condition")), Optional.empty(),
|
||||
mx, my);
|
||||
if (click == 0)
|
||||
startEditing(new ScheduledDelay(), confirmed -> {
|
||||
if (!confirmed)
|
||||
return;
|
||||
ArrayList<ScheduleWaitCondition> conditions = new ArrayList<>();
|
||||
conditions.add(editingCondition);
|
||||
columns.add(conditions);
|
||||
}, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (x < 18 || x > 33 || y > 14)
|
||||
return false;
|
||||
|
||||
renderTooltip(ms, ImmutableList.of(Lang.translate("gui.schedule.add_entry")), Optional.empty(), mx, my);
|
||||
if (click == 0)
|
||||
startEditing(new FilteredDestination(), confirmed -> {
|
||||
if (!confirmed)
|
||||
return;
|
||||
|
||||
ScheduleEntry entry = new ScheduleEntry();
|
||||
ScheduledDelay delay = new ScheduledDelay();
|
||||
ArrayList<ScheduleWaitCondition> initialConditions = new ArrayList<>();
|
||||
initialConditions.add(delay);
|
||||
entry.destination = editingDestination;
|
||||
delay.value = 5;
|
||||
delay.timeUnit = TimeUnit.SECONDS;
|
||||
entry.conditions.add(initialConditions);
|
||||
schedule.entries.add(entry);
|
||||
}, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getFieldSize(int minSize, Pair<ItemStack, Component> pair) {
|
||||
ItemStack stack = pair.getFirst();
|
||||
Component text = pair.getSecond();
|
||||
boolean hasItem = !stack.isEmpty();
|
||||
return Math.max((text == null ? 0 : font.width(text)) + (hasItem ? 20 : 0) + 16, minSize);
|
||||
}
|
||||
|
||||
protected void startStencil(PoseStack matrixStack, float x, float y, float w, float h) {
|
||||
RenderSystem.clear(GL30.GL_STENCIL_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX);
|
||||
|
||||
GL11.glDisable(GL11.GL_STENCIL_TEST);
|
||||
RenderSystem.stencilMask(~0);
|
||||
RenderSystem.clear(GL11.GL_STENCIL_BUFFER_BIT, Minecraft.ON_OSX);
|
||||
GL11.glEnable(GL11.GL_STENCIL_TEST);
|
||||
RenderSystem.stencilOp(GL11.GL_REPLACE, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||
RenderSystem.stencilMask(0xFF);
|
||||
RenderSystem.stencilFunc(GL11.GL_NEVER, 1, 0xFF);
|
||||
|
||||
matrixStack.pushPose();
|
||||
matrixStack.translate(x, y, 0);
|
||||
matrixStack.scale(w, h, 1);
|
||||
GuiUtils.drawGradientRect(matrixStack.last()
|
||||
.pose(), -100, 0, 0, 1, 1, 0xff000000, 0xff000000);
|
||||
matrixStack.popPose();
|
||||
|
||||
GL11.glEnable(GL11.GL_STENCIL_TEST);
|
||||
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||
RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF);
|
||||
}
|
||||
|
||||
protected void endStencil() {
|
||||
GL11.glDisable(GL11.GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) {
|
||||
if (editorConfirm != null && editorConfirm.isMouseOver(pMouseX, pMouseY) && onEditorClose != null) {
|
||||
onEditorClose.accept(true);
|
||||
stopEditing();
|
||||
return true;
|
||||
}
|
||||
if (editorDelete != null && editorDelete.isMouseOver(pMouseX, pMouseY) && onEditorClose != null) {
|
||||
onEditorClose.accept(false);
|
||||
stopEditing();
|
||||
return true;
|
||||
}
|
||||
if (action(new PoseStack(), pMouseX, pMouseY, pButton))
|
||||
return true;
|
||||
|
||||
return super.mouseClicked(pMouseX, pMouseY, pButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) {
|
||||
if (editingCondition == null && editingDestination == null)
|
||||
return super.keyPressed(pKeyCode, pScanCode, pModifiers);
|
||||
InputConstants.Key mouseKey = InputConstants.getKey(pKeyCode, pScanCode);
|
||||
boolean hitEnter = getFocused() instanceof EditBox && (pKeyCode == 257 || pKeyCode == 335);
|
||||
boolean hitE = getFocused() == null && minecraft.options.keyInventory.isActiveAndMatches(mouseKey);
|
||||
if (hitE || hitEnter) {
|
||||
onEditorClose.accept(true);
|
||||
stopEditing();
|
||||
return true;
|
||||
}
|
||||
return super.keyPressed(pKeyCode, pScanCode, pModifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(double pMouseX, double pMouseY, double pDelta) {
|
||||
if (editingCondition != null || editingDestination != null)
|
||||
return super.mouseScrolled(pMouseX, pMouseY, pDelta);
|
||||
|
||||
if (hasShiftDown()) {
|
||||
List<ScheduleEntry> entries = schedule.entries;
|
||||
int y = (int) (pMouseY - topPos - 25 + scroll.getValue());
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
ScheduleEntry entry = entries.get(i);
|
||||
int maxRows = 0;
|
||||
for (List<ScheduleWaitCondition> list : entry.conditions)
|
||||
maxRows = Math.max(maxRows, list.size());
|
||||
int cardHeight = CARD_HEADER + 24 + maxRows * 18;
|
||||
|
||||
if (y >= cardHeight) {
|
||||
y -= cardHeight + 9;
|
||||
if (y < 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isConditionAreaScrollable(entry))
|
||||
break;
|
||||
if (y < 24)
|
||||
break;
|
||||
if (pMouseX < leftPos + 25)
|
||||
break;
|
||||
if (pMouseX > leftPos + 205)
|
||||
break;
|
||||
float chaseTarget = horizontalScrolls.get(i)
|
||||
.getChaseTarget();
|
||||
if (pDelta > 0 && !Mth.equal(chaseTarget, 0)) {
|
||||
horizontalScrolls.get(i)
|
||||
.chase(chaseTarget - 1, 0.5f, Chaser.EXP);
|
||||
return true;
|
||||
}
|
||||
if (pDelta < 0 && !Mth.equal(chaseTarget, entry.conditions.size() - 1)) {
|
||||
horizontalScrolls.get(i)
|
||||
.chase(chaseTarget + 1, 0.5f, Chaser.EXP);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
float chaseTarget = scroll.getChaseTarget();
|
||||
float max = 40 - 173;
|
||||
for (ScheduleEntry scheduleEntry : schedule.entries) {
|
||||
int maxRows = 0;
|
||||
for (List<ScheduleWaitCondition> list : scheduleEntry.conditions)
|
||||
maxRows = Math.max(maxRows, list.size());
|
||||
max += CARD_HEADER + 24 + maxRows * 18 + 10;
|
||||
}
|
||||
if (max > 0) {
|
||||
chaseTarget -= pDelta * 12;
|
||||
chaseTarget = Mth.clamp(chaseTarget, 0, max);
|
||||
scroll.chase((int) chaseTarget, 0.7f, Chaser.EXP);
|
||||
} else
|
||||
scroll.chase(0, 0.7f, Chaser.EXP);
|
||||
|
||||
return super.mouseScrolled(pMouseX, pMouseY, pDelta);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderForeground(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) {
|
||||
super.renderForeground(matrixStack, mouseX, mouseY, partialTicks);
|
||||
GuiGameElement.of(menu.contentHolder).<GuiGameElement
|
||||
.GuiRenderBuilder>at(leftPos + 251, topPos + 187, -200)
|
||||
.scale(3)
|
||||
.render(matrixStack);
|
||||
action(matrixStack, mouseX, mouseY, -1);
|
||||
|
||||
if (editingCondition == null && editingDestination == null)
|
||||
return;
|
||||
int x = leftPos + 53;
|
||||
int y = topPos + 87;
|
||||
if (mouseX < x || mouseY < y || mouseX >= x + 18 || mouseY >= y + 18)
|
||||
return;
|
||||
IScheduleInput rendered = editingCondition == null ? editingDestination : editingCondition;
|
||||
List<Component> secondLineTooltip = rendered.getSecondLineTooltip();
|
||||
if (secondLineTooltip == null || (hoveredSlot != null && !hoveredSlot.getItem()
|
||||
.isEmpty()))
|
||||
return;
|
||||
renderTooltip(matrixStack, secondLineTooltip, Optional.empty(), mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg(PoseStack pPoseStack, float pPartialTick, int pMouseX, int pMouseY) {
|
||||
AllGuiTextures.SCHEDULE.render(pPoseStack, leftPos, topPos);
|
||||
FormattedCharSequence formattedcharsequence = title.getVisualOrderText();
|
||||
int center = leftPos + (AllGuiTextures.SCHEDULE.width - 8) / 2;
|
||||
font.draw(pPoseStack, formattedcharsequence, (float) (center - font.width(formattedcharsequence) / 2),
|
||||
(float) topPos + 4, 0x505050);
|
||||
renderSchedule(pPoseStack, pMouseX, pMouseY, pPartialTick);
|
||||
|
||||
if (editingCondition == null && editingDestination == null)
|
||||
return;
|
||||
|
||||
this.fillGradient(pPoseStack, 0, 0, this.width, this.height, -1072689136, -804253680);
|
||||
AllGuiTextures.SCHEDULE_EDITOR.render(pPoseStack, leftPos - 2, topPos + 40);
|
||||
AllGuiTextures.PLAYER_INVENTORY.render(pPoseStack, leftPos + 38, topPos + 122);
|
||||
font.draw(pPoseStack, playerInventoryTitle, leftPos + 46, topPos + 128, 0x505050);
|
||||
|
||||
formattedcharsequence = editingCondition == null ? Lang.translate("schedule.destination.editor")
|
||||
.getVisualOrderText()
|
||||
: Lang.translate("schedule.condition.editor")
|
||||
.getVisualOrderText();
|
||||
font.draw(pPoseStack, formattedcharsequence, (float) (center - font.width(formattedcharsequence) / 2),
|
||||
(float) topPos + 44, 0x505050);
|
||||
|
||||
IScheduleInput rendered = editingCondition == null ? editingDestination : editingCondition;
|
||||
if (!rendered.needsSlot() && !rendered.renderSpecialIcon(pPoseStack, leftPos + 54, topPos + 88)) {
|
||||
Pair<ItemStack, Component> summary = rendered.getSummary();
|
||||
ItemStack icon = summary.getFirst();
|
||||
if (icon.isEmpty())
|
||||
icon = rendered.getSecondLineIcon();
|
||||
if (icon.isEmpty())
|
||||
AllGuiTextures.SCHEDULE_EDITOR_INACTIVE_SLOT.render(pPoseStack, leftPos + 53, topPos + 87);
|
||||
else
|
||||
GuiGameElement.of(icon)
|
||||
.at(leftPos + 54, topPos + 88)
|
||||
.render(pPoseStack);
|
||||
}
|
||||
|
||||
if (editorDividers == null)
|
||||
return;
|
||||
|
||||
AllGuiTextures.SCHEDULE_EDITOR_SECOND_LINE.render(pPoseStack, leftPos + 74, topPos + 87);
|
||||
for (Integer integer : editorDividers)
|
||||
AllGuiTextures.SCHEDULE_EDITOR_DIVIDER.render(pPoseStack, leftPos + 74 + integer, topPos + 87);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed() {
|
||||
super.removed();
|
||||
AllPackets.channel.sendToServer(new ScheduleEditPacket(schedule));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Rect2i> getExtraAreas() {
|
||||
return extraAreas;
|
||||
}
|
||||
|
||||
public Font getFont() {
|
||||
return font;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.AllShapes;
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.foundation.block.ITE;
|
||||
import com.simibubi.create.foundation.gui.ScreenOpener;
|
||||
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
|
||||
public class StationBlock extends HorizontalDirectionalBlock implements ITE<StationTileEntity> {
|
||||
|
||||
public static final BooleanProperty ASSEMBLING = BooleanProperty.create("assembling");
|
||||
|
||||
public StationBlock(Properties p_54120_) {
|
||||
super(p_54120_);
|
||||
registerDefaultState(defaultBlockState().setValue(ASSEMBLING, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(Builder<Block, BlockState> pBuilder) {
|
||||
super.createBlockStateDefinition(pBuilder.add(FACING, ASSEMBLING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillItemCategory(CreativeModeTab pTab, NonNullList<ItemStack> pItems) {
|
||||
super.fillItemCategory(pTab, pItems);
|
||||
pItems.add(AllItems.SCHEDULE.asStack());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand,
|
||||
BlockHitResult pHit) {
|
||||
|
||||
if (pPlayer == null)
|
||||
return InteractionResult.PASS;
|
||||
ItemStack itemInHand = pPlayer.getItemInHand(pHand);
|
||||
if (AllItems.WRENCH.isIn(itemInHand))
|
||||
return InteractionResult.PASS;
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
|
||||
() -> () -> withTileEntityDo(pLevel, pPos, te -> this.displayScreen(te, pPlayer)));
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@OnlyIn(value = Dist.CLIENT)
|
||||
protected void displayScreen(StationTileEntity te, Player player) {
|
||||
if (!(player instanceof LocalPlayer))
|
||||
return;
|
||||
GlobalStation station = te.getOrCreateGlobalStation();
|
||||
if (station == null)
|
||||
return;
|
||||
BlockState blockState = te.getBlockState();
|
||||
boolean assembling = blockState.getBlock() == this && blockState.getValue(ASSEMBLING);
|
||||
ScreenOpener.open(assembling ? new AssemblyScreen(te, station) : new StationScreen(te, station));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
return super.getStateForPlacement(pContext).setValue(FACING, pContext.getHorizontalDirection());
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
|
||||
return AllShapes.STATION.get(pState.getValue(FACING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<StationTileEntity> getTileEntityClass() {
|
||||
return StationTileEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends StationTileEntity> getTileEntityType() {
|
||||
return AllTileEntities.TRACK_STATION.get();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||
import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class StationEditPacket extends TileEntityConfigurationPacket<StationTileEntity> {
|
||||
|
||||
boolean assemblyMode;
|
||||
Boolean tryAssemble;
|
||||
String name;
|
||||
|
||||
public static StationEditPacket tryAssemble(BlockPos pos) {
|
||||
StationEditPacket packet = new StationEditPacket(pos);
|
||||
packet.tryAssemble = true;
|
||||
return packet;
|
||||
}
|
||||
|
||||
public static StationEditPacket tryDisassemble(BlockPos pos) {
|
||||
StationEditPacket packet = new StationEditPacket(pos);
|
||||
packet.tryAssemble = false;
|
||||
return packet;
|
||||
}
|
||||
|
||||
public static StationEditPacket configure(BlockPos pos, boolean assemble, String name) {
|
||||
StationEditPacket packet = new StationEditPacket(pos);
|
||||
packet.assemblyMode = assemble;
|
||||
packet.tryAssemble = null;
|
||||
packet.name = name;
|
||||
return packet;
|
||||
}
|
||||
|
||||
public StationEditPacket(FriendlyByteBuf buffer) {
|
||||
super(buffer);
|
||||
}
|
||||
|
||||
public StationEditPacket(BlockPos pos) {
|
||||
super(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeSettings(FriendlyByteBuf buffer) {
|
||||
buffer.writeBoolean(tryAssemble != null);
|
||||
if (tryAssemble != null) {
|
||||
buffer.writeBoolean(tryAssemble);
|
||||
return;
|
||||
}
|
||||
buffer.writeBoolean(assemblyMode);
|
||||
buffer.writeUtf(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readSettings(FriendlyByteBuf buffer) {
|
||||
name = "";
|
||||
if (buffer.readBoolean()) {
|
||||
tryAssemble = buffer.readBoolean();
|
||||
return;
|
||||
}
|
||||
assemblyMode = buffer.readBoolean();
|
||||
name = buffer.readUtf(256);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applySettings(StationTileEntity te) {
|
||||
Level level = te.getLevel();
|
||||
BlockPos blockPos = te.getBlockPos();
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
|
||||
if (!name.isBlank()) {
|
||||
GlobalStation station = te.getOrCreateGlobalStation();
|
||||
if (station != null)
|
||||
station.name = name;
|
||||
Create.RAILWAYS.markTracksDirty();
|
||||
}
|
||||
|
||||
if (!(blockState.getBlock() instanceof StationBlock))
|
||||
return;
|
||||
Boolean isAssemblyMode = blockState.getValue(StationBlock.ASSEMBLING);
|
||||
if (tryAssemble != null) {
|
||||
if (!isAssemblyMode)
|
||||
return;
|
||||
if (tryAssemble)
|
||||
te.assemble();
|
||||
else {
|
||||
if (disassembleAndEnterMode(te))
|
||||
te.refreshAssemblyInfo();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (isAssemblyMode == assemblyMode)
|
||||
return;
|
||||
|
||||
BlockState newState = blockState.cycle(StationBlock.ASSEMBLING);
|
||||
Boolean nowAssembling = newState.getValue(StationBlock.ASSEMBLING);
|
||||
if (nowAssembling) {
|
||||
if (!disassembleAndEnterMode(te))
|
||||
return;
|
||||
} else {
|
||||
te.cancelAssembly();
|
||||
}
|
||||
|
||||
level.setBlock(blockPos, newState, 3);
|
||||
te.refreshBlockState();
|
||||
|
||||
if (nowAssembling)
|
||||
te.refreshAssemblyInfo();
|
||||
}
|
||||
|
||||
private boolean disassembleAndEnterMode(StationTileEntity te) {
|
||||
GlobalStation station = te.getOrCreateGlobalStation();
|
||||
if (station != null) {
|
||||
Train train = station.getPresentTrain();
|
||||
if (train != null && !train.disassemble(te.getAssemblyDirection(), te.getTarget()
|
||||
.getGlobalPosition()
|
||||
.above()))
|
||||
return false;
|
||||
}
|
||||
return te.tryEnterAssemblyMode();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import com.jozufozu.flywheel.core.PartialModel;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.simibubi.create.content.logistics.trains.ITrackBlock;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
||||
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class StationRenderer extends SafeTileEntityRenderer<StationTileEntity> {
|
||||
|
||||
public StationRenderer(BlockEntityRendererProvider.Context context) {}
|
||||
|
||||
@Override
|
||||
protected void renderSafe(StationTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer,
|
||||
int light, int overlay) {
|
||||
|
||||
BlockPos pos = te.getBlockPos();
|
||||
TrackTargetingBehaviour target = te.getTarget();
|
||||
BlockPos targetPosition = target.getGlobalPosition();
|
||||
Level level = te.getLevel();
|
||||
|
||||
BlockState trackState = level.getBlockState(targetPosition);
|
||||
Block block = trackState.getBlock();
|
||||
if (!(block instanceof ITrackBlock))
|
||||
return;
|
||||
|
||||
GlobalStation station = te.getOrCreateGlobalStation();
|
||||
|
||||
if (!te.getBlockState()
|
||||
.getValue(StationBlock.ASSEMBLING) || station == null || station.getPresentTrain() != null) {
|
||||
ms.pushPose();
|
||||
ms.translate(-pos.getX(), -pos.getY(), -pos.getZ());
|
||||
TrackTargetingBehaviour.render(level, targetPosition, target.getTargetDirection(), 0xCC993B, ms, buffer,
|
||||
light, overlay);
|
||||
ms.popPose();
|
||||
return;
|
||||
}
|
||||
|
||||
ITrackBlock track = (ITrackBlock) block;
|
||||
Direction direction = te.assemblyDirection;
|
||||
|
||||
if (direction == null || te.assemblyLength == 0 || te.bogeyLocations == null)
|
||||
return;
|
||||
|
||||
ms.pushPose();
|
||||
BlockPos offset = targetPosition.subtract(pos);
|
||||
ms.translate(offset.getX(), offset.getY(), offset.getZ());
|
||||
|
||||
MutableBlockPos currentPos = targetPosition.mutable();
|
||||
|
||||
PartialModel assemblyOverlay = track.prepareAssemblyOverlay(level, targetPosition, trackState, direction, ms);
|
||||
int colorWhenValid = 0x7092F2;
|
||||
int colorWhenCarriage = 0x70EF70;
|
||||
VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped());
|
||||
|
||||
currentPos.move(direction, 1);
|
||||
ms.translate(0, 0, 1);
|
||||
|
||||
for (int i = 0; i < te.assemblyLength; i++) {
|
||||
int valid = te.isValidBogeyOffset(i) ? colorWhenValid : -1;
|
||||
|
||||
for (int j : te.bogeyLocations)
|
||||
if (i == j) {
|
||||
valid = colorWhenCarriage;
|
||||
break;
|
||||
}
|
||||
|
||||
if (valid != -1) {
|
||||
int lightColor = LevelRenderer.getLightColor(level, currentPos);
|
||||
SuperByteBuffer sbb = CachedBufferer.partial(assemblyOverlay, trackState);
|
||||
sbb.color(valid);
|
||||
sbb.light(lightColor);
|
||||
sbb.renderInto(ms, vb);
|
||||
}
|
||||
ms.translate(0, 0, 1);
|
||||
currentPos.move(direction);
|
||||
}
|
||||
|
||||
ms.popPose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRenderOffScreen(StationTileEntity pBlockEntity) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewDistance() {
|
||||
return 96;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,309 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Carriage;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||
import com.simibubi.create.content.logistics.trains.entity.TrainIconType;
|
||||
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
import com.simibubi.create.foundation.gui.UIRenderHelper;
|
||||
import com.simibubi.create.foundation.gui.widget.IconButton;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.util.Mth;
|
||||
|
||||
public class StationScreen extends AbstractStationScreen {
|
||||
|
||||
private EditBox nameBox;
|
||||
private EditBox trainNameBox;
|
||||
private IconButton newTrainButton;
|
||||
private IconButton disassembleTrainButton;
|
||||
private IconButton openScheduleButton;
|
||||
|
||||
private int leavingAnimation;
|
||||
private LerpedFloat trainPosition;
|
||||
|
||||
private boolean switchingToAssemblyMode;
|
||||
|
||||
public StationScreen(StationTileEntity te, GlobalStation station) {
|
||||
super(te, station);
|
||||
background = AllGuiTextures.STATION;
|
||||
leavingAnimation = 0;
|
||||
trainPosition = LerpedFloat.linear()
|
||||
.startWithValue(0);
|
||||
switchingToAssemblyMode = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
int x = guiLeft;
|
||||
int y = guiTop;
|
||||
|
||||
Consumer<String> onTextChanged;
|
||||
|
||||
onTextChanged = s -> nameBox.x = nameBoxX(s, nameBox);
|
||||
nameBox = new EditBox(new NoShadowFontWrapper(font), x + 23, y + 4, background.width - 20, 10,
|
||||
new TextComponent(station.name));
|
||||
nameBox.setBordered(false);
|
||||
nameBox.setMaxLength(25);
|
||||
nameBox.setTextColor(0x442000);
|
||||
nameBox.setValue(station.name);
|
||||
nameBox.changeFocus(false);
|
||||
nameBox.mouseClicked(0, 0, 0);
|
||||
nameBox.setResponder(onTextChanged);
|
||||
nameBox.x = nameBoxX(nameBox.getValue(), nameBox);
|
||||
addRenderableWidget(nameBox);
|
||||
|
||||
Runnable assemblyCallback = () -> {
|
||||
switchingToAssemblyMode = true;
|
||||
minecraft.setScreen(new AssemblyScreen(te, station));
|
||||
};
|
||||
|
||||
newTrainButton = new WideIconButton(x + 84, y + 65, AllGuiTextures.I_NEW_TRAIN);
|
||||
newTrainButton.setToolTip(new TextComponent("New Train"));
|
||||
newTrainButton.withCallback(assemblyCallback);
|
||||
addRenderableWidget(newTrainButton);
|
||||
|
||||
disassembleTrainButton = new WideIconButton(x + 94, y + 65, AllGuiTextures.I_DISASSEMBLE_TRAIN);
|
||||
disassembleTrainButton.active = false;
|
||||
disassembleTrainButton.visible = false;
|
||||
disassembleTrainButton.withCallback(assemblyCallback);
|
||||
addRenderableWidget(disassembleTrainButton);
|
||||
|
||||
openScheduleButton = new IconButton(x + 73, y + 65, AllIcons.I_VIEW_SCHEDULE);
|
||||
openScheduleButton.active = false;
|
||||
openScheduleButton.visible = false;
|
||||
addRenderableWidget(openScheduleButton);
|
||||
|
||||
onTextChanged = s -> trainNameBox.x = nameBoxX(s, trainNameBox);
|
||||
trainNameBox = new EditBox(font, x + 23, y + 47, background.width - 20, 10, new TextComponent(""));
|
||||
trainNameBox.setBordered(false);
|
||||
trainNameBox.setMaxLength(15);
|
||||
trainNameBox.setTextColor(0xC6C6C6);
|
||||
trainNameBox.changeFocus(false);
|
||||
trainNameBox.mouseClicked(0, 0, 0);
|
||||
trainNameBox.setResponder(onTextChanged);
|
||||
trainNameBox.active = false;
|
||||
|
||||
tickTrainDisplay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
tickTrainDisplay();
|
||||
if (getFocused() != nameBox) {
|
||||
nameBox.setCursorPosition(nameBox.getValue()
|
||||
.length());
|
||||
nameBox.setHighlightPos(nameBox.getCursorPosition());
|
||||
}
|
||||
if (getFocused() != trainNameBox || trainNameBox.active == false) {
|
||||
trainNameBox.setCursorPosition(trainNameBox.getValue()
|
||||
.length());
|
||||
trainNameBox.setHighlightPos(trainNameBox.getCursorPosition());
|
||||
}
|
||||
super.tick();
|
||||
}
|
||||
|
||||
private void tickTrainDisplay() {
|
||||
Train train = displayedTrain.get();
|
||||
|
||||
if (train == null) {
|
||||
if (trainNameBox.active) {
|
||||
trainNameBox.active = false;
|
||||
removeWidget(trainNameBox);
|
||||
}
|
||||
|
||||
leavingAnimation = 0;
|
||||
newTrainButton.active = true;
|
||||
newTrainButton.visible = true;
|
||||
Train imminentTrain = station.getImminentTrain();
|
||||
|
||||
if (imminentTrain != null) {
|
||||
displayedTrain = new WeakReference<>(imminentTrain);
|
||||
newTrainButton.active = false;
|
||||
newTrainButton.visible = false;
|
||||
disassembleTrainButton.active = false;
|
||||
disassembleTrainButton.visible = true;
|
||||
openScheduleButton.active = false;
|
||||
openScheduleButton.visible = true;
|
||||
|
||||
trainNameBox.active = true;
|
||||
trainNameBox.setValue(imminentTrain.name.getString());
|
||||
trainNameBox.x = nameBoxX(trainNameBox.getValue(), trainNameBox);
|
||||
addRenderableWidget(trainNameBox);
|
||||
|
||||
int trainIconWidth = getTrainIconWidth(imminentTrain);
|
||||
int targetPos = background.width / 2 - trainIconWidth / 2;
|
||||
float f = (float) (imminentTrain.navigation.distanceToDestination / 15f);
|
||||
trainPosition.startWithValue(targetPos - (targetPos + 5) * f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int trainIconWidth = getTrainIconWidth(train);
|
||||
int targetPos = background.width / 2 - trainIconWidth / 2;
|
||||
|
||||
if (leavingAnimation > 0) {
|
||||
disassembleTrainButton.active = false;
|
||||
float f = 1 - (leavingAnimation / 80f);
|
||||
trainPosition.setValue(targetPos + f * f * f * (background.width - targetPos + 5));
|
||||
leavingAnimation--;
|
||||
if (leavingAnimation > 0)
|
||||
return;
|
||||
|
||||
displayedTrain = new WeakReference<>(null);
|
||||
disassembleTrainButton.visible = false;
|
||||
openScheduleButton.active = false;
|
||||
openScheduleButton.visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (train.navigation.destination != station && train.currentStation != station) {
|
||||
leavingAnimation = 80;
|
||||
return;
|
||||
}
|
||||
|
||||
disassembleTrainButton.active = train.currentStation == station; // TODO te.canAssemble
|
||||
openScheduleButton.active = train.runtime.schedule != null;
|
||||
|
||||
float f = (float) (train.navigation.distanceToDestination / 30f);
|
||||
trainPosition.setValue(targetPos - (targetPos + trainIconWidth) * f);
|
||||
}
|
||||
|
||||
private int nameBoxX(String s, EditBox nameBox) {
|
||||
return guiLeft + background.width / 2 - (Math.min(font.width(s), nameBox.getWidth()) + 10) / 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||
super.renderWindow(ms, mouseX, mouseY, partialTicks);
|
||||
int x = guiLeft;
|
||||
int y = guiTop;
|
||||
|
||||
String text = nameBox.getValue();
|
||||
|
||||
if (!nameBox.isFocused())
|
||||
AllGuiTextures.STATION_EDIT_NAME.render(ms, nameBoxX(text, nameBox) + font.width(text) + 5, y + 1);
|
||||
|
||||
Train train = displayedTrain.get();
|
||||
if (train == null) {
|
||||
TextComponent header = new TextComponent("Station is Idle");
|
||||
font.draw(ms, header, x + 97 - font.width(header) / 2, y + 47, 0x7A7A7A);
|
||||
return;
|
||||
}
|
||||
|
||||
float position = trainPosition.getValue(partialTicks);
|
||||
|
||||
ms.pushPose();
|
||||
RenderSystem.enableBlend();
|
||||
ms.translate(position, 0, 0);
|
||||
TrainIconType icon = train.icon;
|
||||
int offset = 0;
|
||||
|
||||
List<Carriage> carriages = train.carriages;
|
||||
for (int i = carriages.size() - 1; i > 0; i--) {
|
||||
RenderSystem.setShaderColor(1, 1, 1, Math.min(1f,
|
||||
Math.min((position + offset - 10) / 30f, (background.width - 40 - position - offset) / 30f)));
|
||||
|
||||
if (i == carriages.size() - 1 && train.doubleEnded) {
|
||||
offset += icon.render(TrainIconType.FLIPPED_ENGINE, ms, x + offset, y + 20) + 1;
|
||||
continue;
|
||||
}
|
||||
Carriage carriage = carriages.get(i);
|
||||
offset += icon.render(carriage.bogeySpacing, ms, x + offset, y + 20) + 1;
|
||||
}
|
||||
|
||||
RenderSystem.setShaderColor(1, 1, 1,
|
||||
Math.min(1f, Math.min((position + offset - 10) / 30f, (background.width - 40 - position - offset) / 30f)));
|
||||
offset += icon.render(TrainIconType.ENGINE, ms, x + offset, y + 20);
|
||||
RenderSystem.disableBlend();
|
||||
ms.popPose();
|
||||
|
||||
RenderSystem.setShaderColor(1, 1, 1, 1);
|
||||
|
||||
UIRenderHelper.drawStretched(ms, x + 21, y + 43, 150, 46, -100, AllGuiTextures.STATION_TEXTBOX_MIDDLE);
|
||||
AllGuiTextures.STATION_TEXTBOX_TOP.render(ms, x + 21, y + 42);
|
||||
AllGuiTextures.STATION_TEXTBOX_BOTTOM.render(ms, x + 21, y + 86);
|
||||
|
||||
ms.pushPose();
|
||||
ms.translate(Mth.clamp(position + offset - 13, 25, 159), 0, 0);
|
||||
AllGuiTextures.STATION_TEXTBOX_SPEECH.render(ms, x, y + 38);
|
||||
ms.popPose();
|
||||
|
||||
text = trainNameBox.getValue();
|
||||
if (!trainNameBox.isFocused())
|
||||
AllGuiTextures.STATION_EDIT_TRAIN_NAME.render(ms, nameBoxX(text, trainNameBox) + font.width(text) + 5,
|
||||
y + 44);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) {
|
||||
if (!nameBox.isFocused() && pMouseY > guiTop && pMouseY < guiTop + 14 && pMouseX > guiLeft
|
||||
&& pMouseX < guiLeft + background.width) {
|
||||
nameBox.setFocus(true);
|
||||
nameBox.setHighlightPos(0);
|
||||
setFocused(nameBox);
|
||||
return true;
|
||||
}
|
||||
if (trainNameBox.active && !trainNameBox.isFocused() && pMouseY > guiTop + 45 && pMouseY < guiTop + 58
|
||||
&& pMouseX > guiLeft + 25 && pMouseX < guiLeft + 168) {
|
||||
trainNameBox.setFocus(true);
|
||||
trainNameBox.setHighlightPos(0);
|
||||
setFocused(trainNameBox);
|
||||
return true;
|
||||
}
|
||||
return super.mouseClicked(pMouseX, pMouseY, pButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) {
|
||||
boolean hitEnter = getFocused() instanceof EditBox && (pKeyCode == 257 || pKeyCode == 335);
|
||||
|
||||
if (hitEnter && nameBox.isFocused()) {
|
||||
nameBox.setFocus(false);
|
||||
syncStationName();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hitEnter && trainNameBox.isFocused()) {
|
||||
trainNameBox.setFocus(false);
|
||||
syncTrainName();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.keyPressed(pKeyCode, pScanCode, pModifiers);
|
||||
}
|
||||
|
||||
private void syncTrainName() {
|
||||
Train train = displayedTrain.get();
|
||||
if (train != null && !trainNameBox.getValue()
|
||||
.equals(train.name.getString()))
|
||||
AllPackets.channel.sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId()));
|
||||
}
|
||||
|
||||
private void syncStationName() {
|
||||
if (!nameBox.getValue()
|
||||
.equals(station.name))
|
||||
AllPackets.channel.sendToServer(StationEditPacket.configure(te.getBlockPos(), false, nameBox.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed() {
|
||||
super.removed();
|
||||
AllPackets.channel
|
||||
.sendToServer(StationEditPacket.configure(te.getBlockPos(), switchingToAssemblyMode, nameBox.getValue()));
|
||||
Train train = displayedTrain.get();
|
||||
if (!switchingToAssemblyMode && train != null)
|
||||
AllPackets.channel.sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId()));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,495 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
|
||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
||||
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.TrackNode;
|
||||
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
|
||||
import com.simibubi.create.content.logistics.trains.TrackPropagator;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Carriage;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Carriage.CarriageBogey;
|
||||
import com.simibubi.create.content.logistics.trains.entity.CarriageContraption;
|
||||
import com.simibubi.create.content.logistics.trains.entity.MovingPoint;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBehaviour.GraphLocation;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
import com.simibubi.create.foundation.utility.WorldAttached;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.core.Direction.AxisDirection;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class StationTileEntity extends SmartTileEntity implements IDisplayAssemblyExceptions {
|
||||
|
||||
UUID id;
|
||||
|
||||
protected int failedCarriageIndex;
|
||||
protected AssemblyException lastException;
|
||||
|
||||
public StationTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
setLazyTickRate(20);
|
||||
id = UUID.randomUUID();
|
||||
lastException = null;
|
||||
failedCarriageIndex = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
||||
behaviours.add(new TrackTargetingBehaviour(this));
|
||||
}
|
||||
|
||||
public TrackTargetingBehaviour getTarget() {
|
||||
return getBehaviour(TrackTargetingBehaviour.TYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
if (!level.isClientSide)
|
||||
getOrCreateGlobalStation();
|
||||
super.initialize();
|
||||
}
|
||||
|
||||
public GlobalStation getOrCreateGlobalStation() {
|
||||
for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values()) {
|
||||
GlobalStation station = trackGraph.getStation(id);
|
||||
if (station == null)
|
||||
continue;
|
||||
return station;
|
||||
}
|
||||
|
||||
GraphLocation loc = getTarget().determineGraphLocation();
|
||||
if (loc == null)
|
||||
return null;
|
||||
|
||||
GlobalStation globalStation = new GlobalStation(id, loc.edge, loc.position, worldPosition);
|
||||
loc.graph.addStation(globalStation);
|
||||
return globalStation;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag tag, boolean clientPacket) {
|
||||
id = tag.getUUID("Id");
|
||||
lastException = AssemblyException.read(tag);
|
||||
failedCarriageIndex = tag.getInt("FailedCarriageIndex");
|
||||
super.read(tag, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(CompoundTag tag, boolean clientPacket) {
|
||||
tag.putUUID("Id", id);
|
||||
AssemblyException.write(tag, lastException);
|
||||
tag.putInt("FailedCarriageIndex", failedCarriageIndex);
|
||||
super.write(tag, clientPacket);
|
||||
}
|
||||
|
||||
// Train Assembly
|
||||
|
||||
public static WorldAttached<Map<BlockPos, BoundingBox>> assemblyAreas = new WorldAttached<>(w -> new HashMap<>());
|
||||
|
||||
Direction assemblyDirection;
|
||||
int assemblyLength;
|
||||
int[] bogeyLocations;
|
||||
IBogeyBlock[] bogeyTypes;
|
||||
int bogeyCount;
|
||||
|
||||
@Override
|
||||
public void lazyTick() {
|
||||
if (isAssembling() && !level.isClientSide)
|
||||
refreshAssemblyInfo();
|
||||
super.lazyTick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (isAssembling() && level.isClientSide)
|
||||
refreshAssemblyInfo();
|
||||
super.tick();
|
||||
}
|
||||
|
||||
public void trackClicked(Player player, ITrackBlock track, BlockState state, BlockPos pos) {
|
||||
refreshAssemblyInfo();
|
||||
BoundingBox bb = assemblyAreas.get(level)
|
||||
.get(worldPosition);
|
||||
if (bb == null || !bb.isInside(pos))
|
||||
return;
|
||||
|
||||
int bogeyOffset = pos.distManhattan(getTarget().getGlobalPosition()) - 1;
|
||||
if (!isValidBogeyOffset(bogeyOffset))
|
||||
return;
|
||||
|
||||
Vec3 upNormal = track.getUpNormal(level, pos, state);
|
||||
BlockState bogeyAnchor = track.getBogeyAnchor(level, pos, state);
|
||||
level.setBlock(pos.offset(new BlockPos(upNormal)), bogeyAnchor, 3);
|
||||
}
|
||||
|
||||
public boolean isAssembling() {
|
||||
BlockState state = getBlockState();
|
||||
return state.hasProperty(StationBlock.ASSEMBLING) && state.getValue(StationBlock.ASSEMBLING);
|
||||
}
|
||||
|
||||
public boolean tryEnterAssemblyMode() {
|
||||
TrackTargetingBehaviour target = getTarget();
|
||||
if (!target.hasValidTrack())
|
||||
return false;
|
||||
|
||||
BlockPos targetPosition = target.getGlobalPosition();
|
||||
BlockState trackState = target.getTrackBlockState();
|
||||
ITrackBlock track = target.getTrack();
|
||||
Vec3 trackAxis = track.getTrackAxis(level, targetPosition, trackState);
|
||||
|
||||
boolean axisFound = false;
|
||||
for (Axis axis : Iterate.axes) {
|
||||
if (trackAxis.get(axis) == 0)
|
||||
continue;
|
||||
if (axisFound)
|
||||
return false;
|
||||
axisFound = true;
|
||||
}
|
||||
|
||||
Create.RAILWAYS.trains.clear();
|
||||
Create.RAILWAYS.carriageById.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void refreshAssemblyInfo() {
|
||||
TrackTargetingBehaviour target = getTarget();
|
||||
if (!target.hasValidTrack())
|
||||
return;
|
||||
|
||||
GlobalStation station = getOrCreateGlobalStation();
|
||||
if (station == null || station.getPresentTrain() != null)
|
||||
return;
|
||||
|
||||
int prevLength = assemblyLength;
|
||||
BlockPos targetPosition = target.getGlobalPosition();
|
||||
BlockState trackState = target.getTrackBlockState();
|
||||
ITrackBlock track = target.getTrack();
|
||||
getAssemblyDirection();
|
||||
|
||||
MutableBlockPos currentPos = targetPosition.mutable();
|
||||
currentPos.move(assemblyDirection);
|
||||
|
||||
BlockPos bogeyOffset = new BlockPos(track.getUpNormal(level, targetPosition, trackState));
|
||||
|
||||
int MAX_LENGTH = 48;
|
||||
int MAX_BOGEY_COUNT = 20;
|
||||
|
||||
int bogeyIndex = 0;
|
||||
int maxBogeyCount = MAX_BOGEY_COUNT;
|
||||
if (bogeyLocations == null)
|
||||
bogeyLocations = new int[maxBogeyCount];
|
||||
if (bogeyTypes == null)
|
||||
bogeyTypes = new IBogeyBlock[maxBogeyCount];
|
||||
Arrays.fill(bogeyLocations, -1);
|
||||
Arrays.fill(bogeyTypes, null);
|
||||
|
||||
for (int i = 0; i < MAX_LENGTH; i++) {
|
||||
if (i == MAX_LENGTH - 1 || !track.trackEquals(trackState, level.getBlockState(currentPos))) {
|
||||
assemblyLength = i;
|
||||
break;
|
||||
}
|
||||
|
||||
BlockState potentialBogeyState = level.getBlockState(bogeyOffset.offset(currentPos));
|
||||
if (potentialBogeyState.getBlock()instanceof IBogeyBlock bogey && bogeyIndex < bogeyLocations.length) {
|
||||
bogeyTypes[bogeyIndex] = bogey;
|
||||
bogeyLocations[bogeyIndex] = i;
|
||||
bogeyIndex++;
|
||||
}
|
||||
|
||||
currentPos.move(assemblyDirection);
|
||||
}
|
||||
|
||||
bogeyCount = bogeyIndex;
|
||||
|
||||
if (level.isClientSide)
|
||||
return;
|
||||
if (prevLength == assemblyLength)
|
||||
return;
|
||||
|
||||
Map<BlockPos, BoundingBox> map = assemblyAreas.get(level);
|
||||
BlockPos startPosition = targetPosition.relative(assemblyDirection);
|
||||
BlockPos trackEnd = startPosition.relative(assemblyDirection, assemblyLength - 1);
|
||||
map.put(worldPosition, BoundingBox.fromCorners(startPosition, trackEnd));
|
||||
}
|
||||
|
||||
public boolean isValidBogeyOffset(int i) {
|
||||
if ((i < 4 || bogeyCount == 0) && i != 0)
|
||||
return false;
|
||||
for (int j : bogeyLocations) {
|
||||
if (j == -1)
|
||||
break;
|
||||
if (i >= j - 3 && i <= j + 3)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Direction getAssemblyDirection() {
|
||||
if (assemblyDirection != null)
|
||||
return assemblyDirection;
|
||||
TrackTargetingBehaviour target = getTarget();
|
||||
if (!target.hasValidTrack())
|
||||
return null;
|
||||
BlockPos targetPosition = target.getGlobalPosition();
|
||||
BlockState trackState = target.getTrackBlockState();
|
||||
ITrackBlock track = target.getTrack();
|
||||
AxisDirection axisDirection = target.getTargetDirection();
|
||||
Vec3 axis = track.getTrackAxis(level, targetPosition, trackState)
|
||||
.normalize()
|
||||
.scale(axisDirection.getStep());
|
||||
return assemblyDirection = Direction.getNearest(axis.x, axis.y, axis.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setRemovedNotDueToChunkUnload() {
|
||||
assemblyAreas.get(level)
|
||||
.remove(worldPosition);
|
||||
for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values())
|
||||
trackGraph.removeStation(id);
|
||||
super.setRemovedNotDueToChunkUnload();
|
||||
}
|
||||
|
||||
public void assemble() {
|
||||
refreshAssemblyInfo();
|
||||
|
||||
if (bogeyLocations[0] != 0) {
|
||||
exception(new AssemblyException(new TextComponent("Frontmost Bogey must be at Station Marker")), -1);
|
||||
return;
|
||||
}
|
||||
|
||||
TrackTargetingBehaviour target = getTarget();
|
||||
if (!target.hasValidTrack())
|
||||
return;
|
||||
|
||||
BlockPos trackPosition = target.getGlobalPosition();
|
||||
BlockState trackState = target.getTrackBlockState();
|
||||
ITrackBlock track = target.getTrack();
|
||||
BlockPos bogeyOffset = new BlockPos(track.getUpNormal(level, trackPosition, trackState));
|
||||
|
||||
DiscoveredLocation location = null;
|
||||
List<Pair<BlockPos, DiscoveredLocation>> ends =
|
||||
TrackPropagator.getEnds(level, trackPosition, trackState, null, true);
|
||||
for (Pair<BlockPos, DiscoveredLocation> pair : ends)
|
||||
if (trackPosition.relative(assemblyDirection)
|
||||
.equals(pair.getFirst()))
|
||||
location = pair.getSecond();
|
||||
if (location == null)
|
||||
return;
|
||||
|
||||
List<Double> pointOffsets = new ArrayList<>();
|
||||
for (int i = 0; i < bogeyLocations.length; i++) {
|
||||
int loc = bogeyLocations[i];
|
||||
if (loc == -1)
|
||||
break;
|
||||
double bogeySize = bogeyTypes[i].getWheelPointSpacing();
|
||||
pointOffsets.add(Double.valueOf(loc + .5 - bogeySize / 2));
|
||||
pointOffsets.add(Double.valueOf(loc + .5 + bogeySize / 2));
|
||||
}
|
||||
|
||||
List<MovingPoint> points = new ArrayList<>();
|
||||
Vec3 directionVec = Vec3.atLowerCornerOf(assemblyDirection.getNormal());
|
||||
TrackGraph graph = null;
|
||||
TrackNode secondNode = null;
|
||||
|
||||
for (int i = 0; i < assemblyLength + 20; i++) {
|
||||
if (points.size() == pointOffsets.size())
|
||||
break;
|
||||
|
||||
DiscoveredLocation currentLocation = location;
|
||||
location = new DiscoveredLocation(location.getLocation()
|
||||
.add(directionVec));
|
||||
|
||||
if (graph == null)
|
||||
graph = Create.RAILWAYS.getGraph(level, currentLocation);
|
||||
if (graph == null)
|
||||
continue;
|
||||
TrackNode node = graph.locateNode(currentLocation);
|
||||
if (node == null)
|
||||
continue;
|
||||
|
||||
for (int pointIndex = points.size(); pointIndex < pointOffsets.size(); pointIndex++) {
|
||||
double offset = pointOffsets.get(pointIndex);
|
||||
if (offset > i)
|
||||
break;
|
||||
double positionOnEdge = i - offset;
|
||||
|
||||
Map<TrackNode, TrackEdge> connectionsFromNode = graph.getConnectionsFrom(node);
|
||||
|
||||
if (secondNode == null)
|
||||
for (Entry<TrackNode, TrackEdge> entry : connectionsFromNode.entrySet()) {
|
||||
TrackEdge edge = entry.getValue();
|
||||
TrackNode otherNode = entry.getKey();
|
||||
if (edge.isTurn())
|
||||
continue;
|
||||
Vec3 edgeDirection = edge.getDirection(node, otherNode, true);
|
||||
if (Mth.equal(edgeDirection.normalize()
|
||||
.dot(directionVec), -1d))
|
||||
secondNode = otherNode;
|
||||
}
|
||||
|
||||
if (secondNode == null) {
|
||||
Create.LOGGER.warn("Cannot assemble: No valid starting node found");
|
||||
return;
|
||||
}
|
||||
|
||||
TrackEdge edge = connectionsFromNode.get(secondNode);
|
||||
|
||||
if (edge == null) {
|
||||
Create.LOGGER.warn("Cannot assemble: Missing graph edge");
|
||||
return;
|
||||
}
|
||||
|
||||
points.add(new MovingPoint(graph, node, secondNode, edge, positionOnEdge));
|
||||
}
|
||||
|
||||
secondNode = node;
|
||||
}
|
||||
|
||||
if (points.size() != pointOffsets.size()) {
|
||||
Create.LOGGER.warn("Cannot assemble: Not all Points created");
|
||||
return;
|
||||
}
|
||||
|
||||
if (points.size() == 0) {
|
||||
exception(new AssemblyException(new TextComponent("No Bogeys Found")), -1);
|
||||
return;
|
||||
}
|
||||
|
||||
List<CarriageContraption> contraptions = new ArrayList<>();
|
||||
List<Carriage> carriages = new ArrayList<>();
|
||||
List<Integer> spacing = new ArrayList<>();
|
||||
|
||||
for (int bogeyIndex = 0; bogeyIndex < bogeyCount; bogeyIndex++) {
|
||||
int pointIndex = bogeyIndex * 2;
|
||||
if (bogeyIndex > 0)
|
||||
spacing.add(bogeyLocations[bogeyIndex] - bogeyLocations[bogeyIndex - 1]);
|
||||
CarriageContraption contraption = new CarriageContraption(assemblyDirection);
|
||||
BlockPos bogeyPosOffset = trackPosition.offset(bogeyOffset);
|
||||
|
||||
try {
|
||||
boolean success = contraption.assemble(level,
|
||||
bogeyPosOffset.relative(assemblyDirection, bogeyLocations[bogeyIndex] + 1));
|
||||
if (!success) {
|
||||
exception(new AssemblyException(new TextComponent("Nothing attached to Bogey " + bogeyIndex)), -1);
|
||||
return;
|
||||
}
|
||||
} catch (AssemblyException e) {
|
||||
exception(e, contraptions.size() + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
IBogeyBlock typeOfFirstBogey = bogeyTypes[bogeyIndex];
|
||||
CarriageBogey firstBogey =
|
||||
new CarriageBogey(typeOfFirstBogey, points.get(pointIndex), points.get(pointIndex + 1));
|
||||
CarriageBogey secondBogey = null;
|
||||
BlockPos secondBogeyPos = contraption.getSecondBogeyPos();
|
||||
int bogeySpacing = 0;
|
||||
|
||||
if (secondBogeyPos != null) {
|
||||
if (bogeyIndex == bogeyCount - 1 || !secondBogeyPos
|
||||
.equals(bogeyPosOffset.relative(assemblyDirection, bogeyLocations[bogeyIndex + 1] + 1))) {
|
||||
exception(new AssemblyException(new TextComponent("Bogeys are not connected in order")),
|
||||
contraptions.size() + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
bogeySpacing = bogeyLocations[bogeyIndex + 1] - bogeyLocations[bogeyIndex];
|
||||
secondBogey = new CarriageBogey(bogeyTypes[bogeyIndex + 1], points.get(pointIndex + 2),
|
||||
points.get(pointIndex + 3));
|
||||
bogeyIndex++;
|
||||
|
||||
} else if (!typeOfFirstBogey.allowsSingleBogeyCarriage()) {
|
||||
exception(
|
||||
new AssemblyException(new TextComponent("This bogey type cannot support a carriage on its own")),
|
||||
contraptions.size() + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
contraptions.add(contraption);
|
||||
Carriage carriage = new Carriage(firstBogey, secondBogey, bogeySpacing);
|
||||
carriage.setContraption(contraption);
|
||||
carriages.add(carriage);
|
||||
}
|
||||
|
||||
for (CarriageContraption contraption : contraptions) {
|
||||
contraption.removeBlocksFromWorld(level, BlockPos.ZERO);
|
||||
contraption.expandBoundsAroundAxis(Axis.Y);
|
||||
}
|
||||
|
||||
Create.RAILWAYS.carriageById.values()
|
||||
.forEach(Carriage::discardEntity);
|
||||
Create.RAILWAYS.carriageById.clear();
|
||||
|
||||
Train train = new Train(UUID.randomUUID(), graph, carriages, spacing);
|
||||
GlobalStation station = getOrCreateGlobalStation();
|
||||
train.currentStation = station;
|
||||
station.reserveFor(train);
|
||||
|
||||
Create.RAILWAYS.trains.put(train.id, train);
|
||||
clearException();
|
||||
}
|
||||
|
||||
public void cancelAssembly() {
|
||||
assemblyLength = 0;
|
||||
assemblyAreas.get(level)
|
||||
.remove(worldPosition);
|
||||
clearException();
|
||||
}
|
||||
|
||||
private void clearException() {
|
||||
exception(null, -1);
|
||||
}
|
||||
|
||||
private void exception(AssemblyException exception, int carriage) {
|
||||
failedCarriageIndex = carriage;
|
||||
lastException = exception;
|
||||
sendData();
|
||||
}
|
||||
|
||||
// Render
|
||||
|
||||
private AABB renderBounds = null;
|
||||
|
||||
@Override
|
||||
public AABB getRenderBoundingBox() {
|
||||
if (isAssembling())
|
||||
return INFINITE_EXTENT_AABB;
|
||||
if (renderBounds == null)
|
||||
renderBounds = new AABB(worldPosition, getTarget().getGlobalPosition());
|
||||
return renderBounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssemblyException getLastAssemblyException() {
|
||||
return lastException;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.logistics.trains.ITrackBlock;
|
||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||
import com.simibubi.create.content.logistics.trains.TrackNode;
|
||||
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
|
||||
import com.simibubi.create.content.logistics.trains.TrackPropagator;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
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.Pair;
|
||||
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
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.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public class TrackTargetingBehaviour extends TileEntityBehaviour {
|
||||
|
||||
public static final BehaviourType<TrackTargetingBehaviour> TYPE = new BehaviourType<>();
|
||||
|
||||
private BlockPos targetTrack;
|
||||
private AxisDirection targetDirection;
|
||||
|
||||
public TrackTargetingBehaviour(SmartTileEntity te) {
|
||||
super(te);
|
||||
targetDirection = AxisDirection.POSITIVE;
|
||||
targetTrack = BlockPos.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(CompoundTag nbt, boolean clientPacket) {
|
||||
nbt.put("TargetTrack", NbtUtils.writeBlockPos(targetTrack));
|
||||
nbt.putBoolean("TargetDirection", targetDirection == AxisDirection.POSITIVE);
|
||||
super.write(nbt, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundTag nbt, boolean clientPacket) {
|
||||
targetTrack = NbtUtils.readBlockPos(nbt.getCompound("TargetTrack"));
|
||||
targetDirection = nbt.getBoolean("TargetDirection") ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE;
|
||||
super.read(nbt, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BehaviourType<?> getType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
public boolean hasValidTrack() {
|
||||
return getTrackBlockState().getBlock() instanceof ITrackBlock;
|
||||
}
|
||||
|
||||
public ITrackBlock getTrack() {
|
||||
return (ITrackBlock) getTrackBlockState().getBlock();
|
||||
}
|
||||
|
||||
public BlockState getTrackBlockState() {
|
||||
return getWorld().getBlockState(getGlobalPosition());
|
||||
}
|
||||
|
||||
public BlockPos getGlobalPosition() {
|
||||
return targetTrack.offset(tileEntity.getBlockPos());
|
||||
}
|
||||
|
||||
public AxisDirection getTargetDirection() {
|
||||
return targetDirection;
|
||||
}
|
||||
|
||||
static class GraphLocation {
|
||||
public TrackGraph graph;
|
||||
public Couple<TrackNode> edge;
|
||||
public double position;
|
||||
}
|
||||
|
||||
public GraphLocation determineGraphLocation() {
|
||||
Level level = getWorld();
|
||||
BlockPos pos = getGlobalPosition();
|
||||
BlockState trackBlockState = getTrackBlockState();
|
||||
ITrackBlock track = getTrack();
|
||||
if (track == null)
|
||||
return null;
|
||||
|
||||
Vec3 axis = track.getTrackAxis(level, pos, trackBlockState)
|
||||
.normalize()
|
||||
.scale(getTargetDirection().getStep());
|
||||
|
||||
List<Pair<BlockPos, DiscoveredLocation>> ends =
|
||||
TrackPropagator.getEnds(level, pos, trackBlockState, null, true);
|
||||
|
||||
TrackGraph graph = null;
|
||||
TrackNode frontNode = null;
|
||||
TrackNode backNode = null;
|
||||
double position = 0;
|
||||
|
||||
for (Pair<BlockPos, DiscoveredLocation> pair : ends) {
|
||||
DiscoveredLocation current = pair.getSecond();
|
||||
BlockPos currentPos = pair.getFirst();
|
||||
Vec3 offset = Vec3.atLowerCornerOf(currentPos.subtract(pos));
|
||||
boolean forward = offset.distanceToSqr(axis.scale(-1)) < 1 / 4096f;
|
||||
boolean backwards = offset.distanceToSqr(axis) < 1 / 4096f;
|
||||
|
||||
if (!forward && !backwards)
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
DiscoveredLocation loc = current;
|
||||
List<Pair<BlockPos, DiscoveredLocation>> list =
|
||||
TrackPropagator.getEnds(level, currentPos, level.getBlockState(currentPos), current, true);
|
||||
if (!list.isEmpty()) {
|
||||
currentPos = list.get(0)
|
||||
.getFirst();
|
||||
current = list.get(0)
|
||||
.getSecond();
|
||||
}
|
||||
|
||||
if (graph == null)
|
||||
graph = Create.RAILWAYS.getGraph(level, loc);
|
||||
if (graph == null)
|
||||
continue;
|
||||
TrackNode node = graph.locateNode(loc);
|
||||
if (node == null)
|
||||
continue;
|
||||
if (forward)
|
||||
frontNode = node;
|
||||
if (backwards) {
|
||||
backNode = node;
|
||||
position = i + .5;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (frontNode == null || backNode == null)
|
||||
return null;
|
||||
|
||||
GraphLocation graphLocation = new GraphLocation();
|
||||
graphLocation.edge = Couple.create(backNode, frontNode);
|
||||
graphLocation.position = position;
|
||||
graphLocation.graph = graph;
|
||||
return graphLocation;
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static void render(LevelAccessor level, BlockPos pos, AxisDirection direction, int tintColor, PoseStack ms,
|
||||
MultiBufferSource buffer, int light, int overlay) {
|
||||
BlockState trackState = level.getBlockState(pos);
|
||||
Block block = trackState.getBlock();
|
||||
if (!(block instanceof ITrackBlock))
|
||||
return;
|
||||
|
||||
ms.pushPose();
|
||||
ms.translate(pos.getX(), pos.getY(), pos.getZ());
|
||||
|
||||
ITrackBlock track = (ITrackBlock) block;
|
||||
SuperByteBuffer sbb =
|
||||
CachedBufferer.partial(track.prepareStationOverlay(level, pos, trackState, direction, ms), trackState);
|
||||
sbb.color(tintColor);
|
||||
sbb.light(LevelRenderer.getLightColor(level, pos));
|
||||
sbb.renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped()));
|
||||
|
||||
ms.popPose();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.content.logistics.trains.ITrackBlock;
|
||||
import com.simibubi.create.foundation.render.SuperRenderTypeBuffer;
|
||||
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;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
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.state.BlockState;
|
||||
|
||||
public class TrackTargetingBlockItem extends BlockItem {
|
||||
|
||||
public TrackTargetingBlockItem(Block pBlock, Properties pProperties) {
|
||||
super(pBlock, pProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useOn(UseOnContext pContext) {
|
||||
ItemStack stack = pContext.getItemInHand();
|
||||
BlockPos pos = pContext.getClickedPos();
|
||||
Level level = pContext.getLevel();
|
||||
BlockState state = level.getBlockState(pos);
|
||||
Player player = pContext.getPlayer();
|
||||
|
||||
if (player == null)
|
||||
return InteractionResult.FAIL;
|
||||
|
||||
if (player.isSteppingCarefully() && stack.hasTag()) {
|
||||
if (level.isClientSide)
|
||||
return InteractionResult.SUCCESS;
|
||||
player.displayClientMessage(Lang.translate("track_target.clear"), true);
|
||||
stack.setTag(null);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
if (state.getBlock() instanceof ITrackBlock track) {
|
||||
if (level.isClientSide)
|
||||
return InteractionResult.SUCCESS;
|
||||
CompoundTag stackTag = stack.getOrCreateTag();
|
||||
boolean front = player.getLookAngle()
|
||||
.dot(track.getTrackAxis(level, pos, state)) < 0;
|
||||
stackTag.put("SelectedPos", NbtUtils.writeBlockPos(pos));
|
||||
stackTag.putBoolean("SelectedDirection", front);
|
||||
player.displayClientMessage(Lang.translate("track_target.set"), true);
|
||||
stack.setTag(stackTag);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
if (!stack.hasTag()) {
|
||||
player.displayClientMessage(Lang.translate("track_target.missing")
|
||||
.withStyle(ChatFormatting.RED), true);
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
CompoundTag tag = stack.getTag();
|
||||
CompoundTag teTag = new CompoundTag();
|
||||
teTag.putBoolean("TargetDirection", tag.getBoolean("SelectedDirection"));
|
||||
|
||||
BlockPos selectedPos = NbtUtils.readBlockPos(tag.getCompound("SelectedPos"));
|
||||
BlockPos placedPos = pos.relative(pContext.getClickedFace(), state.getMaterial()
|
||||
.isReplaceable() ? 0 : 1);
|
||||
|
||||
if (!selectedPos.closerThan(placedPos, 16)) {
|
||||
player.displayClientMessage(Lang.translate("track_target.too_far")
|
||||
.withStyle(ChatFormatting.RED), true);
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
teTag.put("TargetTrack", NbtUtils.writeBlockPos(selectedPos.subtract(placedPos)));
|
||||
tag.put("BlockEntityTag", teTag);
|
||||
|
||||
InteractionResult useOn = super.useOn(pContext);
|
||||
if (level.isClientSide || useOn == InteractionResult.FAIL)
|
||||
return useOn;
|
||||
|
||||
ItemStack itemInHand = player.getItemInHand(pContext.getHand());
|
||||
if (!itemInHand.isEmpty())
|
||||
itemInHand.setTag(null);
|
||||
player.displayClientMessage(Lang.translate("track_target.success")
|
||||
.withStyle(ChatFormatting.GREEN), true);
|
||||
return useOn;
|
||||
}
|
||||
|
||||
public static void clientTick() {
|
||||
|
||||
}
|
||||
|
||||
public static void render(PoseStack ms, SuperRenderTypeBuffer buffer) {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||
import com.simibubi.create.content.logistics.trains.entity.TrainIconType;
|
||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.network.NetworkEvent.Context;
|
||||
|
||||
public class TrainEditPacket extends SimplePacketBase {
|
||||
|
||||
private String name;
|
||||
private UUID id;
|
||||
private ResourceLocation iconType;
|
||||
|
||||
public TrainEditPacket(UUID id, String name, ResourceLocation iconType) {
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.iconType = iconType;
|
||||
}
|
||||
|
||||
public TrainEditPacket(FriendlyByteBuf buffer) {
|
||||
id = buffer.readUUID();
|
||||
name = buffer.readUtf(256);
|
||||
iconType = buffer.readResourceLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeUUID(id);
|
||||
buffer.writeUtf(name);
|
||||
buffer.writeResourceLocation(iconType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Supplier<Context> context) {
|
||||
context.get()
|
||||
.enqueueWork(() -> {
|
||||
Train train = Create.RAILWAYS.trains.get(id);
|
||||
if (train == null)
|
||||
return;
|
||||
if (!name.isBlank())
|
||||
train.name = new TextComponent(name);
|
||||
train.icon = TrainIconType.byId(iconType);
|
||||
});
|
||||
context.get()
|
||||
.setPacketHandled(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.simibubi.create.content.logistics.trains.management;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
||||
import com.simibubi.create.foundation.gui.element.ScreenElement;
|
||||
import com.simibubi.create.foundation.gui.widget.IconButton;
|
||||
|
||||
public class WideIconButton extends IconButton {
|
||||
|
||||
public WideIconButton(int x, int y, ScreenElement icon) {
|
||||
super(x, y, 26, 18, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawBg(PoseStack matrixStack, AllGuiTextures button) {
|
||||
super.drawBg(matrixStack, button);
|
||||
blit(matrixStack, x + 9, y, button.startX + 1, button.startY, button.width - 1, button.height);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package com.simibubi.create.content.logistics.trains.management.schedule;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
|
||||
import com.simibubi.create.foundation.gui.widget.Label;
|
||||
import com.simibubi.create.foundation.gui.widget.ScrollInput;
|
||||
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public abstract class CargoThresholdCondition extends ScheduleWaitCondition {
|
||||
public static enum Ops {
|
||||
GREATER(">"), LESS("<"), EQUAL("=");
|
||||
|
||||
public String formatted;
|
||||
|
||||
private Ops(String formatted) {
|
||||
this.formatted = formatted;
|
||||
}
|
||||
|
||||
public static List<? extends Component> translatedOptions() {
|
||||
return Arrays.stream(values())
|
||||
.map(op -> Lang.translate("schedule.condition.threshold." + Lang.asId(op.name())))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
public CargoThresholdCondition.Ops ops = Ops.GREATER;
|
||||
public int threshold;
|
||||
|
||||
protected abstract Component getUnit();
|
||||
|
||||
protected abstract ItemStack getIcon();
|
||||
|
||||
@Override
|
||||
public Pair<ItemStack, Component> getSummary() {
|
||||
return Pair.of(getIcon(), new TextComponent(ops.formatted + " " + threshold).append(getUnit()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(CompoundTag tag) {
|
||||
NBTHelper.writeEnum(tag, "Operator", ops);
|
||||
tag.putInt("Threshold", threshold);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag tag) {
|
||||
ops = NBTHelper.readEnum(tag, "Operator", CargoThresholdCondition.Ops.class);
|
||||
threshold = tag.getInt("Threshold");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsSlot() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Component> getSecondLineTooltip() {
|
||||
return ImmutableList.of(Lang.translate("schedule.condition.threshold.place_item"),
|
||||
Lang.translate("schedule.condition.threshold.place_item_2")
|
||||
.withStyle(ChatFormatting.GRAY));
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void createWidgets(ScheduleScreen screen,
|
||||
List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets,
|
||||
List<Integer> dividers, int x, int y) {
|
||||
super.createWidgets(screen, editorSubWidgets, dividers, x, y);
|
||||
|
||||
EditBox editBox = new EditBox(screen.getFont(), x + 109, y + 52, 35, 10, new TextComponent(threshold + ""));
|
||||
editBox.setBordered(false);
|
||||
editBox.setValue(threshold + "");
|
||||
editBox.setTextColor(0xFFFFFF);
|
||||
editBox.changeFocus(false);
|
||||
editBox.mouseClicked(0, 0, 0);
|
||||
editBox.setFilter(s -> {
|
||||
if (s.isEmpty())
|
||||
return true;
|
||||
try {
|
||||
Integer.parseInt(s);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
Label label = new Label(x + 87, y + 52, new TextComponent(ops.formatted)).withShadow();
|
||||
label.text = new TextComponent(ops.formatted);
|
||||
ScrollInput scrollInput = new SelectionScrollInput(x + 76, y + 48, 24, 16).forOptions(Ops.translatedOptions())
|
||||
.titled(Lang.translate("schedule.condition.threshold.train_holds"))
|
||||
.calling(state -> {
|
||||
label.text = new TextComponent(Ops.values()[state].formatted);
|
||||
})
|
||||
.setState(ops.ordinal());
|
||||
|
||||
editorSubWidgets.add(Pair.of(editBox, (dest, box) -> {
|
||||
CargoThresholdCondition c = (CargoThresholdCondition) dest;
|
||||
String text = ((EditBox) box).getValue();
|
||||
if (text.isEmpty())
|
||||
c.threshold = 0;
|
||||
else
|
||||
c.threshold = Integer.parseInt(text);
|
||||
}));
|
||||
editorSubWidgets.add(Pair.of(scrollInput, (dest, box) -> {
|
||||
CargoThresholdCondition c = (CargoThresholdCondition) dest;
|
||||
c.ops = Ops.values()[((ScrollInput) box).getState()];
|
||||
}));
|
||||
editorSubWidgets.add(Pair.of(label, (d, l) -> {
|
||||
}));
|
||||
|
||||
dividers.add(24);
|
||||
dividers.add(70);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package com.simibubi.create.content.logistics.trains.management.schedule;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public class FilteredDestination extends ScheduleDestination {
|
||||
public String nameFilter = "";
|
||||
|
||||
@Override
|
||||
public Pair<ItemStack, Component> getSummary() {
|
||||
return Pair.of(AllBlocks.TRACK_STATION.asStack(), new TextComponent(nameFilter));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag tag) {
|
||||
nameFilter = tag.getString("Filter");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(CompoundTag tag) {
|
||||
tag.putString("Filter", nameFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return Create.asResource("filtered");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getSecondLineIcon() {
|
||||
return AllBlocks.TRACK_STATION.asStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Component> getTitleAs(String type) {
|
||||
return ImmutableList.of(Lang.translate("schedule.destination.filtered_matching",
|
||||
new TextComponent(nameFilter).withStyle(ChatFormatting.YELLOW)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Component> getSecondLineTooltip() {
|
||||
return ImmutableList.of(Lang.translate("schedule.destination.filter"),
|
||||
Lang.translate("schedule.destination.filter_2")
|
||||
.withStyle(ChatFormatting.GRAY),
|
||||
Lang.translate("schedule.destination.filter_3")
|
||||
.withStyle(ChatFormatting.DARK_GRAY),
|
||||
Lang.translate("schedule.destination.filter_4")
|
||||
.withStyle(ChatFormatting.DARK_GRAY));
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void createWidgets(ScheduleScreen screen,
|
||||
List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets,
|
||||
List<Integer> dividers, int x, int y) {
|
||||
super.createWidgets(screen, editorSubWidgets, dividers, x, y);
|
||||
EditBox editBox = new EditBox(screen.getFont(), x + 84, y + 52, 112, 10, new TextComponent(nameFilter));
|
||||
editBox.setBordered(false);
|
||||
editBox.setTextColor(0xFFFFFF);
|
||||
editBox.setValue(nameFilter);
|
||||
editBox.changeFocus(false);
|
||||
editBox.mouseClicked(0, 0, 0);
|
||||
editorSubWidgets
|
||||
.add(Pair.of(editBox, (dest, box) -> ((FilteredDestination) dest).nameFilter = ((EditBox) box).getValue()));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package com.simibubi.create.content.logistics.trains.management.schedule;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.contraptions.processing.EmptyingByBasin;
|
||||
import com.simibubi.create.content.logistics.item.filter.FilterItem;
|
||||
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
|
||||
import com.simibubi.create.foundation.gui.widget.Label;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
public class FluidThresholdCondition extends CargoThresholdCondition {
|
||||
public ItemStack compareStack = ItemStack.EMPTY;
|
||||
public FluidStack fluidStack = null;
|
||||
|
||||
@Override
|
||||
protected Component getUnit() {
|
||||
return new TextComponent("b");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemStack getIcon() {
|
||||
return compareStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(CompoundTag tag) {
|
||||
super.write(tag);
|
||||
tag.put("Bucket", compareStack.serializeNBT());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag tag) {
|
||||
super.read(tag);
|
||||
compareStack = ItemStack.of(tag.getCompound("Bucket"));
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private FluidStack loadFluid() {
|
||||
if (fluidStack != null)
|
||||
return fluidStack;
|
||||
fluidStack = FluidStack.EMPTY;
|
||||
if (!EmptyingByBasin.canItemBeEmptied(Minecraft.getInstance().level, compareStack))
|
||||
return fluidStack;
|
||||
FluidStack fluidInFilter = EmptyingByBasin.emptyItem(Minecraft.getInstance().level, compareStack, true)
|
||||
.getFirst();
|
||||
if (fluidInFilter == null)
|
||||
return fluidStack;
|
||||
return fluidStack = fluidInFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Component> getTitleAs(String type) {
|
||||
return ImmutableList.of(
|
||||
Lang.translate("schedule.condition.threshold.train_holds",
|
||||
Lang.translate("schedule.condition.threshold." + Lang.asId(ops.name()))),
|
||||
Lang.translate("schedule.condition.threshold.x_units_of_item", threshold,
|
||||
Lang.translate("schedule.condition.threshold.buckets"),
|
||||
compareStack.getItem() instanceof FilterItem
|
||||
? Lang.translate("schedule.condition.threshold.matching_content")
|
||||
: loadFluid().getDisplayName())
|
||||
.withStyle(ChatFormatting.DARK_AQUA));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(ItemStack stack) {
|
||||
compareStack = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return Create.asResource("fluid_threshold");
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void createWidgets(ScheduleScreen screen,
|
||||
List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets,
|
||||
List<Integer> dividers, int x, int y) {
|
||||
super.createWidgets(screen, editorSubWidgets, dividers, x, y);
|
||||
|
||||
TranslatableComponent buckets = Lang.translate("schedule.condition.threshold.buckets");
|
||||
Label label = new Label(x + 155, y + 52, buckets).withShadow();
|
||||
label.text = buckets;
|
||||
editorSubWidgets.add(Pair.of(label, (d, l) -> {
|
||||
}));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package com.simibubi.create.content.logistics.trains.management.schedule;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public interface IScheduleInput {
|
||||
|
||||
public abstract Pair<ItemStack, Component> getSummary();
|
||||
|
||||
public abstract ResourceLocation getId();
|
||||
|
||||
public default boolean needsSlot() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public default void createWidgets(ScheduleScreen screen,
|
||||
List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets,
|
||||
List<Integer> dividers, int x, int y) {}
|
||||
|
||||
public default List<Component> getTitleAs(String type) {
|
||||
ResourceLocation id = getId();
|
||||
return ImmutableList.of(new TranslatableComponent(id.getNamespace() + ".schedule." + type + "." + id.getPath()));
|
||||
}
|
||||
|
||||
public default ItemStack getSecondLineIcon() {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
public default void setItem(ItemStack stack) {}
|
||||
|
||||
@Nullable
|
||||
public default List<Component> getSecondLineTooltip() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public default boolean renderSpecialIcon(PoseStack ms, int x, int y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.simibubi.create.content.logistics.trains.management.schedule;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class IdleCargoCondition extends TimedWaitCondition {
|
||||
@Override
|
||||
public Pair<ItemStack, Component> getSummary() {
|
||||
return Pair.of(ItemStack.EMPTY, Lang.translate("schedule.condition.idle_short", formatTime(true)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return Create.asResource("idle");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package com.simibubi.create.content.logistics.trains.management.schedule;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.logistics.item.filter.FilterItem;
|
||||
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
|
||||
import com.simibubi.create.foundation.gui.widget.Label;
|
||||
import com.simibubi.create.foundation.gui.widget.ScrollInput;
|
||||
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public class ItemThresholdCondition extends CargoThresholdCondition {
|
||||
public ItemStack stack = ItemStack.EMPTY;
|
||||
public boolean stacks;
|
||||
|
||||
@Override
|
||||
protected Component getUnit() {
|
||||
return new TextComponent(stacks ? "\u25A4" : "");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemStack getIcon() {
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(CompoundTag tag) {
|
||||
super.write(tag);
|
||||
tag.put("Item", stack.serializeNBT());
|
||||
tag.putBoolean("Stacks", stacks);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag tag) {
|
||||
super.read(tag);
|
||||
stack = ItemStack.of(tag.getCompound("Item"));
|
||||
stacks = tag.getBoolean("Stacks");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(ItemStack stack) {
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Component> getTitleAs(String type) {
|
||||
return ImmutableList.of(
|
||||
Lang.translate("schedule.condition.threshold.train_holds",
|
||||
Lang.translate("schedule.condition.threshold." + Lang.asId(ops.name()))),
|
||||
Lang.translate("schedule.condition.threshold.x_units_of_item", threshold,
|
||||
Lang.translate("schedule.condition.threshold." + (stacks ? "stacks" : "items")),
|
||||
stack.getItem() instanceof FilterItem ? Lang.translate("schedule.condition.threshold.matching_content")
|
||||
: stack.getHoverName())
|
||||
.withStyle(ChatFormatting.DARK_AQUA));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return Create.asResource("item_threshold");
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void createWidgets(ScheduleScreen screen,
|
||||
List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets,
|
||||
List<Integer> dividers, int x, int y) {
|
||||
super.createWidgets(screen, editorSubWidgets, dividers, x, y);
|
||||
|
||||
Label label = new Label(x + 155, y + 52, new TextComponent(ops.formatted)).withShadow();
|
||||
ScrollInput scrollInput = new SelectionScrollInput(x + 150, y + 48, 49, 16)
|
||||
.forOptions(ImmutableList.of(Lang.translate("schedule.condition.threshold.items"),
|
||||
Lang.translate("schedule.condition.threshold.stacks")))
|
||||
.titled(Lang.translate("schedule.condition.threshold.item_measure"))
|
||||
.writingTo(label)
|
||||
.setState(stacks ? 1 : 0);
|
||||
|
||||
editorSubWidgets.add(Pair.of(scrollInput, (dest, box) -> {
|
||||
ItemThresholdCondition c = (ItemThresholdCondition) dest;
|
||||
c.stacks = ((ScrollInput) box).getState() == 1;
|
||||
}));
|
||||
editorSubWidgets.add(Pair.of(label, (d, l) -> {
|
||||
}));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.simibubi.create.content.logistics.trains.management.schedule;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class NearestDestination extends ScheduleDestination {
|
||||
@Override
|
||||
public Pair<ItemStack, Component> getSummary() {
|
||||
return Pair.of(AllBlocks.TRACK_STATION.asStack(), Lang.translate("schedule.destination.nearest"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(CompoundTag tag) {}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag tag) {}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return Create.asResource("nearest");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.simibubi.create.content.logistics.trains.management.schedule;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class RedstoneDestination extends ScheduleDestination {
|
||||
@Override
|
||||
public Pair<ItemStack, Component> getSummary() {
|
||||
return Pair.of(AllBlocks.TRACK_STATION.asStack(), new TextComponent("Redstone Pulse"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(CompoundTag tag) {}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag tag) {}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return Create.asResource("redstone");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package com.simibubi.create.content.logistics.trains.management.schedule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class Schedule {
|
||||
|
||||
public static List<Pair<ResourceLocation, Supplier<? extends ScheduleDestination>>> DESTINATION_TYPES =
|
||||
new ArrayList<>();
|
||||
public static List<Pair<ResourceLocation, Supplier<? extends ScheduleWaitCondition>>> CONDITION_TYPES =
|
||||
new ArrayList<>();
|
||||
|
||||
static {
|
||||
registerDestination("filtered", FilteredDestination::new);
|
||||
registerDestination("nearest", NearestDestination::new);
|
||||
registerDestination("redstone", RedstoneDestination::new);
|
||||
registerCondition("delay", ScheduledDelay::new);
|
||||
registerCondition("time_of_day", TimeOfDayCondition::new);
|
||||
registerCondition("fluid_threshold", FluidThresholdCondition::new);
|
||||
registerCondition("item_threshold", ItemThresholdCondition::new);
|
||||
registerCondition("idle", IdleCargoCondition::new);
|
||||
registerCondition("unloaded", StationUnloadedCondition::new);
|
||||
registerCondition("powered", StationPoweredCondition::new);
|
||||
}
|
||||
|
||||
private static void registerDestination(String name, Supplier<? extends ScheduleDestination> factory) {
|
||||
DESTINATION_TYPES.add(Pair.of(Create.asResource(name), factory));
|
||||
}
|
||||
|
||||
private static void registerCondition(String name, Supplier<? extends ScheduleWaitCondition> factory) {
|
||||
CONDITION_TYPES.add(Pair.of(Create.asResource(name), factory));
|
||||
}
|
||||
|
||||
public static <T> List<? extends Component> getTypeOptions(List<Pair<ResourceLocation, T>> list) {
|
||||
String langSection = list.equals(DESTINATION_TYPES) ? "destination." : "condition.";
|
||||
return list.stream()
|
||||
.map(Pair::getFirst)
|
||||
.map(rl -> rl.getNamespace() + ".schedule." + langSection + rl.getPath())
|
||||
.map(TranslatableComponent::new)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public List<ScheduleEntry> entries;
|
||||
public boolean cyclic;
|
||||
|
||||
public Schedule() {
|
||||
entries = new ArrayList<>();
|
||||
cyclic = true;
|
||||
}
|
||||
|
||||
public CompoundTag write() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
ListTag list = NBTHelper.writeCompoundList(entries, ScheduleEntry::write);
|
||||
tag.put("Entries", list);
|
||||
tag.putBoolean("Cyclic", cyclic);
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static Schedule fromTag(CompoundTag tag) {
|
||||
Schedule schedule = new Schedule();
|
||||
schedule.entries = NBTHelper.readCompoundList(tag.getList("Entries", Tag.TAG_COMPOUND), ScheduleEntry::fromTag);
|
||||
schedule.cyclic = tag.getBoolean("Cyclic");
|
||||
return schedule;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.simibubi.create.content.logistics.trains.management.schedule;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public abstract class ScheduleDestination implements IScheduleInput {
|
||||
|
||||
protected abstract void write(CompoundTag tag);
|
||||
|
||||
protected abstract void read(CompoundTag tag);
|
||||
|
||||
public final CompoundTag write() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putString("Id", getId().toString());
|
||||
write(tag);
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static ScheduleDestination fromTag(CompoundTag tag) {
|
||||
ResourceLocation location = new ResourceLocation(tag.getString("Id"));
|
||||
Supplier<? extends ScheduleDestination> supplier = null;
|
||||
for (Pair<ResourceLocation, Supplier<? extends ScheduleDestination>> pair : Schedule.DESTINATION_TYPES)
|
||||
if (pair.getFirst()
|
||||
.equals(location))
|
||||
supplier = pair.getSecond();
|
||||
|
||||
if (supplier == null) {
|
||||
Create.LOGGER.warn("Could not parse schedule destination type: " + location);
|
||||
return null;
|
||||
}
|
||||
|
||||
ScheduleDestination scheduleDestination = supplier.get();
|
||||
scheduleDestination.read(tag);
|
||||
return scheduleDestination;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.simibubi.create.content.logistics.trains.management.schedule;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.network.NetworkEvent.Context;
|
||||
|
||||
public class ScheduleEditPacket extends SimplePacketBase {
|
||||
|
||||
private Schedule schedule;
|
||||
|
||||
public ScheduleEditPacket(Schedule schedule) {
|
||||
this.schedule = schedule;
|
||||
}
|
||||
|
||||
public ScheduleEditPacket(FriendlyByteBuf buffer) {
|
||||
schedule = Schedule.fromTag(buffer.readNbt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeNbt(schedule.write());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Supplier<Context> context) {
|
||||
context.get()
|
||||
.enqueueWork(() -> {
|
||||
ServerPlayer sender = context.get()
|
||||
.getSender();
|
||||
ItemStack mainHandItem = sender.getMainHandItem();
|
||||
if (!AllItems.SCHEDULE.isIn(mainHandItem))
|
||||
return;
|
||||
mainHandItem.getOrCreateTag()
|
||||
.put("Schedule", schedule.write());
|
||||
sender.getCooldowns()
|
||||
.addCooldown(mainHandItem.getItem(), 5);
|
||||
});
|
||||
context.get()
|
||||
.setPacketHandled(true);
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue