mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-02-28 12:54:40 +01:00
Big Data
- Added the Display Board - Added the Data Gatherer - Nixie Tubes no longer animate text from "dynamic" vanilla text components - Trains now keep travel time statistics for prediction purposes - Created "Data-target" behaviour for Signs, Display Boards, Lecterns and Nixie Tubes - Created "Data-source" behaviour for Train Stations, Clocks, Nixie Tubes, Content Observers, Stockpile Switches, Respawn Anchors, Depots, Belts, Belt Tunnels and Command Blocks
This commit is contained in:
parent
9d8803d280
commit
39b51821aa
114 changed files with 7231 additions and 743 deletions
|
@ -188,11 +188,13 @@ b496452f2f7dbbba385e1fc10b560ec266e4b5e7 assets/create/blockstates/cyan_sail.jso
|
||||||
2c04d57e56849f243aec8a1e769574d24daac1e9 assets/create/blockstates/cyan_valve_handle.json
|
2c04d57e56849f243aec8a1e769574d24daac1e9 assets/create/blockstates/cyan_valve_handle.json
|
||||||
1726b1b9e04a0634e7e1fdcf1cf4cc898efc5c2f assets/create/blockstates/dark_oak_window.json
|
1726b1b9e04a0634e7e1fdcf1cf4cc898efc5c2f assets/create/blockstates/dark_oak_window.json
|
||||||
50d4627d8e8b5adade12de764ab528ddacfa9ea5 assets/create/blockstates/dark_oak_window_pane.json
|
50d4627d8e8b5adade12de764ab528ddacfa9ea5 assets/create/blockstates/dark_oak_window_pane.json
|
||||||
|
990cdcce80e6e4ea3055c2572c5fafe3ee795b0f assets/create/blockstates/data_gatherer.json
|
||||||
de0116bf32a26d697a3b999044d6fb0b1b98320e assets/create/blockstates/deepslate_pillar.json
|
de0116bf32a26d697a3b999044d6fb0b1b98320e assets/create/blockstates/deepslate_pillar.json
|
||||||
c3317a94c509d4bb2fe9c6f64a072334421998d3 assets/create/blockstates/deepslate_zinc_ore.json
|
c3317a94c509d4bb2fe9c6f64a072334421998d3 assets/create/blockstates/deepslate_zinc_ore.json
|
||||||
ac85f55d82d96fc15750e6b954297cfd1e00d04d assets/create/blockstates/deployer.json
|
ac85f55d82d96fc15750e6b954297cfd1e00d04d assets/create/blockstates/deployer.json
|
||||||
3660f44309279a0347347f23ce7444c6ed98cafd assets/create/blockstates/depot.json
|
3660f44309279a0347347f23ce7444c6ed98cafd assets/create/blockstates/depot.json
|
||||||
0270b68550e19720d0cdc9e44f63618908628192 assets/create/blockstates/diorite_pillar.json
|
0270b68550e19720d0cdc9e44f63618908628192 assets/create/blockstates/diorite_pillar.json
|
||||||
|
62cc543abb242836570d07d619fcdb4c79c75db4 assets/create/blockstates/display_board.json
|
||||||
30b3422bfee9878c92521429b2536d3e0313cedb assets/create/blockstates/dripstone_pillar.json
|
30b3422bfee9878c92521429b2536d3e0313cedb assets/create/blockstates/dripstone_pillar.json
|
||||||
35fc68eb1d031d28ad09b7b603e64ae459634179 assets/create/blockstates/encased_chain_drive.json
|
35fc68eb1d031d28ad09b7b603e64ae459634179 assets/create/blockstates/encased_chain_drive.json
|
||||||
7b2b836649e729feafa60972bf95e3afb2143131 assets/create/blockstates/encased_fan.json
|
7b2b836649e729feafa60972bf95e3afb2143131 assets/create/blockstates/encased_fan.json
|
||||||
|
@ -382,8 +384,8 @@ bc91f1cbdf0c2f9867edb36652bda43aa614e414 assets/create/blockstates/polished_cut_
|
||||||
c650bece9b333daba3174f944e6ebd41a010c850 assets/create/blockstates/powered_shaft.json
|
c650bece9b333daba3174f944e6ebd41a010c850 assets/create/blockstates/powered_shaft.json
|
||||||
e8b0a401c10d1ba67ed71ba31bd5f9bc28571b65 assets/create/blockstates/powered_toggle_latch.json
|
e8b0a401c10d1ba67ed71ba31bd5f9bc28571b65 assets/create/blockstates/powered_toggle_latch.json
|
||||||
3a739f9d4276828d83f2d2750bf3227c87bcd438 assets/create/blockstates/pulley_magnet.json
|
3a739f9d4276828d83f2d2750bf3227c87bcd438 assets/create/blockstates/pulley_magnet.json
|
||||||
dee3cdef860bb92d439ecaaec4300b42208b025c assets/create/blockstates/pulse_extender.json
|
2a825cb867b9738b34d80b4151c55f76eb95e2ef assets/create/blockstates/pulse_extender.json
|
||||||
638eb675fe3c464a0ab265c37f7d37fdf6440323 assets/create/blockstates/pulse_repeater.json
|
9035c427fdb0035312f617196e65a1e3814bd0fa assets/create/blockstates/pulse_repeater.json
|
||||||
ea8200550190eb65d8631c7842e06d99274b3c79 assets/create/blockstates/purple_nixie_tube.json
|
ea8200550190eb65d8631c7842e06d99274b3c79 assets/create/blockstates/purple_nixie_tube.json
|
||||||
d06cd9a1101b18d306a786320aab12018b1325d6 assets/create/blockstates/purple_sail.json
|
d06cd9a1101b18d306a786320aab12018b1325d6 assets/create/blockstates/purple_sail.json
|
||||||
92957119abd5fbcca36a113b2a80255fd70fc303 assets/create/blockstates/purple_seat.json
|
92957119abd5fbcca36a113b2a80255fd70fc303 assets/create/blockstates/purple_seat.json
|
||||||
|
@ -540,22 +542,22 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
|
||||||
6801fa1f466f172700e573e5b8ee8ee5f9ca4583 assets/create/blockstates/yellow_valve_handle.json
|
6801fa1f466f172700e573e5b8ee8ee5f9ca4583 assets/create/blockstates/yellow_valve_handle.json
|
||||||
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
|
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
|
||||||
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
|
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
|
||||||
03a6020bfac9e4f979252abc8a631e6aafaa6b8b assets/create/lang/en_ud.json
|
dde2b8043a318bc88b6d381f9de6bfd557c0f079 assets/create/lang/en_ud.json
|
||||||
f30503db6d2841ebc7c59bf0a79b680a765613cd assets/create/lang/en_us.json
|
0ea900a1d36f0b19568f8183844a64016c539dcf assets/create/lang/en_us.json
|
||||||
3730041212c67067395b57218f26a403a18016c9 assets/create/lang/unfinished/de_de.json
|
c9977bb0eb8912a4260e414d8868628904d847a0 assets/create/lang/unfinished/de_de.json
|
||||||
f1dd81b07e832b0f3187b2f52fdf3cdbea41fec1 assets/create/lang/unfinished/es_cl.json
|
4d30c4754b8494fbbe62340b7c67ba3d2ada6721 assets/create/lang/unfinished/es_cl.json
|
||||||
afc637fd921e0f17ec2b70d93b7a474d347a6a18 assets/create/lang/unfinished/es_es.json
|
29c05f8ed2ec05e5bd4c73f6678946041c4e8293 assets/create/lang/unfinished/es_es.json
|
||||||
7258250074ffe3e50fe4803a2effe4f2b7a94c4e assets/create/lang/unfinished/fr_fr.json
|
027514a78a5f233c2d579694fa3c6a2c57ce3272 assets/create/lang/unfinished/fr_fr.json
|
||||||
91cd404b62a87dd820cc5602622c88c65a5d5dbb assets/create/lang/unfinished/it_it.json
|
f354377f09ebc8ee7863dc24266215fc77003c11 assets/create/lang/unfinished/it_it.json
|
||||||
7716adb1099e6b164d07390679b3a1b77397048e assets/create/lang/unfinished/ja_jp.json
|
8e8d4fe60ca6386e14c31cb4a24274cd21e92212 assets/create/lang/unfinished/ja_jp.json
|
||||||
4b2b3ff736dbbfc58803432463e11850d651e631 assets/create/lang/unfinished/ko_kr.json
|
39194f6899360e4a13f0d3feac07ab25b5c18256 assets/create/lang/unfinished/ko_kr.json
|
||||||
23ec8c0fbb3d82e92397ef5857b2f57e2f72ae40 assets/create/lang/unfinished/nl_nl.json
|
4b067fe0830950e7cc6615c8f466686b5aefee7f assets/create/lang/unfinished/nl_nl.json
|
||||||
e8ef3db7b90bbc2a91bd104228c81b54bca638e7 assets/create/lang/unfinished/pl_pl.json
|
44fd3bc93eb6f2dce30a7f52a765662fb1093791 assets/create/lang/unfinished/pl_pl.json
|
||||||
0213870418b26af7f67c794973144594918fa114 assets/create/lang/unfinished/pt_br.json
|
410f0132633089e26db9d7b70c49fc3c39541cd6 assets/create/lang/unfinished/pt_br.json
|
||||||
c0fccd4886228185a61af35535f3a92944d64c98 assets/create/lang/unfinished/pt_pt.json
|
bec4373054c1e0d2cd803572f8491e7597e292c2 assets/create/lang/unfinished/pt_pt.json
|
||||||
2cf778412184edac79cf457adb57f68475d7bcf0 assets/create/lang/unfinished/ru_ru.json
|
3ff78cccb260071cf5d55af9ace4f7ed1eadb46b assets/create/lang/unfinished/ru_ru.json
|
||||||
feab3d65b3b95ecb6730d5d45fd672e4e2545ee3 assets/create/lang/unfinished/zh_cn.json
|
9ea4b032f852a55d9359fb931f5eb91243d87e36 assets/create/lang/unfinished/zh_cn.json
|
||||||
eee611a3eecfa457050d522195f76e95a35dca81 assets/create/lang/unfinished/zh_tw.json
|
33a7cf2b3b6014b5714fdb5f63de49474f23d2aa assets/create/lang/unfinished/zh_tw.json
|
||||||
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
|
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
|
||||||
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
|
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
|
||||||
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
|
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
|
||||||
|
@ -1783,11 +1785,13 @@ b1eace1d7fe80e2b8dc0d844621f0d485f34cbf8 assets/create/models/item/cut_veridium_
|
||||||
523cd531eadaadc45fb356ca58b99a8fe206c3a7 assets/create/models/item/cyan_valve_handle.json
|
523cd531eadaadc45fb356ca58b99a8fe206c3a7 assets/create/models/item/cyan_valve_handle.json
|
||||||
f786a43e296d9f10d7c302fe3ae9cddf4ba9984e assets/create/models/item/dark_oak_window.json
|
f786a43e296d9f10d7c302fe3ae9cddf4ba9984e assets/create/models/item/dark_oak_window.json
|
||||||
515d55b1ce18543fdb44b194901040fd29e75818 assets/create/models/item/dark_oak_window_pane.json
|
515d55b1ce18543fdb44b194901040fd29e75818 assets/create/models/item/dark_oak_window_pane.json
|
||||||
|
2faefc40f532f8480916f6d6a9c4a15e40deecef assets/create/models/item/data_gatherer.json
|
||||||
422c5ab12029ffdf37b315a158168d71725bd334 assets/create/models/item/deepslate_pillar.json
|
422c5ab12029ffdf37b315a158168d71725bd334 assets/create/models/item/deepslate_pillar.json
|
||||||
0f220a538e6a083debf68b4f1135d5f3ae4a3918 assets/create/models/item/deepslate_zinc_ore.json
|
0f220a538e6a083debf68b4f1135d5f3ae4a3918 assets/create/models/item/deepslate_zinc_ore.json
|
||||||
2104c1276259ab67b94f3d4fe97e14b6bc6941ac assets/create/models/item/deployer.json
|
2104c1276259ab67b94f3d4fe97e14b6bc6941ac assets/create/models/item/deployer.json
|
||||||
84d87f715efab45dc7bcb2e3c0870ed56fa20ee9 assets/create/models/item/depot.json
|
84d87f715efab45dc7bcb2e3c0870ed56fa20ee9 assets/create/models/item/depot.json
|
||||||
e0ecc0a20cf9dd54ccfc48e0041d5220b2c8316e assets/create/models/item/diorite_pillar.json
|
e0ecc0a20cf9dd54ccfc48e0041d5220b2c8316e assets/create/models/item/diorite_pillar.json
|
||||||
|
0ff9267a39783dce5e0aa59e78088c64337ad6ee assets/create/models/item/display_board.json
|
||||||
6006f88e56d74a3fd75a9dddb25af39075e0482b assets/create/models/item/diving_boots.json
|
6006f88e56d74a3fd75a9dddb25af39075e0482b assets/create/models/item/diving_boots.json
|
||||||
df8cfe7e8eb527329094396e11222e9097e309d7 assets/create/models/item/diving_helmet.json
|
df8cfe7e8eb527329094396e11222e9097e309d7 assets/create/models/item/diving_helmet.json
|
||||||
4b2af721dccfcf4e5b5a7b0f64f295d7cfd27f69 assets/create/models/item/dough.json
|
4b2af721dccfcf4e5b5a7b0f64f295d7cfd27f69 assets/create/models/item/dough.json
|
||||||
|
@ -3478,11 +3482,13 @@ db7ea40bfd36b5fa864453716256aba748435e36 data/create/loot_tables/blocks/cyan_sea
|
||||||
8854c95ee0d78abfb0393f7b4185618dc9aecba3 data/create/loot_tables/blocks/cyan_valve_handle.json
|
8854c95ee0d78abfb0393f7b4185618dc9aecba3 data/create/loot_tables/blocks/cyan_valve_handle.json
|
||||||
0d17705688109e9cf81c99ef559b1183b0e6053c data/create/loot_tables/blocks/dark_oak_window.json
|
0d17705688109e9cf81c99ef559b1183b0e6053c data/create/loot_tables/blocks/dark_oak_window.json
|
||||||
636acaf2ebbbd790f8efe45a98cd036ffe848407 data/create/loot_tables/blocks/dark_oak_window_pane.json
|
636acaf2ebbbd790f8efe45a98cd036ffe848407 data/create/loot_tables/blocks/dark_oak_window_pane.json
|
||||||
|
c9dad60d36dde6522729fe433cb5022a00c12ce1 data/create/loot_tables/blocks/data_gatherer.json
|
||||||
18f29fec67600edc66b25217017b5b618efb1f4b data/create/loot_tables/blocks/deepslate_pillar.json
|
18f29fec67600edc66b25217017b5b618efb1f4b data/create/loot_tables/blocks/deepslate_pillar.json
|
||||||
841d6010e87a4bf4e35e8ccc411e5d7f513b484a data/create/loot_tables/blocks/deepslate_zinc_ore.json
|
841d6010e87a4bf4e35e8ccc411e5d7f513b484a data/create/loot_tables/blocks/deepslate_zinc_ore.json
|
||||||
12a02b7737557a81281369826907b7e75076b8a0 data/create/loot_tables/blocks/deployer.json
|
12a02b7737557a81281369826907b7e75076b8a0 data/create/loot_tables/blocks/deployer.json
|
||||||
b6118279802f1a27e6e0c3d0feca86f0792f85df data/create/loot_tables/blocks/depot.json
|
b6118279802f1a27e6e0c3d0feca86f0792f85df data/create/loot_tables/blocks/depot.json
|
||||||
48eba3e521b190fedfb6e7580bdb10bcb3f290bd data/create/loot_tables/blocks/diorite_pillar.json
|
48eba3e521b190fedfb6e7580bdb10bcb3f290bd data/create/loot_tables/blocks/diorite_pillar.json
|
||||||
|
2a8d81a07e9d209349264787eee93a0b973d2510 data/create/loot_tables/blocks/display_board.json
|
||||||
7ab5f0aa32d6641999943636766c806a1d59e1d2 data/create/loot_tables/blocks/dripstone_pillar.json
|
7ab5f0aa32d6641999943636766c806a1d59e1d2 data/create/loot_tables/blocks/dripstone_pillar.json
|
||||||
2186860c4a0cb47a66bdfdefcde302c599cddeea data/create/loot_tables/blocks/encased_chain_drive.json
|
2186860c4a0cb47a66bdfdefcde302c599cddeea data/create/loot_tables/blocks/encased_chain_drive.json
|
||||||
7fcc15674a7583b965441fb079b8997e4244a4ff data/create/loot_tables/blocks/encased_fan.json
|
7fcc15674a7583b965441fb079b8997e4244a4ff data/create/loot_tables/blocks/encased_fan.json
|
||||||
|
@ -5292,7 +5298,7 @@ ff1900963bc4cd8ceffa78d58ef1952ceacb2fb7 data/forge/tags/items/storage_blocks/br
|
||||||
69f596fcb065e26b02ce246760432b5174191b76 data/minecraft/tags/blocks/impermeable.json
|
69f596fcb065e26b02ce246760432b5174191b76 data/minecraft/tags/blocks/impermeable.json
|
||||||
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/lush_ground_replaceable.json
|
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/lush_ground_replaceable.json
|
||||||
02f7a9df2f9e154749266e7ac59c37aa076a3390 data/minecraft/tags/blocks/mineable/axe.json
|
02f7a9df2f9e154749266e7ac59c37aa076a3390 data/minecraft/tags/blocks/mineable/axe.json
|
||||||
a462e6c5caf03b7d11e61ef775724472fdd53570 data/minecraft/tags/blocks/mineable/pickaxe.json
|
20500209238916508e88a8219e7f3b342bb16461 data/minecraft/tags/blocks/mineable/pickaxe.json
|
||||||
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/moss_replaceable.json
|
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/moss_replaceable.json
|
||||||
e157c1d3af30e409e34bbefbe15a037e6e1c8daa data/minecraft/tags/blocks/needs_iron_tool.json
|
e157c1d3af30e409e34bbefbe15a037e6e1c8daa data/minecraft/tags/blocks/needs_iron_tool.json
|
||||||
a08f67865337f62601c5e333b4011382d10020e4 data/minecraft/tags/blocks/needs_stone_tool.json
|
a08f67865337f62601c5e333b4011382d10020e4 data/minecraft/tags/blocks/needs_stone_tool.json
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"facing=down,powered=false": {
|
||||||
|
"model": "create:block/data_gatherer/block",
|
||||||
|
"x": 180
|
||||||
|
},
|
||||||
|
"facing=up,powered=false": {
|
||||||
|
"model": "create:block/data_gatherer/block"
|
||||||
|
},
|
||||||
|
"facing=north,powered=false": {
|
||||||
|
"model": "create:block/data_gatherer/block",
|
||||||
|
"x": 90
|
||||||
|
},
|
||||||
|
"facing=south,powered=false": {
|
||||||
|
"model": "create:block/data_gatherer/block",
|
||||||
|
"x": 90,
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=west,powered=false": {
|
||||||
|
"model": "create:block/data_gatherer/block",
|
||||||
|
"x": 90,
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=east,powered=false": {
|
||||||
|
"model": "create:block/data_gatherer/block",
|
||||||
|
"x": 90,
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=down,powered=true": {
|
||||||
|
"model": "create:block/data_gatherer/block_powered",
|
||||||
|
"x": 180
|
||||||
|
},
|
||||||
|
"facing=up,powered=true": {
|
||||||
|
"model": "create:block/data_gatherer/block_powered"
|
||||||
|
},
|
||||||
|
"facing=north,powered=true": {
|
||||||
|
"model": "create:block/data_gatherer/block_powered",
|
||||||
|
"x": 90
|
||||||
|
},
|
||||||
|
"facing=south,powered=true": {
|
||||||
|
"model": "create:block/data_gatherer/block_powered",
|
||||||
|
"x": 90,
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=west,powered=true": {
|
||||||
|
"model": "create:block/data_gatherer/block_powered",
|
||||||
|
"x": 90,
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=east,powered=true": {
|
||||||
|
"model": "create:block/data_gatherer/block_powered",
|
||||||
|
"x": 90,
|
||||||
|
"y": 90
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"down=false,facing=north,up=false,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block"
|
||||||
|
},
|
||||||
|
"down=true,facing=north,up=false,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block"
|
||||||
|
},
|
||||||
|
"down=false,facing=south,up=false,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"down=true,facing=south,up=false,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"down=false,facing=west,up=false,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"down=true,facing=west,up=false,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"down=false,facing=east,up=false,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"down=true,facing=east,up=false,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"down=false,facing=north,up=true,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block"
|
||||||
|
},
|
||||||
|
"down=true,facing=north,up=true,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block"
|
||||||
|
},
|
||||||
|
"down=false,facing=south,up=true,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"down=true,facing=south,up=true,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"down=false,facing=west,up=true,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"down=true,facing=west,up=true,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"down=false,facing=east,up=true,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"down=true,facing=east,up=true,waterlogged=false": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"down=false,facing=north,up=false,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block"
|
||||||
|
},
|
||||||
|
"down=true,facing=north,up=false,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block"
|
||||||
|
},
|
||||||
|
"down=false,facing=south,up=false,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"down=true,facing=south,up=false,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"down=false,facing=west,up=false,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"down=true,facing=west,up=false,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"down=false,facing=east,up=false,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"down=true,facing=east,up=false,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"down=false,facing=north,up=true,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block"
|
||||||
|
},
|
||||||
|
"down=true,facing=north,up=true,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block"
|
||||||
|
},
|
||||||
|
"down=false,facing=south,up=true,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"down=true,facing=south,up=true,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"down=false,facing=west,up=true,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"down=true,facing=west,up=true,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"down=false,facing=east,up=true,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"down=true,facing=east,up=true,waterlogged=true": {
|
||||||
|
"model": "create:block/display_board/block",
|
||||||
|
"y": 90
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,64 +1,124 @@
|
||||||
{
|
{
|
||||||
"variants": {
|
"variants": {
|
||||||
"facing=north,powered=false,powering=false": {
|
"facing=north,inverted=false,powered=false,powering=false": {
|
||||||
"model": "create:block/diodes/pulse_extender",
|
"model": "create:block/diodes/pulse_extender",
|
||||||
"y": 180
|
"y": 180
|
||||||
},
|
},
|
||||||
"facing=south,powered=false,powering=false": {
|
"facing=south,inverted=false,powered=false,powering=false": {
|
||||||
"model": "create:block/diodes/pulse_extender"
|
"model": "create:block/diodes/pulse_extender"
|
||||||
},
|
},
|
||||||
"facing=west,powered=false,powering=false": {
|
"facing=west,inverted=false,powered=false,powering=false": {
|
||||||
"model": "create:block/diodes/pulse_extender",
|
"model": "create:block/diodes/pulse_extender",
|
||||||
"y": 90
|
"y": 90
|
||||||
},
|
},
|
||||||
"facing=east,powered=false,powering=false": {
|
"facing=east,inverted=false,powered=false,powering=false": {
|
||||||
"model": "create:block/diodes/pulse_extender",
|
"model": "create:block/diodes/pulse_extender",
|
||||||
"y": 270
|
"y": 270
|
||||||
},
|
},
|
||||||
"facing=north,powered=true,powering=false": {
|
"facing=north,inverted=true,powered=false,powering=false": {
|
||||||
"model": "create:block/pulse_extender_powered",
|
|
||||||
"y": 180
|
|
||||||
},
|
|
||||||
"facing=south,powered=true,powering=false": {
|
|
||||||
"model": "create:block/pulse_extender_powered"
|
|
||||||
},
|
|
||||||
"facing=west,powered=true,powering=false": {
|
|
||||||
"model": "create:block/pulse_extender_powered",
|
|
||||||
"y": 90
|
|
||||||
},
|
|
||||||
"facing=east,powered=true,powering=false": {
|
|
||||||
"model": "create:block/pulse_extender_powered",
|
|
||||||
"y": 270
|
|
||||||
},
|
|
||||||
"facing=north,powered=false,powering=true": {
|
|
||||||
"model": "create:block/pulse_extender_powering",
|
"model": "create:block/pulse_extender_powering",
|
||||||
"y": 180
|
"y": 180
|
||||||
},
|
},
|
||||||
"facing=south,powered=false,powering=true": {
|
"facing=south,inverted=true,powered=false,powering=false": {
|
||||||
"model": "create:block/pulse_extender_powering"
|
"model": "create:block/pulse_extender_powering"
|
||||||
},
|
},
|
||||||
"facing=west,powered=false,powering=true": {
|
"facing=west,inverted=true,powered=false,powering=false": {
|
||||||
"model": "create:block/pulse_extender_powering",
|
"model": "create:block/pulse_extender_powering",
|
||||||
"y": 90
|
"y": 90
|
||||||
},
|
},
|
||||||
"facing=east,powered=false,powering=true": {
|
"facing=east,inverted=true,powered=false,powering=false": {
|
||||||
"model": "create:block/pulse_extender_powering",
|
"model": "create:block/pulse_extender_powering",
|
||||||
"y": 270
|
"y": 270
|
||||||
},
|
},
|
||||||
"facing=north,powered=true,powering=true": {
|
"facing=north,inverted=false,powered=true,powering=false": {
|
||||||
|
"model": "create:block/pulse_extender_powered",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,inverted=false,powered=true,powering=false": {
|
||||||
|
"model": "create:block/pulse_extender_powered"
|
||||||
|
},
|
||||||
|
"facing=west,inverted=false,powered=true,powering=false": {
|
||||||
|
"model": "create:block/pulse_extender_powered",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,inverted=false,powered=true,powering=false": {
|
||||||
|
"model": "create:block/pulse_extender_powered",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,inverted=true,powered=true,powering=false": {
|
||||||
"model": "create:block/pulse_extender_powered_powering",
|
"model": "create:block/pulse_extender_powered_powering",
|
||||||
"y": 180
|
"y": 180
|
||||||
},
|
},
|
||||||
"facing=south,powered=true,powering=true": {
|
"facing=south,inverted=true,powered=true,powering=false": {
|
||||||
"model": "create:block/pulse_extender_powered_powering"
|
"model": "create:block/pulse_extender_powered_powering"
|
||||||
},
|
},
|
||||||
"facing=west,powered=true,powering=true": {
|
"facing=west,inverted=true,powered=true,powering=false": {
|
||||||
"model": "create:block/pulse_extender_powered_powering",
|
"model": "create:block/pulse_extender_powered_powering",
|
||||||
"y": 90
|
"y": 90
|
||||||
},
|
},
|
||||||
"facing=east,powered=true,powering=true": {
|
"facing=east,inverted=true,powered=true,powering=false": {
|
||||||
"model": "create:block/pulse_extender_powered_powering",
|
"model": "create:block/pulse_extender_powered_powering",
|
||||||
"y": 270
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,inverted=false,powered=false,powering=true": {
|
||||||
|
"model": "create:block/pulse_extender_powering",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,inverted=false,powered=false,powering=true": {
|
||||||
|
"model": "create:block/pulse_extender_powering"
|
||||||
|
},
|
||||||
|
"facing=west,inverted=false,powered=false,powering=true": {
|
||||||
|
"model": "create:block/pulse_extender_powering",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,inverted=false,powered=false,powering=true": {
|
||||||
|
"model": "create:block/pulse_extender_powering",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,inverted=true,powered=false,powering=true": {
|
||||||
|
"model": "create:block/diodes/pulse_extender",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,inverted=true,powered=false,powering=true": {
|
||||||
|
"model": "create:block/diodes/pulse_extender"
|
||||||
|
},
|
||||||
|
"facing=west,inverted=true,powered=false,powering=true": {
|
||||||
|
"model": "create:block/diodes/pulse_extender",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,inverted=true,powered=false,powering=true": {
|
||||||
|
"model": "create:block/diodes/pulse_extender",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,inverted=false,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_extender_powered_powering",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,inverted=false,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_extender_powered_powering"
|
||||||
|
},
|
||||||
|
"facing=west,inverted=false,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_extender_powered_powering",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,inverted=false,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_extender_powered_powering",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,inverted=true,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_extender_powered",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,inverted=true,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_extender_powered"
|
||||||
|
},
|
||||||
|
"facing=west,inverted=true,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_extender_powered",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,inverted=true,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_extender_powered",
|
||||||
|
"y": 270
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,64 +1,124 @@
|
||||||
{
|
{
|
||||||
"variants": {
|
"variants": {
|
||||||
"facing=north,powered=false,powering=false": {
|
"facing=north,inverted=false,powered=false,powering=false": {
|
||||||
"model": "create:block/diodes/pulse_repeater",
|
"model": "create:block/diodes/pulse_repeater",
|
||||||
"y": 180
|
"y": 180
|
||||||
},
|
},
|
||||||
"facing=south,powered=false,powering=false": {
|
"facing=south,inverted=false,powered=false,powering=false": {
|
||||||
"model": "create:block/diodes/pulse_repeater"
|
"model": "create:block/diodes/pulse_repeater"
|
||||||
},
|
},
|
||||||
"facing=west,powered=false,powering=false": {
|
"facing=west,inverted=false,powered=false,powering=false": {
|
||||||
"model": "create:block/diodes/pulse_repeater",
|
"model": "create:block/diodes/pulse_repeater",
|
||||||
"y": 90
|
"y": 90
|
||||||
},
|
},
|
||||||
"facing=east,powered=false,powering=false": {
|
"facing=east,inverted=false,powered=false,powering=false": {
|
||||||
"model": "create:block/diodes/pulse_repeater",
|
"model": "create:block/diodes/pulse_repeater",
|
||||||
"y": 270
|
"y": 270
|
||||||
},
|
},
|
||||||
"facing=north,powered=true,powering=false": {
|
"facing=north,inverted=true,powered=false,powering=false": {
|
||||||
"model": "create:block/pulse_repeater_powered",
|
|
||||||
"y": 180
|
|
||||||
},
|
|
||||||
"facing=south,powered=true,powering=false": {
|
|
||||||
"model": "create:block/pulse_repeater_powered"
|
|
||||||
},
|
|
||||||
"facing=west,powered=true,powering=false": {
|
|
||||||
"model": "create:block/pulse_repeater_powered",
|
|
||||||
"y": 90
|
|
||||||
},
|
|
||||||
"facing=east,powered=true,powering=false": {
|
|
||||||
"model": "create:block/pulse_repeater_powered",
|
|
||||||
"y": 270
|
|
||||||
},
|
|
||||||
"facing=north,powered=false,powering=true": {
|
|
||||||
"model": "create:block/pulse_repeater_powering",
|
"model": "create:block/pulse_repeater_powering",
|
||||||
"y": 180
|
"y": 180
|
||||||
},
|
},
|
||||||
"facing=south,powered=false,powering=true": {
|
"facing=south,inverted=true,powered=false,powering=false": {
|
||||||
"model": "create:block/pulse_repeater_powering"
|
"model": "create:block/pulse_repeater_powering"
|
||||||
},
|
},
|
||||||
"facing=west,powered=false,powering=true": {
|
"facing=west,inverted=true,powered=false,powering=false": {
|
||||||
"model": "create:block/pulse_repeater_powering",
|
"model": "create:block/pulse_repeater_powering",
|
||||||
"y": 90
|
"y": 90
|
||||||
},
|
},
|
||||||
"facing=east,powered=false,powering=true": {
|
"facing=east,inverted=true,powered=false,powering=false": {
|
||||||
"model": "create:block/pulse_repeater_powering",
|
"model": "create:block/pulse_repeater_powering",
|
||||||
"y": 270
|
"y": 270
|
||||||
},
|
},
|
||||||
"facing=north,powered=true,powering=true": {
|
"facing=north,inverted=false,powered=true,powering=false": {
|
||||||
|
"model": "create:block/pulse_repeater_powered",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,inverted=false,powered=true,powering=false": {
|
||||||
|
"model": "create:block/pulse_repeater_powered"
|
||||||
|
},
|
||||||
|
"facing=west,inverted=false,powered=true,powering=false": {
|
||||||
|
"model": "create:block/pulse_repeater_powered",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,inverted=false,powered=true,powering=false": {
|
||||||
|
"model": "create:block/pulse_repeater_powered",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,inverted=true,powered=true,powering=false": {
|
||||||
"model": "create:block/pulse_repeater_powered_powering",
|
"model": "create:block/pulse_repeater_powered_powering",
|
||||||
"y": 180
|
"y": 180
|
||||||
},
|
},
|
||||||
"facing=south,powered=true,powering=true": {
|
"facing=south,inverted=true,powered=true,powering=false": {
|
||||||
"model": "create:block/pulse_repeater_powered_powering"
|
"model": "create:block/pulse_repeater_powered_powering"
|
||||||
},
|
},
|
||||||
"facing=west,powered=true,powering=true": {
|
"facing=west,inverted=true,powered=true,powering=false": {
|
||||||
"model": "create:block/pulse_repeater_powered_powering",
|
"model": "create:block/pulse_repeater_powered_powering",
|
||||||
"y": 90
|
"y": 90
|
||||||
},
|
},
|
||||||
"facing=east,powered=true,powering=true": {
|
"facing=east,inverted=true,powered=true,powering=false": {
|
||||||
"model": "create:block/pulse_repeater_powered_powering",
|
"model": "create:block/pulse_repeater_powered_powering",
|
||||||
"y": 270
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,inverted=false,powered=false,powering=true": {
|
||||||
|
"model": "create:block/pulse_repeater_powering",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,inverted=false,powered=false,powering=true": {
|
||||||
|
"model": "create:block/pulse_repeater_powering"
|
||||||
|
},
|
||||||
|
"facing=west,inverted=false,powered=false,powering=true": {
|
||||||
|
"model": "create:block/pulse_repeater_powering",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,inverted=false,powered=false,powering=true": {
|
||||||
|
"model": "create:block/pulse_repeater_powering",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,inverted=true,powered=false,powering=true": {
|
||||||
|
"model": "create:block/diodes/pulse_repeater",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,inverted=true,powered=false,powering=true": {
|
||||||
|
"model": "create:block/diodes/pulse_repeater"
|
||||||
|
},
|
||||||
|
"facing=west,inverted=true,powered=false,powering=true": {
|
||||||
|
"model": "create:block/diodes/pulse_repeater",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,inverted=true,powered=false,powering=true": {
|
||||||
|
"model": "create:block/diodes/pulse_repeater",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,inverted=false,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_repeater_powered_powering",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,inverted=false,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_repeater_powered_powering"
|
||||||
|
},
|
||||||
|
"facing=west,inverted=false,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_repeater_powered_powering",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,inverted=false,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_repeater_powered_powering",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,inverted=true,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_repeater_powered",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,inverted=true,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_repeater_powered"
|
||||||
|
},
|
||||||
|
"facing=west,inverted=true,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_repeater_powered",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,inverted=true,powered=true,powering=true": {
|
||||||
|
"model": "create:block/pulse_repeater_powered",
|
||||||
|
"y": 270
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -189,11 +189,13 @@
|
||||||
"block.create.cyan_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B u\u0250\u028E\u0186",
|
"block.create.cyan_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B u\u0250\u028E\u0186",
|
||||||
"block.create.dark_oak_window": "\u028Dopu\u0131M \u029E\u0250O \u029E\u0279\u0250\u15E1",
|
"block.create.dark_oak_window": "\u028Dopu\u0131M \u029E\u0250O \u029E\u0279\u0250\u15E1",
|
||||||
"block.create.dark_oak_window_pane": "\u01DDu\u0250\u0500 \u028Dopu\u0131M \u029E\u0250O \u029E\u0279\u0250\u15E1",
|
"block.create.dark_oak_window_pane": "\u01DDu\u0250\u0500 \u028Dopu\u0131M \u029E\u0250O \u029E\u0279\u0250\u15E1",
|
||||||
|
"block.create.data_gatherer": "\u0279\u01DD\u0279\u01DD\u0265\u0287\u0250\u2141 \u0250\u0287\u0250\u15E1",
|
||||||
"block.create.deepslate_pillar": "\u0279\u0250\u05DF\u05DF\u0131\u0500 \u01DD\u0287\u0250\u05DFsd\u01DD\u01DD\u15E1",
|
"block.create.deepslate_pillar": "\u0279\u0250\u05DF\u05DF\u0131\u0500 \u01DD\u0287\u0250\u05DFsd\u01DD\u01DD\u15E1",
|
||||||
"block.create.deepslate_zinc_ore": "\u01DD\u0279O \u0254u\u0131Z \u01DD\u0287\u0250\u05DFsd\u01DD\u01DD\u15E1",
|
"block.create.deepslate_zinc_ore": "\u01DD\u0279O \u0254u\u0131Z \u01DD\u0287\u0250\u05DFsd\u01DD\u01DD\u15E1",
|
||||||
"block.create.deployer": "\u0279\u01DD\u028Eo\u05DFd\u01DD\u15E1",
|
"block.create.deployer": "\u0279\u01DD\u028Eo\u05DFd\u01DD\u15E1",
|
||||||
"block.create.depot": "\u0287od\u01DD\u15E1",
|
"block.create.depot": "\u0287od\u01DD\u15E1",
|
||||||
"block.create.diorite_pillar": "\u0279\u0250\u05DF\u05DF\u0131\u0500 \u01DD\u0287\u0131\u0279o\u0131\u15E1",
|
"block.create.diorite_pillar": "\u0279\u0250\u05DF\u05DF\u0131\u0500 \u01DD\u0287\u0131\u0279o\u0131\u15E1",
|
||||||
|
"block.create.display_board": "p\u0279\u0250o\u15FA \u028E\u0250\u05DFds\u0131\u15E1",
|
||||||
"block.create.dripstone_pillar": "\u0279\u0250\u05DF\u05DF\u0131\u0500 \u01DDuo\u0287sd\u0131\u0279\u15E1",
|
"block.create.dripstone_pillar": "\u0279\u0250\u05DF\u05DF\u0131\u0500 \u01DDuo\u0287sd\u0131\u0279\u15E1",
|
||||||
"block.create.encased_chain_drive": "\u01DD\u028C\u0131\u0279\u15E1 u\u0131\u0250\u0265\u0186 p\u01DDs\u0250\u0254u\u018E",
|
"block.create.encased_chain_drive": "\u01DD\u028C\u0131\u0279\u15E1 u\u0131\u0250\u0265\u0186 p\u01DDs\u0250\u0254u\u018E",
|
||||||
"block.create.encased_fan": "u\u0250\u2132 p\u01DDs\u0250\u0254u\u018E",
|
"block.create.encased_fan": "u\u0250\u2132 p\u01DDs\u0250\u0254u\u018E",
|
||||||
|
|
|
@ -192,11 +192,13 @@
|
||||||
"block.create.cyan_valve_handle": "Cyan Valve Handle",
|
"block.create.cyan_valve_handle": "Cyan Valve Handle",
|
||||||
"block.create.dark_oak_window": "Dark Oak Window",
|
"block.create.dark_oak_window": "Dark Oak Window",
|
||||||
"block.create.dark_oak_window_pane": "Dark Oak Window Pane",
|
"block.create.dark_oak_window_pane": "Dark Oak Window Pane",
|
||||||
|
"block.create.data_gatherer": "Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "Deepslate Pillar",
|
"block.create.deepslate_pillar": "Deepslate Pillar",
|
||||||
"block.create.deepslate_zinc_ore": "Deepslate Zinc Ore",
|
"block.create.deepslate_zinc_ore": "Deepslate Zinc Ore",
|
||||||
"block.create.deployer": "Deployer",
|
"block.create.deployer": "Deployer",
|
||||||
"block.create.depot": "Depot",
|
"block.create.depot": "Depot",
|
||||||
"block.create.diorite_pillar": "Diorite Pillar",
|
"block.create.diorite_pillar": "Diorite Pillar",
|
||||||
|
"block.create.display_board": "Display Board",
|
||||||
"block.create.dripstone_pillar": "Dripstone Pillar",
|
"block.create.dripstone_pillar": "Dripstone Pillar",
|
||||||
"block.create.encased_chain_drive": "Encased Chain Drive",
|
"block.create.encased_chain_drive": "Encased Chain Drive",
|
||||||
"block.create.encased_fan": "Encased Fan",
|
"block.create.encased_fan": "Encased Fan",
|
||||||
|
@ -1433,6 +1435,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "Combine Item Names",
|
||||||
|
"create.data_source.count_items": "Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "k",
|
||||||
|
"create.data_source.value_list.million": "m",
|
||||||
|
"create.data_source.player_deaths": "Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "'%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "Time of Day",
|
||||||
|
"create.data_source.stop_watch": "Stopwatch",
|
||||||
|
"create.data_source.time.format": "Time Format",
|
||||||
|
"create.data_source.time.12_hour": "12-hour",
|
||||||
|
"create.data_source.time.24_hour": "24-hour",
|
||||||
|
"create.data_source.accumulate_items": "Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "per Hour",
|
||||||
|
"create.data_source.station_summary": "Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "now",
|
||||||
|
"create.data_source.station_summary.minutes": " min",
|
||||||
|
"create.data_source.station_summary.seconds": "%1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "Line %1$s",
|
||||||
|
"create.data_target.page": "Page %1$s",
|
||||||
|
"create.data_target.single_line": "Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": " ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": " ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": " ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": " ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": " ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "█;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "Hi :)",
|
"create.gui.config.overlay1": "Hi :)",
|
||||||
"create.gui.config.overlay2": "This is a sample overlay",
|
"create.gui.config.overlay2": "This is a sample overlay",
|
||||||
"create.gui.config.overlay3": "Click or drag with your mouse",
|
"create.gui.config.overlay3": "Click or drag with your mouse",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 1439",
|
"_": "Missing Localizations: 1503",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "Türkiser Ventilgriff",
|
"block.create.cyan_valve_handle": "Türkiser Ventilgriff",
|
||||||
"block.create.dark_oak_window": "Schwarzeichenholzfenster",
|
"block.create.dark_oak_window": "Schwarzeichenholzfenster",
|
||||||
"block.create.dark_oak_window_pane": "Schwarzeichenholzfensterscheibe",
|
"block.create.dark_oak_window_pane": "Schwarzeichenholzfensterscheibe",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
||||||
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||||
"block.create.deployer": "Einsatzgerät",
|
"block.create.deployer": "Einsatzgerät",
|
||||||
"block.create.depot": "Depot",
|
"block.create.depot": "Depot",
|
||||||
"block.create.diorite_pillar": "Dioritsäule",
|
"block.create.diorite_pillar": "Dioritsäule",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||||
"block.create.encased_chain_drive": "Ummantelter Kettenriemen",
|
"block.create.encased_chain_drive": "Ummantelter Kettenriemen",
|
||||||
"block.create.encased_fan": "Ummantelter Lüfter",
|
"block.create.encased_fan": "Ummantelter Lüfter",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "Hi :)",
|
"create.gui.config.overlay1": "Hi :)",
|
||||||
"create.gui.config.overlay2": "Dies ist ein Beispiel Overlay",
|
"create.gui.config.overlay2": "Dies ist ein Beispiel Overlay",
|
||||||
"create.gui.config.overlay3": "Klicke oder ziehe mit deiner Maus",
|
"create.gui.config.overlay3": "Klicke oder ziehe mit deiner Maus",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 450",
|
"_": "Missing Localizations: 514",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "Válvula Cian",
|
"block.create.cyan_valve_handle": "Válvula Cian",
|
||||||
"block.create.dark_oak_window": "Ventana de Roble Oscuro",
|
"block.create.dark_oak_window": "Ventana de Roble Oscuro",
|
||||||
"block.create.dark_oak_window_pane": "Panel de Ventana de Roble Oscuro",
|
"block.create.dark_oak_window_pane": "Panel de Ventana de Roble Oscuro",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
||||||
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||||
"block.create.deployer": "Desplegador",
|
"block.create.deployer": "Desplegador",
|
||||||
"block.create.depot": "Depósito",
|
"block.create.depot": "Depósito",
|
||||||
"block.create.diorite_pillar": "Pilar de Diorita",
|
"block.create.diorite_pillar": "Pilar de Diorita",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||||
"block.create.encased_chain_drive": "Conductor en Cadena Encubierto",
|
"block.create.encased_chain_drive": "Conductor en Cadena Encubierto",
|
||||||
"block.create.encased_fan": "Ventilador Encubierto",
|
"block.create.encased_fan": "Ventilador Encubierto",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "Hola :)",
|
"create.gui.config.overlay1": "Hola :)",
|
||||||
"create.gui.config.overlay2": "Este es un overlay de ejemplo",
|
"create.gui.config.overlay2": "Este es un overlay de ejemplo",
|
||||||
"create.gui.config.overlay3": "Haz clic o arrastra con el mouse",
|
"create.gui.config.overlay3": "Haz clic o arrastra con el mouse",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 121",
|
"_": "Missing Localizations: 185",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "Asa de válvula cian",
|
"block.create.cyan_valve_handle": "Asa de válvula cian",
|
||||||
"block.create.dark_oak_window": "Ventana de roble oscuro",
|
"block.create.dark_oak_window": "Ventana de roble oscuro",
|
||||||
"block.create.dark_oak_window_pane": "Panel de ventana de roble oscuro",
|
"block.create.dark_oak_window_pane": "Panel de ventana de roble oscuro",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "Pilar de pizarra profunda",
|
"block.create.deepslate_pillar": "Pilar de pizarra profunda",
|
||||||
"block.create.deepslate_zinc_ore": "Mena de cinc de pizarra profunda",
|
"block.create.deepslate_zinc_ore": "Mena de cinc de pizarra profunda",
|
||||||
"block.create.deployer": "Desplegador",
|
"block.create.deployer": "Desplegador",
|
||||||
"block.create.depot": "Depósito",
|
"block.create.depot": "Depósito",
|
||||||
"block.create.diorite_pillar": "Pilar de diorita",
|
"block.create.diorite_pillar": "Pilar de diorita",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "Pilar de espeleotema",
|
"block.create.dripstone_pillar": "Pilar de espeleotema",
|
||||||
"block.create.encased_chain_drive": "Cadena de transmisión revestida",
|
"block.create.encased_chain_drive": "Cadena de transmisión revestida",
|
||||||
"block.create.encased_fan": "Ventilador revestido",
|
"block.create.encased_fan": "Ventilador revestido",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "Hola :)",
|
"create.gui.config.overlay1": "Hola :)",
|
||||||
"create.gui.config.overlay2": "Esta es una muestra de la superposición",
|
"create.gui.config.overlay2": "Esta es una muestra de la superposición",
|
||||||
"create.gui.config.overlay3": "Haga clic o arrastre con el ratón",
|
"create.gui.config.overlay3": "Haga clic o arrastre con el ratón",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 1701",
|
"_": "Missing Localizations: 1765",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "Vanne cyan",
|
"block.create.cyan_valve_handle": "Vanne cyan",
|
||||||
"block.create.dark_oak_window": "fenêtre en chêne sombre",
|
"block.create.dark_oak_window": "fenêtre en chêne sombre",
|
||||||
"block.create.dark_oak_window_pane": "Vitre en chêne sombre",
|
"block.create.dark_oak_window_pane": "Vitre en chêne sombre",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
||||||
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||||
"block.create.deployer": "Déployeur",
|
"block.create.deployer": "Déployeur",
|
||||||
"block.create.depot": "Dépot",
|
"block.create.depot": "Dépot",
|
||||||
"block.create.diorite_pillar": "UNLOCALIZED: Diorite Pillar",
|
"block.create.diorite_pillar": "UNLOCALIZED: Diorite Pillar",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||||
"block.create.encased_chain_drive": "Chaine de transmission",
|
"block.create.encased_chain_drive": "Chaine de transmission",
|
||||||
"block.create.encased_fan": "Ventilateur enchâssé",
|
"block.create.encased_fan": "Ventilateur enchâssé",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "UNLOCALIZED: Hi :)",
|
"create.gui.config.overlay1": "UNLOCALIZED: Hi :)",
|
||||||
"create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay",
|
"create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay",
|
||||||
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 1390",
|
"_": "Missing Localizations: 1454",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "Maniglia per valvola ciano",
|
"block.create.cyan_valve_handle": "Maniglia per valvola ciano",
|
||||||
"block.create.dark_oak_window": "Finestra di quercia scura",
|
"block.create.dark_oak_window": "Finestra di quercia scura",
|
||||||
"block.create.dark_oak_window_pane": "Pannello di finestra di quercia scura",
|
"block.create.dark_oak_window_pane": "Pannello di finestra di quercia scura",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
||||||
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||||
"block.create.deployer": "Installatore",
|
"block.create.deployer": "Installatore",
|
||||||
"block.create.depot": "Deposito",
|
"block.create.depot": "Deposito",
|
||||||
"block.create.diorite_pillar": "Pilastro di diorite",
|
"block.create.diorite_pillar": "Pilastro di diorite",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||||
"block.create.encased_chain_drive": "Trasmissione a catena incassata",
|
"block.create.encased_chain_drive": "Trasmissione a catena incassata",
|
||||||
"block.create.encased_fan": "Ventilatore incassato",
|
"block.create.encased_fan": "Ventilatore incassato",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "Ciao :)",
|
"create.gui.config.overlay1": "Ciao :)",
|
||||||
"create.gui.config.overlay2": "Questo overlay è di esempio",
|
"create.gui.config.overlay2": "Questo overlay è di esempio",
|
||||||
"create.gui.config.overlay3": "Cliccalo o trascinalo col mouse",
|
"create.gui.config.overlay3": "Cliccalo o trascinalo col mouse",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 116",
|
"_": "Missing Localizations: 180",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "水色のバルブハンドル",
|
"block.create.cyan_valve_handle": "水色のバルブハンドル",
|
||||||
"block.create.dark_oak_window": "ダークオークの窓",
|
"block.create.dark_oak_window": "ダークオークの窓",
|
||||||
"block.create.dark_oak_window_pane": "ダークオークの板窓",
|
"block.create.dark_oak_window_pane": "ダークオークの板窓",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "深層岩の柱",
|
"block.create.deepslate_pillar": "深層岩の柱",
|
||||||
"block.create.deepslate_zinc_ore": "深層亜鉛鉱石",
|
"block.create.deepslate_zinc_ore": "深層亜鉛鉱石",
|
||||||
"block.create.deployer": "デプロイヤー",
|
"block.create.deployer": "デプロイヤー",
|
||||||
"block.create.depot": "デポ",
|
"block.create.depot": "デポ",
|
||||||
"block.create.diorite_pillar": "閃緑岩の柱",
|
"block.create.diorite_pillar": "閃緑岩の柱",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "鍾乳石の柱",
|
"block.create.dripstone_pillar": "鍾乳石の柱",
|
||||||
"block.create.encased_chain_drive": "ケース入りチェーンドライブ",
|
"block.create.encased_chain_drive": "ケース入りチェーンドライブ",
|
||||||
"block.create.encased_fan": "ケース入りファン",
|
"block.create.encased_fan": "ケース入りファン",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "やぁ(・∀・)",
|
"create.gui.config.overlay1": "やぁ(・∀・)",
|
||||||
"create.gui.config.overlay2": "これはオーバーレイのサンプルです",
|
"create.gui.config.overlay2": "これはオーバーレイのサンプルです",
|
||||||
"create.gui.config.overlay3": "マウスでクリックまたはドラッグしてください",
|
"create.gui.config.overlay3": "マウスでクリックまたはドラッグしてください",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 116",
|
"_": "Missing Localizations: 180",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "청록색 밸브 손잡이",
|
"block.create.cyan_valve_handle": "청록색 밸브 손잡이",
|
||||||
"block.create.dark_oak_window": "짙은 참나무 유리창",
|
"block.create.dark_oak_window": "짙은 참나무 유리창",
|
||||||
"block.create.dark_oak_window_pane": "짙은 참나무 유리판",
|
"block.create.dark_oak_window_pane": "짙은 참나무 유리판",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "심층암 기둥",
|
"block.create.deepslate_pillar": "심층암 기둥",
|
||||||
"block.create.deepslate_zinc_ore": "심층암 아연 광석",
|
"block.create.deepslate_zinc_ore": "심층암 아연 광석",
|
||||||
"block.create.deployer": "기계 손",
|
"block.create.deployer": "기계 손",
|
||||||
"block.create.depot": "아이템 거치대",
|
"block.create.depot": "아이템 거치대",
|
||||||
"block.create.diorite_pillar": "섬록암 기둥",
|
"block.create.diorite_pillar": "섬록암 기둥",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "점적석 기둥",
|
"block.create.dripstone_pillar": "점적석 기둥",
|
||||||
"block.create.encased_chain_drive": "체인 드라이브",
|
"block.create.encased_chain_drive": "체인 드라이브",
|
||||||
"block.create.encased_fan": "선풍기",
|
"block.create.encased_fan": "선풍기",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "Hi :)",
|
"create.gui.config.overlay1": "Hi :)",
|
||||||
"create.gui.config.overlay2": "This is a sample overlay",
|
"create.gui.config.overlay2": "This is a sample overlay",
|
||||||
"create.gui.config.overlay3": "Click or drag with your mouse",
|
"create.gui.config.overlay3": "Click or drag with your mouse",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 2054",
|
"_": "Missing Localizations: 2118",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "UNLOCALIZED: Cyan Valve Handle",
|
"block.create.cyan_valve_handle": "UNLOCALIZED: Cyan Valve Handle",
|
||||||
"block.create.dark_oak_window": "UNLOCALIZED: Dark Oak Window",
|
"block.create.dark_oak_window": "UNLOCALIZED: Dark Oak Window",
|
||||||
"block.create.dark_oak_window_pane": "UNLOCALIZED: Dark Oak Window Pane",
|
"block.create.dark_oak_window_pane": "UNLOCALIZED: Dark Oak Window Pane",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
||||||
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||||
"block.create.deployer": "UNLOCALIZED: Deployer",
|
"block.create.deployer": "UNLOCALIZED: Deployer",
|
||||||
"block.create.depot": "UNLOCALIZED: Depot",
|
"block.create.depot": "UNLOCALIZED: Depot",
|
||||||
"block.create.diorite_pillar": "UNLOCALIZED: Diorite Pillar",
|
"block.create.diorite_pillar": "UNLOCALIZED: Diorite Pillar",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||||
"block.create.encased_chain_drive": "UNLOCALIZED: Encased Chain Drive",
|
"block.create.encased_chain_drive": "UNLOCALIZED: Encased Chain Drive",
|
||||||
"block.create.encased_fan": "Omhulsde Ventilator",
|
"block.create.encased_fan": "Omhulsde Ventilator",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "UNLOCALIZED: Hi :)",
|
"create.gui.config.overlay1": "UNLOCALIZED: Hi :)",
|
||||||
"create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay",
|
"create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay",
|
||||||
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 489",
|
"_": "Missing Localizations: 553",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "Błękitne pokrętło",
|
"block.create.cyan_valve_handle": "Błękitne pokrętło",
|
||||||
"block.create.dark_oak_window": "Ciemnodębowe okno",
|
"block.create.dark_oak_window": "Ciemnodębowe okno",
|
||||||
"block.create.dark_oak_window_pane": "Ciemnodębowa szyba okienna",
|
"block.create.dark_oak_window_pane": "Ciemnodębowa szyba okienna",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
||||||
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||||
"block.create.deployer": "Aplikator",
|
"block.create.deployer": "Aplikator",
|
||||||
"block.create.depot": "Składnica",
|
"block.create.depot": "Składnica",
|
||||||
"block.create.diorite_pillar": "Diorytowy filar",
|
"block.create.diorite_pillar": "Diorytowy filar",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||||
"block.create.encased_chain_drive": "Izolowany przekaźnik łańcuchowy",
|
"block.create.encased_chain_drive": "Izolowany przekaźnik łańcuchowy",
|
||||||
"block.create.encased_fan": "Izolowany wiatrak",
|
"block.create.encased_fan": "Izolowany wiatrak",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "Cześć :)",
|
"create.gui.config.overlay1": "Cześć :)",
|
||||||
"create.gui.config.overlay2": "To jest przykładowa nakładka",
|
"create.gui.config.overlay2": "To jest przykładowa nakładka",
|
||||||
"create.gui.config.overlay3": "Kliknij lub przeciągnij myszką",
|
"create.gui.config.overlay3": "Kliknij lub przeciągnij myszką",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 1301",
|
"_": "Missing Localizations: 1365",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "Válvula ciano",
|
"block.create.cyan_valve_handle": "Válvula ciano",
|
||||||
"block.create.dark_oak_window": "Janela de carvalho escuro",
|
"block.create.dark_oak_window": "Janela de carvalho escuro",
|
||||||
"block.create.dark_oak_window_pane": "Vidraça de carvalho escuro",
|
"block.create.dark_oak_window_pane": "Vidraça de carvalho escuro",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "Pilar de ardósia",
|
"block.create.deepslate_pillar": "Pilar de ardósia",
|
||||||
"block.create.deepslate_zinc_ore": "Minério de zinco de ardósia",
|
"block.create.deepslate_zinc_ore": "Minério de zinco de ardósia",
|
||||||
"block.create.deployer": "Implantador",
|
"block.create.deployer": "Implantador",
|
||||||
"block.create.depot": "Depósito",
|
"block.create.depot": "Depósito",
|
||||||
"block.create.diorite_pillar": "Pilar de diorito",
|
"block.create.diorite_pillar": "Pilar de diorito",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "Pilar de espeleotema",
|
"block.create.dripstone_pillar": "Pilar de espeleotema",
|
||||||
"block.create.encased_chain_drive": "Correia Revestida",
|
"block.create.encased_chain_drive": "Correia Revestida",
|
||||||
"block.create.encased_fan": "Ventilador Revestida",
|
"block.create.encased_fan": "Ventilador Revestida",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "UNLOCALIZED: Hi :)",
|
"create.gui.config.overlay1": "UNLOCALIZED: Hi :)",
|
||||||
"create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay",
|
"create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay",
|
||||||
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 1673",
|
"_": "Missing Localizations: 1737",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "Manopla de válvula ciano",
|
"block.create.cyan_valve_handle": "Manopla de válvula ciano",
|
||||||
"block.create.dark_oak_window": "UNLOCALIZED: Dark Oak Window",
|
"block.create.dark_oak_window": "UNLOCALIZED: Dark Oak Window",
|
||||||
"block.create.dark_oak_window_pane": "UNLOCALIZED: Dark Oak Window Pane",
|
"block.create.dark_oak_window_pane": "UNLOCALIZED: Dark Oak Window Pane",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
||||||
"block.create.deepslate_zinc_ore": "Deepslate zinc ore",
|
"block.create.deepslate_zinc_ore": "Deepslate zinc ore",
|
||||||
"block.create.deployer": "Implantador",
|
"block.create.deployer": "Implantador",
|
||||||
"block.create.depot": "Depósito",
|
"block.create.depot": "Depósito",
|
||||||
"block.create.diorite_pillar": "UNLOCALIZED: Diorite Pillar",
|
"block.create.diorite_pillar": "UNLOCALIZED: Diorite Pillar",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||||
"block.create.encased_chain_drive": "Correia Revestida",
|
"block.create.encased_chain_drive": "Correia Revestida",
|
||||||
"block.create.encased_fan": "Ventilador Revestida",
|
"block.create.encased_fan": "Ventilador Revestida",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "UNLOCALIZED: Hi :)",
|
"create.gui.config.overlay1": "UNLOCALIZED: Hi :)",
|
||||||
"create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay",
|
"create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay",
|
||||||
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 494",
|
"_": "Missing Localizations: 558",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "Бирюзовый ручной вентиль",
|
"block.create.cyan_valve_handle": "Бирюзовый ручной вентиль",
|
||||||
"block.create.dark_oak_window": "Окно из тёмного дуба",
|
"block.create.dark_oak_window": "Окно из тёмного дуба",
|
||||||
"block.create.dark_oak_window_pane": "Панель из окна из тёмного дуб",
|
"block.create.dark_oak_window_pane": "Панель из окна из тёмного дуб",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
||||||
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||||
"block.create.deployer": "Автономный активатор",
|
"block.create.deployer": "Автономный активатор",
|
||||||
"block.create.depot": "Депо",
|
"block.create.depot": "Депо",
|
||||||
"block.create.diorite_pillar": "Диоритовая колонна",
|
"block.create.diorite_pillar": "Диоритовая колонна",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||||
"block.create.encased_chain_drive": "Цепной привод в корпусе",
|
"block.create.encased_chain_drive": "Цепной привод в корпусе",
|
||||||
"block.create.encased_fan": "Вентилятор в корпусе",
|
"block.create.encased_fan": "Вентилятор в корпусе",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "Привет :)",
|
"create.gui.config.overlay1": "Привет :)",
|
||||||
"create.gui.config.overlay2": "Это образец оверлея",
|
"create.gui.config.overlay2": "Это образец оверлея",
|
||||||
"create.gui.config.overlay3": "Кликни и тащи с помощью мыши",
|
"create.gui.config.overlay3": "Кликни и тащи с помощью мыши",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 116",
|
"_": "Missing Localizations: 180",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "青色阀门手轮",
|
"block.create.cyan_valve_handle": "青色阀门手轮",
|
||||||
"block.create.dark_oak_window": "深色橡木窗户",
|
"block.create.dark_oak_window": "深色橡木窗户",
|
||||||
"block.create.dark_oak_window_pane": "深色橡木窗户板",
|
"block.create.dark_oak_window_pane": "深色橡木窗户板",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "深板岩柱",
|
"block.create.deepslate_pillar": "深板岩柱",
|
||||||
"block.create.deepslate_zinc_ore": "深层锌矿石",
|
"block.create.deepslate_zinc_ore": "深层锌矿石",
|
||||||
"block.create.deployer": "机械手",
|
"block.create.deployer": "机械手",
|
||||||
"block.create.depot": "置物台",
|
"block.create.depot": "置物台",
|
||||||
"block.create.diorite_pillar": "闪长岩柱",
|
"block.create.diorite_pillar": "闪长岩柱",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "滴水石柱",
|
"block.create.dripstone_pillar": "滴水石柱",
|
||||||
"block.create.encased_chain_drive": "链式传动箱",
|
"block.create.encased_chain_drive": "链式传动箱",
|
||||||
"block.create.encased_fan": "鼓风机",
|
"block.create.encased_fan": "鼓风机",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "Hi :)",
|
"create.gui.config.overlay1": "Hi :)",
|
||||||
"create.gui.config.overlay2": "这是一个实例层",
|
"create.gui.config.overlay2": "这是一个实例层",
|
||||||
"create.gui.config.overlay3": "点击拖拽你的鼠标",
|
"create.gui.config.overlay3": "点击拖拽你的鼠标",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_": "Missing Localizations: 508",
|
"_": "Missing Localizations: 572",
|
||||||
|
|
||||||
"_": "->------------------------] Game Elements [------------------------<-",
|
"_": "->------------------------] Game Elements [------------------------<-",
|
||||||
|
|
||||||
|
@ -193,11 +193,13 @@
|
||||||
"block.create.cyan_valve_handle": "藍綠色閥門開關",
|
"block.create.cyan_valve_handle": "藍綠色閥門開關",
|
||||||
"block.create.dark_oak_window": "黑橡木窗戶",
|
"block.create.dark_oak_window": "黑橡木窗戶",
|
||||||
"block.create.dark_oak_window_pane": "黑橡木窗戶片",
|
"block.create.dark_oak_window_pane": "黑橡木窗戶片",
|
||||||
|
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||||
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
||||||
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||||
"block.create.deployer": "機器手",
|
"block.create.deployer": "機器手",
|
||||||
"block.create.depot": "置物臺",
|
"block.create.depot": "置物臺",
|
||||||
"block.create.diorite_pillar": "豎紋閃長岩",
|
"block.create.diorite_pillar": "豎紋閃長岩",
|
||||||
|
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||||
"block.create.encased_chain_drive": "鏈式傳動箱",
|
"block.create.encased_chain_drive": "鏈式傳動箱",
|
||||||
"block.create.encased_fan": "鼓風機",
|
"block.create.encased_fan": "鼓風機",
|
||||||
|
@ -1434,6 +1436,72 @@
|
||||||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||||
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
"create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s",
|
||||||
|
|
||||||
|
"create.data_gatherer.set": "UNLOCALIZED: Targeted position selected",
|
||||||
|
"create.data_gatherer.success": "UNLOCALIZED: Successfully bound to targeted position",
|
||||||
|
"create.data_gatherer.clear": "UNLOCALIZED: Cleared position selection",
|
||||||
|
"create.data_gatherer.too_far": "UNLOCALIZED: Targeted position is too far from here",
|
||||||
|
"create.data_gatherer.invalid": "UNLOCALIZED: Gatherer has no valid target, try placing it again",
|
||||||
|
"create.data_gatherer.title": "UNLOCALIZED: Data Gatherer",
|
||||||
|
"create.data_gatherer.no_source": "UNLOCALIZED: Not a Data Source",
|
||||||
|
"create.data_gatherer.no_target": "UNLOCALIZED: Not a Data Target",
|
||||||
|
"create.data_gatherer.reading_from": "UNLOCALIZED: Read from:",
|
||||||
|
"create.data_gatherer.writing_to": "UNLOCALIZED: Send to:",
|
||||||
|
"create.data_gatherer.attached_side": "UNLOCALIZED: Block on attached side",
|
||||||
|
"create.data_gatherer.targeted_location": "UNLOCALIZED: Block in targeted location",
|
||||||
|
"create.data_gatherer.view_compatible": "UNLOCALIZED: Click to view all Compatible",
|
||||||
|
"create.data_gatherer.information_type": "UNLOCALIZED: Type of Information",
|
||||||
|
"create.data_gatherer.display_on": "UNLOCALIZED: Write data to:",
|
||||||
|
"create.data_gatherer.display_on_multiline": "UNLOCALIZED: Start writing at:",
|
||||||
|
|
||||||
|
"create.data_source.label": "UNLOCALIZED: Attached Label",
|
||||||
|
"create.data_source.combine_item_names": "UNLOCALIZED: Combine Item Names",
|
||||||
|
"create.data_source.count_items": "UNLOCALIZED: Amount of matching Items",
|
||||||
|
"create.data_source.list_items": "UNLOCALIZED: List matching Items",
|
||||||
|
"create.data_source.nixie_tube": "UNLOCALIZED: Copy Nixie Tubes",
|
||||||
|
"create.data_source.fill_level": "UNLOCALIZED: Container Fill Level",
|
||||||
|
"create.data_source.fill_level.display": "UNLOCALIZED: Display Format",
|
||||||
|
"create.data_source.fill_level.percent": "UNLOCALIZED: Percent",
|
||||||
|
"create.data_source.fill_level.progress_bar": "UNLOCALIZED: Progress Bar",
|
||||||
|
"create.data_source.value_list.display": "UNLOCALIZED: Value Display",
|
||||||
|
"create.data_source.value_list.shortened": "UNLOCALIZED: Shortened",
|
||||||
|
"create.data_source.value_list.full_number": "UNLOCALIZED: Full Number",
|
||||||
|
"create.data_source.value_list.thousand": "UNLOCALIZED: k",
|
||||||
|
"create.data_source.value_list.million": "UNLOCALIZED: m",
|
||||||
|
"create.data_source.player_deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.scoreboard": "UNLOCALIZED: Scoreboard",
|
||||||
|
"create.data_source.scoreboard.objective": "UNLOCALIZED: Objective ID",
|
||||||
|
"create.data_source.scoreboard.objective_not_found": "UNLOCALIZED: '%1$s' not found",
|
||||||
|
"create.data_source.scoreboard.objective.deaths": "UNLOCALIZED: Player Deaths",
|
||||||
|
"create.data_source.time_of_day": "UNLOCALIZED: Time of Day",
|
||||||
|
"create.data_source.stop_watch": "UNLOCALIZED: Stopwatch",
|
||||||
|
"create.data_source.time.format": "UNLOCALIZED: Time Format",
|
||||||
|
"create.data_source.time.12_hour": "UNLOCALIZED: 12-hour",
|
||||||
|
"create.data_source.time.24_hour": "UNLOCALIZED: 24-hour",
|
||||||
|
"create.data_source.accumulate_items": "UNLOCALIZED: Accumulate Item Count",
|
||||||
|
"create.data_source.item_throughput": "UNLOCALIZED: Item Throughput",
|
||||||
|
"create.data_source.item_throughput.interval": "UNLOCALIZED: Interval",
|
||||||
|
"create.data_source.item_throughput.interval.second": "UNLOCALIZED: per Second",
|
||||||
|
"create.data_source.item_throughput.interval.minute": "UNLOCALIZED: per Minute",
|
||||||
|
"create.data_source.item_throughput.interval.hour": "UNLOCALIZED: per Hour",
|
||||||
|
"create.data_source.station_summary": "UNLOCALIZED: Train Station Summary",
|
||||||
|
"create.data_source.station_summary.filter": "UNLOCALIZED: Station name filter",
|
||||||
|
"create.data_source.station_summary.train_name_column": "UNLOCALIZED: Train column size",
|
||||||
|
"create.data_source.station_summary.platform_column": "UNLOCALIZED: Platform column size",
|
||||||
|
"create.data_source.station_summary.now": "UNLOCALIZED: now",
|
||||||
|
"create.data_source.station_summary.minutes": "UNLOCALIZED: min",
|
||||||
|
"create.data_source.station_summary.seconds": "UNLOCALIZED: %1$ss",
|
||||||
|
|
||||||
|
"create.data_target.line": "UNLOCALIZED: Line %1$s",
|
||||||
|
"create.data_target.page": "UNLOCALIZED: Page %1$s",
|
||||||
|
"create.data_target.single_line": "UNLOCALIZED: Single Line",
|
||||||
|
|
||||||
|
"create.flap_display.cycles.alphabet": "UNLOCALIZED: ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z",
|
||||||
|
"create.flap_display.cycles.numeric": "UNLOCALIZED: ;0;1;2;3;4;5;6;7;8;9",
|
||||||
|
"create.flap_display.cycles.arrival_time": "UNLOCALIZED: ; min;now;15s;30s;45s",
|
||||||
|
"create.flap_display.cycles.shortened_numbers": "UNLOCALIZED: ;K;M",
|
||||||
|
"create.flap_display.cycles.instant": "UNLOCALIZED: ; ",
|
||||||
|
"create.flap_display.cycles.pixel": "UNLOCALIZED: █;▒",
|
||||||
|
|
||||||
"create.gui.config.overlay1": "嗨 :)",
|
"create.gui.config.overlay1": "嗨 :)",
|
||||||
"create.gui.config.overlay2": "這是一個實例層",
|
"create.gui.config.overlay2": "這是一個實例層",
|
||||||
"create.gui.config.overlay3": "點擊拖拽你的滑鼠",
|
"create.gui.config.overlay3": "點擊拖拽你的滑鼠",
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"parent": "create:block/data_gatherer/block"
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"parent": "create:block/display_board/item"
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"type": "minecraft:block",
|
||||||
|
"pools": [
|
||||||
|
{
|
||||||
|
"rolls": 1.0,
|
||||||
|
"bonus_rolls": 0.0,
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:item",
|
||||||
|
"name": "create:data_gatherer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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:display_board"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"condition": "minecraft:survives_explosion"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -121,6 +121,7 @@
|
||||||
"create:content_observer",
|
"create:content_observer",
|
||||||
"create:stockpile_switch",
|
"create:stockpile_switch",
|
||||||
"create:creative_crate",
|
"create:creative_crate",
|
||||||
|
"create:display_board",
|
||||||
"create:nixie_tube",
|
"create:nixie_tube",
|
||||||
"create:white_nixie_tube",
|
"create:white_nixie_tube",
|
||||||
"create:magenta_nixie_tube",
|
"create:magenta_nixie_tube",
|
||||||
|
|
|
@ -111,49 +111,34 @@ public class AllBlockPartials {
|
||||||
COPPER_BACKTANK_SHAFT = block("copper_backtank/block_shaft_input"),
|
COPPER_BACKTANK_SHAFT = block("copper_backtank/block_shaft_input"),
|
||||||
COPPER_BACKTANK_COGS = block("copper_backtank/block_cogs"),
|
COPPER_BACKTANK_COGS = block("copper_backtank/block_cogs"),
|
||||||
|
|
||||||
TRACK_SEGMENT_LEFT = block("track/segment_left"),
|
TRACK_SEGMENT_LEFT = block("track/segment_left"), TRACK_SEGMENT_RIGHT = block("track/segment_right"),
|
||||||
TRACK_SEGMENT_RIGHT = block("track/segment_right"),
|
TRACK_TIE = block("track/tie"), GIRDER_SEGMENT_TOP = block("metal_girder/segment_top"),
|
||||||
TRACK_TIE = block("track/tie"),
|
|
||||||
GIRDER_SEGMENT_TOP = block("metal_girder/segment_top"),
|
|
||||||
GIRDER_SEGMENT_MIDDLE = block("metal_girder/segment_middle"),
|
GIRDER_SEGMENT_MIDDLE = block("metal_girder/segment_middle"),
|
||||||
GIRDER_SEGMENT_BOTTOM = block("metal_girder/segment_bottom"),
|
GIRDER_SEGMENT_BOTTOM = block("metal_girder/segment_bottom"),
|
||||||
|
|
||||||
TRACK_STATION_OVERLAY = block("track_overlay/station"),
|
TRACK_STATION_OVERLAY = block("track_overlay/station"), TRACK_SIGNAL_OVERLAY = block("track_overlay/signal"),
|
||||||
TRACK_SIGNAL_OVERLAY = block("track_overlay/signal"),
|
|
||||||
TRACK_ASSEMBLING_OVERLAY = block("track_overlay/assembling"),
|
TRACK_ASSEMBLING_OVERLAY = block("track_overlay/assembling"),
|
||||||
TRACK_SIGNAL_DUAL_OVERLAY = block("track_overlay/signal_dual"),
|
TRACK_SIGNAL_DUAL_OVERLAY = block("track_overlay/signal_dual"),
|
||||||
|
|
||||||
BOGEY_FRAME = block("track/bogey/bogey_frame"),
|
BOGEY_FRAME = block("track/bogey/bogey_frame"), SMALL_BOGEY_WHEELS = block("track/bogey/bogey_wheel"),
|
||||||
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_PIN = block("track/bogey/bogey_drive_wheel_pin"),
|
BOGEY_DRIVE = block("track/bogey/bogey_drive"), LARGE_BOGEY_WHEELS = block("track/bogey/bogey_drive_wheel"),
|
||||||
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_HEAD = block("track/bogey/coupling_head"),
|
||||||
TRAIN_COUPLING_CABLE = block("track/bogey/coupling_cable"),
|
TRAIN_COUPLING_CABLE = block("track/bogey/coupling_cable"),
|
||||||
|
|
||||||
TRAIN_CONTROLS_COVER = block("controls/train/cover"),
|
TRAIN_CONTROLS_COVER = block("controls/train/cover"), TRAIN_CONTROLS_LEVER = block("controls/train/lever"),
|
||||||
TRAIN_CONTROLS_LEVER = block("controls/train/lever"),
|
|
||||||
|
|
||||||
ENGINE_PISTON = block("steam_engine/piston"),
|
ENGINE_PISTON = block("steam_engine/piston"), ENGINE_LINKAGE = block("steam_engine/linkage"),
|
||||||
ENGINE_LINKAGE = block("steam_engine/linkage"),
|
ENGINE_CONNECTOR = block("steam_engine/shaft_connector"), BOILER_GAUGE = block("steam_engine/gauge"),
|
||||||
ENGINE_CONNECTOR = block("steam_engine/shaft_connector"),
|
|
||||||
BOILER_GAUGE = block("steam_engine/gauge"),
|
|
||||||
|
|
||||||
SIGNAL_ON = block("track_signal/indicator_on"),
|
SIGNAL_ON = block("track_signal/indicator_on"), SIGNAL_OFF = block("track_signal/indicator_off"),
|
||||||
SIGNAL_OFF = block("track_signal/indicator_off"),
|
|
||||||
|
|
||||||
SIGNAL_PANEL = block("track_signal/panel"),
|
SIGNAL_PANEL = block("track_signal/panel"), SIGNAL_WHITE_CUBE = block("track_signal/white_cube"),
|
||||||
SIGNAL_WHITE_CUBE = block("track_signal/white_cube"),
|
SIGNAL_WHITE_GLOW = block("track_signal/white_glow"), SIGNAL_WHITE = block("track_signal/white_tube"),
|
||||||
SIGNAL_WHITE_GLOW = block("track_signal/white_glow"),
|
SIGNAL_RED_CUBE = block("track_signal/red_cube"), SIGNAL_RED_GLOW = block("track_signal/red_glow"),
|
||||||
SIGNAL_WHITE = block("track_signal/white_tube"),
|
SIGNAL_RED = block("track_signal/red_tube"), SIGNAL_YELLOW_CUBE = block("track_signal/yellow_cube"),
|
||||||
SIGNAL_RED_CUBE = block("track_signal/red_cube"),
|
SIGNAL_YELLOW_GLOW = block("track_signal/yellow_glow"), SIGNAL_YELLOW = block("track_signal/yellow_tube"),
|
||||||
SIGNAL_RED_GLOW = block("track_signal/red_glow"),
|
|
||||||
SIGNAL_RED = block("track_signal/red_tube"),
|
|
||||||
SIGNAL_YELLOW_CUBE = block("track_signal/yellow_cube"),
|
|
||||||
SIGNAL_YELLOW_GLOW = block("track_signal/yellow_glow"),
|
|
||||||
SIGNAL_YELLOW = block("track_signal/yellow_tube"),
|
|
||||||
|
|
||||||
CRAFTING_BLUEPRINT_1x1 = entity("crafting_blueprint_small"),
|
CRAFTING_BLUEPRINT_1x1 = entity("crafting_blueprint_small"),
|
||||||
CRAFTING_BLUEPRINT_2x2 = entity("crafting_blueprint_medium"),
|
CRAFTING_BLUEPRINT_2x2 = entity("crafting_blueprint_medium"),
|
||||||
|
@ -169,8 +154,7 @@ public class AllBlockPartials {
|
||||||
|
|
||||||
public static final Map<BlazeBurnerBlock.HeatLevel, PartialModel> BLAZES =
|
public static final Map<BlazeBurnerBlock.HeatLevel, PartialModel> BLAZES =
|
||||||
new EnumMap<>(BlazeBurnerBlock.HeatLevel.class);
|
new EnumMap<>(BlazeBurnerBlock.HeatLevel.class);
|
||||||
public static final Map<Direction, PartialModel> METAL_GIRDER_BRACKETS =
|
public static final Map<Direction, PartialModel> METAL_GIRDER_BRACKETS = new EnumMap<>(Direction.class);
|
||||||
new EnumMap<>(Direction.class);
|
|
||||||
public static final Map<DyeColor, PartialModel> TOOLBOX_LIDS = new EnumMap<>(DyeColor.class);
|
public static final Map<DyeColor, PartialModel> TOOLBOX_LIDS = new EnumMap<>(DyeColor.class);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import static com.simibubi.create.AllTags.axeOrPickaxe;
|
||||||
import static com.simibubi.create.AllTags.pickaxeOnly;
|
import static com.simibubi.create.AllTags.pickaxeOnly;
|
||||||
import static com.simibubi.create.AllTags.tagBlockAndItem;
|
import static com.simibubi.create.AllTags.tagBlockAndItem;
|
||||||
import static com.simibubi.create.content.AllSections.SCHEMATICS;
|
import static com.simibubi.create.content.AllSections.SCHEMATICS;
|
||||||
|
import static com.simibubi.create.content.logistics.block.data.AllDataGathererBehaviours.assignDataBehaviour;
|
||||||
import static com.simibubi.create.foundation.data.BlockStateGen.axisBlock;
|
import static com.simibubi.create.foundation.data.BlockStateGen.axisBlock;
|
||||||
import static com.simibubi.create.foundation.data.CreateRegistrate.connectedTextures;
|
import static com.simibubi.create.foundation.data.CreateRegistrate.connectedTextures;
|
||||||
import static com.simibubi.create.foundation.data.ModelGen.customItemModel;
|
import static com.simibubi.create.foundation.data.ModelGen.customItemModel;
|
||||||
|
@ -142,6 +143,18 @@ import com.simibubi.create.content.logistics.block.chute.ChuteBlock;
|
||||||
import com.simibubi.create.content.logistics.block.chute.ChuteGenerator;
|
import com.simibubi.create.content.logistics.block.chute.ChuteGenerator;
|
||||||
import com.simibubi.create.content.logistics.block.chute.ChuteItem;
|
import com.simibubi.create.content.logistics.block.chute.ChuteItem;
|
||||||
import com.simibubi.create.content.logistics.block.chute.SmartChuteBlock;
|
import com.simibubi.create.content.logistics.block.chute.SmartChuteBlock;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererBlock;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererBlockItem;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.AccumulatedItemCountDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.FillLevelDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.ItemCountDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.ItemListDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.ItemNameDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.ItemThoughputDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.StationSummaryDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.StopWatchDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.TimeOfDayDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.FlapDisplayDataTarget;
|
||||||
import com.simibubi.create.content.logistics.block.depot.DepotBlock;
|
import com.simibubi.create.content.logistics.block.depot.DepotBlock;
|
||||||
import com.simibubi.create.content.logistics.block.depot.EjectorBlock;
|
import com.simibubi.create.content.logistics.block.depot.EjectorBlock;
|
||||||
import com.simibubi.create.content.logistics.block.depot.EjectorItem;
|
import com.simibubi.create.content.logistics.block.depot.EjectorItem;
|
||||||
|
@ -175,6 +188,7 @@ 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.ItemVaultCTBehaviour;
|
||||||
import com.simibubi.create.content.logistics.block.vault.ItemVaultItem;
|
import com.simibubi.create.content.logistics.block.vault.ItemVaultItem;
|
||||||
import com.simibubi.create.content.logistics.item.LecternControllerBlock;
|
import com.simibubi.create.content.logistics.item.LecternControllerBlock;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBlock;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlock;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlock;
|
||||||
|
@ -426,6 +440,7 @@ public class AllBlocks {
|
||||||
.transform(axeOrPickaxe())
|
.transform(axeOrPickaxe())
|
||||||
.blockstate(new BeltGenerator()::generate)
|
.blockstate(new BeltGenerator()::generate)
|
||||||
.transform(BlockStressDefaults.setImpact(0))
|
.transform(BlockStressDefaults.setImpact(0))
|
||||||
|
.onRegister(assignDataBehaviour(new ItemNameDataSource(), "combine_item_names"))
|
||||||
.onRegister(CreateRegistrate.blockModel(() -> BeltModel::new))
|
.onRegister(CreateRegistrate.blockModel(() -> BeltModel::new))
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
|
@ -495,6 +510,8 @@ public class AllBlocks {
|
||||||
REGISTRATE.block("cuckoo_clock", CuckooClockBlock::regular)
|
REGISTRATE.block("cuckoo_clock", CuckooClockBlock::regular)
|
||||||
.transform(axeOrPickaxe())
|
.transform(axeOrPickaxe())
|
||||||
.transform(BuilderTransformers.cuckooClock())
|
.transform(BuilderTransformers.cuckooClock())
|
||||||
|
.onRegister(assignDataBehaviour(new TimeOfDayDataSource(), "time_of_day"))
|
||||||
|
.onRegister(assignDataBehaviour(new StopWatchDataSource(), "stop_watch"))
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final BlockEntry<CuckooClockBlock> MYSTERIOUS_CUCKOO_CLOCK =
|
public static final BlockEntry<CuckooClockBlock> MYSTERIOUS_CUCKOO_CLOCK =
|
||||||
|
@ -528,7 +545,9 @@ public class AllBlocks {
|
||||||
public static final BlockEntry<CrushingWheelControllerBlock> CRUSHING_WHEEL_CONTROLLER =
|
public static final BlockEntry<CrushingWheelControllerBlock> CRUSHING_WHEEL_CONTROLLER =
|
||||||
REGISTRATE.block("crushing_wheel_controller", CrushingWheelControllerBlock::new)
|
REGISTRATE.block("crushing_wheel_controller", CrushingWheelControllerBlock::new)
|
||||||
.initialProperties(SharedProperties.CRUSHING_WHEEL_CONTROLLER_MATERIAL)
|
.initialProperties(SharedProperties.CRUSHING_WHEEL_CONTROLLER_MATERIAL)
|
||||||
.properties(p -> p.noOcclusion().noDrops().air())
|
.properties(p -> p.noOcclusion()
|
||||||
|
.noDrops()
|
||||||
|
.air())
|
||||||
.blockstate((c, p) -> p.getVariantBuilder(c.get())
|
.blockstate((c, p) -> p.getVariantBuilder(c.get())
|
||||||
.forAllStatesExcept(state -> ConfiguredModel.builder()
|
.forAllStatesExcept(state -> ConfiguredModel.builder()
|
||||||
.modelFile(p.models()
|
.modelFile(p.models()
|
||||||
|
@ -606,6 +625,7 @@ public class AllBlocks {
|
||||||
.initialProperties(SharedProperties::stone)
|
.initialProperties(SharedProperties::stone)
|
||||||
.transform(axeOrPickaxe())
|
.transform(axeOrPickaxe())
|
||||||
.blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p)))
|
.blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p)))
|
||||||
|
.onRegister(assignDataBehaviour(new ItemNameDataSource(), "combine_item_names"))
|
||||||
.item()
|
.item()
|
||||||
.transform(customItemModel("_", "block"))
|
.transform(customItemModel("_", "block"))
|
||||||
.register();
|
.register();
|
||||||
|
@ -617,6 +637,7 @@ public class AllBlocks {
|
||||||
.transform(axeOrPickaxe())
|
.transform(axeOrPickaxe())
|
||||||
.blockstate((c, p) -> p.horizontalBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p), 180))
|
.blockstate((c, p) -> p.horizontalBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p), 180))
|
||||||
.transform(BlockStressDefaults.setImpact(2.0))
|
.transform(BlockStressDefaults.setImpact(2.0))
|
||||||
|
.onRegister(assignDataBehaviour(new ItemNameDataSource(), "combine_item_names"))
|
||||||
.item(EjectorItem::new)
|
.item(EjectorItem::new)
|
||||||
.transform(customItemModel())
|
.transform(customItemModel())
|
||||||
.register();
|
.register();
|
||||||
|
@ -1330,6 +1351,7 @@ public class AllBlocks {
|
||||||
.blockstate((c, p) -> p.horizontalBlock(c.get(),
|
.blockstate((c, p) -> p.horizontalBlock(c.get(),
|
||||||
s -> s.getValue(StationBlock.ASSEMBLING) ? AssetLookup.partialBaseModel(c, p, "assembling")
|
s -> s.getValue(StationBlock.ASSEMBLING) ? AssetLookup.partialBaseModel(c, p, "assembling")
|
||||||
: AssetLookup.partialBaseModel(c, p)))
|
: AssetLookup.partialBaseModel(c, p)))
|
||||||
|
.onRegister(assignDataBehaviour(new StationSummaryDataSource(), "station_summary"))
|
||||||
.lang("Train Station")
|
.lang("Train Station")
|
||||||
.item(TrackTargetingBlockItem::new)
|
.item(TrackTargetingBlockItem::new)
|
||||||
.transform(customItemModel("_", "block"))
|
.transform(customItemModel("_", "block"))
|
||||||
|
@ -1430,11 +1452,13 @@ public class AllBlocks {
|
||||||
public static final BlockEntry<BeltTunnelBlock> ANDESITE_TUNNEL =
|
public static final BlockEntry<BeltTunnelBlock> ANDESITE_TUNNEL =
|
||||||
REGISTRATE.block("andesite_tunnel", BeltTunnelBlock::new)
|
REGISTRATE.block("andesite_tunnel", BeltTunnelBlock::new)
|
||||||
.transform(BuilderTransformers.beltTunnel("andesite", new ResourceLocation("block/polished_andesite")))
|
.transform(BuilderTransformers.beltTunnel("andesite", new ResourceLocation("block/polished_andesite")))
|
||||||
|
.onRegister(assignDataBehaviour(new AccumulatedItemCountDataSource(), "accumulate_items"))
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final BlockEntry<BrassTunnelBlock> BRASS_TUNNEL =
|
public static final BlockEntry<BrassTunnelBlock> BRASS_TUNNEL =
|
||||||
REGISTRATE.block("brass_tunnel", BrassTunnelBlock::new)
|
REGISTRATE.block("brass_tunnel", BrassTunnelBlock::new)
|
||||||
.transform(BuilderTransformers.beltTunnel("brass", Create.asResource("block/brass_block")))
|
.transform(BuilderTransformers.beltTunnel("brass", Create.asResource("block/brass_block")))
|
||||||
|
.onRegister(assignDataBehaviour(new ItemThoughputDataSource(), "item_throughput"))
|
||||||
.onRegister(connectedTextures(BrassTunnelCTBehaviour::new))
|
.onRegister(connectedTextures(BrassTunnelCTBehaviour::new))
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
|
@ -1443,6 +1467,8 @@ public class AllBlocks {
|
||||||
.initialProperties(SharedProperties::stone)
|
.initialProperties(SharedProperties::stone)
|
||||||
.transform(axeOrPickaxe())
|
.transform(axeOrPickaxe())
|
||||||
.blockstate((c, p) -> p.horizontalBlock(c.get(), AssetLookup.forPowered(c, p)))
|
.blockstate((c, p) -> p.horizontalBlock(c.get(), AssetLookup.forPowered(c, p)))
|
||||||
|
.onRegister(assignDataBehaviour(new ItemCountDataSource(), "count_items"))
|
||||||
|
.onRegister(assignDataBehaviour(new ItemListDataSource(), "list_items"))
|
||||||
.item()
|
.item()
|
||||||
.transform(customItemModel("_", "block"))
|
.transform(customItemModel("_", "block"))
|
||||||
.register();
|
.register();
|
||||||
|
@ -1453,6 +1479,7 @@ public class AllBlocks {
|
||||||
.transform(axeOrPickaxe())
|
.transform(axeOrPickaxe())
|
||||||
.blockstate((c, p) -> p.horizontalBlock(c.get(),
|
.blockstate((c, p) -> p.horizontalBlock(c.get(),
|
||||||
AssetLookup.withIndicator(c, p, $ -> AssetLookup.standardModel(c, p), StockpileSwitchBlock.INDICATOR)))
|
AssetLookup.withIndicator(c, p, $ -> AssetLookup.standardModel(c, p), StockpileSwitchBlock.INDICATOR)))
|
||||||
|
.onRegister(assignDataBehaviour(new FillLevelDataSource(), "fill_level"))
|
||||||
.simpleItem()
|
.simpleItem()
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
|
@ -1462,6 +1489,28 @@ public class AllBlocks {
|
||||||
.tag(AllBlockTags.SAFE_NBT.tag)
|
.tag(AllBlockTags.SAFE_NBT.tag)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
|
public static final BlockEntry<DataGathererBlock> DATA_GATHERER =
|
||||||
|
REGISTRATE.block("data_gatherer", DataGathererBlock::new)
|
||||||
|
.initialProperties(SharedProperties::softMetal)
|
||||||
|
.addLayer(() -> RenderType::translucent)
|
||||||
|
.blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.forPowered(c, p)))
|
||||||
|
.item(DataGathererBlockItem::new)
|
||||||
|
.transform(customItemModel("_", "block"))
|
||||||
|
.register();
|
||||||
|
|
||||||
|
public static final BlockEntry<FlapDisplayBlock> FLAP_DISPLAY =
|
||||||
|
REGISTRATE.block("display_board", FlapDisplayBlock::new)
|
||||||
|
.initialProperties(SharedProperties::softMetal)
|
||||||
|
.addLayer(() -> RenderType::cutoutMipped)
|
||||||
|
.transform(pickaxeOnly())
|
||||||
|
.transform(BlockStressDefaults.setImpact(0))
|
||||||
|
.blockstate((c, p) -> p.horizontalBlock(c.get(), AssetLookup.partialBaseModel(c, p)))
|
||||||
|
.onRegister(assignDataBehaviour(new FlapDisplayDataTarget()))
|
||||||
|
.lang("Display Board")
|
||||||
|
.item()
|
||||||
|
.transform(customItemModel())
|
||||||
|
.register();
|
||||||
|
|
||||||
public static final BlockEntry<NixieTubeBlock> ORANGE_NIXIE_TUBE =
|
public static final BlockEntry<NixieTubeBlock> ORANGE_NIXIE_TUBE =
|
||||||
REGISTRATE.block("nixie_tube", p -> new NixieTubeBlock(p, DyeColor.ORANGE))
|
REGISTRATE.block("nixie_tube", p -> new NixieTubeBlock(p, DyeColor.ORANGE))
|
||||||
.initialProperties(SharedProperties::softMetal)
|
.initialProperties(SharedProperties::softMetal)
|
||||||
|
|
|
@ -130,6 +130,11 @@ public class AllShapes {
|
||||||
NIXIE_TUBE_WALL = shape(5, 9, 0, 11, 15, 12).add(5, 1, 0, 11, 7, 12)
|
NIXIE_TUBE_WALL = shape(5, 9, 0, 11, 15, 12).add(5, 1, 0, 11, 7, 12)
|
||||||
.forHorizontal(Direction.SOUTH),
|
.forHorizontal(Direction.SOUTH),
|
||||||
|
|
||||||
|
FLAP_DISPLAY = shape(0, 0, 3, 16, 16, 13).forHorizontal(Direction.SOUTH),
|
||||||
|
|
||||||
|
DATA_GATHERER = shape(1, 0, 1, 15, 6, 15).add(3, 5, 3, 13, 9, 13)
|
||||||
|
.forDirectional(),
|
||||||
|
|
||||||
STEAM_ENGINE = shape(1, 0, 1, 15, 3, 15).add(3, 0, 3, 13, 15, 13)
|
STEAM_ENGINE = shape(1, 0, 1, 15, 3, 15).add(3, 0, 3, 13, 15, 13)
|
||||||
.add(1, 5, 4, 15, 13, 12)
|
.add(1, 5, 4, 15, 13, 12)
|
||||||
.forHorizontalAxis(),
|
.forHorizontalAxis(),
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.simibubi.create;
|
package com.simibubi.create;
|
||||||
|
|
||||||
|
import static com.simibubi.create.content.logistics.block.data.AllDataGathererBehaviours.assignDataBehaviourTE;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.base.CutoutRotatingInstance;
|
import com.simibubi.create.content.contraptions.base.CutoutRotatingInstance;
|
||||||
import com.simibubi.create.content.contraptions.base.HalfShaftInstance;
|
import com.simibubi.create.content.contraptions.base.HalfShaftInstance;
|
||||||
import com.simibubi.create.content.contraptions.base.HorizontalHalfShaftInstance;
|
import com.simibubi.create.content.contraptions.base.HorizontalHalfShaftInstance;
|
||||||
|
@ -143,6 +145,9 @@ import com.simibubi.create.content.logistics.block.chute.ChuteRenderer;
|
||||||
import com.simibubi.create.content.logistics.block.chute.ChuteTileEntity;
|
import com.simibubi.create.content.logistics.block.chute.ChuteTileEntity;
|
||||||
import com.simibubi.create.content.logistics.block.chute.SmartChuteRenderer;
|
import com.simibubi.create.content.logistics.block.chute.SmartChuteRenderer;
|
||||||
import com.simibubi.create.content.logistics.block.chute.SmartChuteTileEntity;
|
import com.simibubi.create.content.logistics.block.chute.SmartChuteTileEntity;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererTileEntity;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.NixieTubeDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.NixieTubeDataTarget;
|
||||||
import com.simibubi.create.content.logistics.block.depot.DepotRenderer;
|
import com.simibubi.create.content.logistics.block.depot.DepotRenderer;
|
||||||
import com.simibubi.create.content.logistics.block.depot.DepotTileEntity;
|
import com.simibubi.create.content.logistics.block.depot.DepotTileEntity;
|
||||||
import com.simibubi.create.content.logistics.block.depot.EjectorInstance;
|
import com.simibubi.create.content.logistics.block.depot.EjectorInstance;
|
||||||
|
@ -171,6 +176,8 @@ import com.simibubi.create.content.logistics.block.vault.ItemVaultTileEntity;
|
||||||
import com.simibubi.create.content.logistics.item.LecternControllerRenderer;
|
import com.simibubi.create.content.logistics.item.LecternControllerRenderer;
|
||||||
import com.simibubi.create.content.logistics.item.LecternControllerTileEntity;
|
import com.simibubi.create.content.logistics.item.LecternControllerTileEntity;
|
||||||
import com.simibubi.create.content.logistics.trains.IBogeyTileEntityRenderer;
|
import com.simibubi.create.content.logistics.trains.IBogeyTileEntityRenderer;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayRenderer;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalRenderer;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalRenderer;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationRenderer;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationRenderer;
|
||||||
|
@ -503,7 +510,8 @@ public class AllTileEntities {
|
||||||
.renderer(() -> PortableStorageInterfaceRenderer::new)
|
.renderer(() -> PortableStorageInterfaceRenderer::new)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final BlockEntityEntry<PortableFluidInterfaceTileEntity> PORTABLE_FLUID_INTERFACE = Create.registrate()
|
public static final BlockEntityEntry<PortableFluidInterfaceTileEntity> PORTABLE_FLUID_INTERFACE =
|
||||||
|
Create.registrate()
|
||||||
.tileEntity("portable_fluid_interface", PortableFluidInterfaceTileEntity::new)
|
.tileEntity("portable_fluid_interface", PortableFluidInterfaceTileEntity::new)
|
||||||
.instance(() -> PSIInstance::new)
|
.instance(() -> PSIInstance::new)
|
||||||
.validBlocks(AllBlocks.PORTABLE_FLUID_INTERFACE)
|
.validBlocks(AllBlocks.PORTABLE_FLUID_INTERFACE)
|
||||||
|
@ -658,6 +666,13 @@ public class AllTileEntities {
|
||||||
.validBlocks(AllBlocks.ORANGE_NIXIE_TUBE)
|
.validBlocks(AllBlocks.ORANGE_NIXIE_TUBE)
|
||||||
.validBlocks(AllBlocks.NIXIE_TUBES.toArray())
|
.validBlocks(AllBlocks.NIXIE_TUBES.toArray())
|
||||||
.renderer(() -> NixieTubeRenderer::new)
|
.renderer(() -> NixieTubeRenderer::new)
|
||||||
|
.onRegister(assignDataBehaviourTE(new NixieTubeDataTarget()))
|
||||||
|
.onRegister(assignDataBehaviourTE(new NixieTubeDataSource()))
|
||||||
|
.register();
|
||||||
|
|
||||||
|
public static final BlockEntityEntry<DataGathererTileEntity> DATA_GATHERER = Create.registrate()
|
||||||
|
.tileEntity("data_gatherer", DataGathererTileEntity::new)
|
||||||
|
.validBlocks(AllBlocks.DATA_GATHERER)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final BlockEntityEntry<StockpileSwitchTileEntity> STOCKPILE_SWITCH = Create.registrate()
|
public static final BlockEntityEntry<StockpileSwitchTileEntity> STOCKPILE_SWITCH = Create.registrate()
|
||||||
|
@ -706,16 +721,14 @@ public class AllTileEntities {
|
||||||
.renderer(() -> BrassDiodeRenderer::new)
|
.renderer(() -> BrassDiodeRenderer::new)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final BlockEntityEntry<PulseRepeaterTileEntity> PULSE_REPEATER =
|
public static final BlockEntityEntry<PulseRepeaterTileEntity> PULSE_REPEATER = Create.registrate()
|
||||||
Create.registrate()
|
|
||||||
.tileEntity("pulse_repeater", PulseRepeaterTileEntity::new)
|
.tileEntity("pulse_repeater", PulseRepeaterTileEntity::new)
|
||||||
.instance(() -> BrassDiodeInstance::new, false)
|
.instance(() -> BrassDiodeInstance::new, false)
|
||||||
.validBlocks(AllBlocks.PULSE_REPEATER)
|
.validBlocks(AllBlocks.PULSE_REPEATER)
|
||||||
.renderer(() -> BrassDiodeRenderer::new)
|
.renderer(() -> BrassDiodeRenderer::new)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final BlockEntityEntry<LecternControllerTileEntity> LECTERN_CONTROLLER =
|
public static final BlockEntityEntry<LecternControllerTileEntity> LECTERN_CONTROLLER = Create.registrate()
|
||||||
Create.registrate()
|
|
||||||
.tileEntity("lectern_controller", LecternControllerTileEntity::new)
|
.tileEntity("lectern_controller", LecternControllerTileEntity::new)
|
||||||
.validBlocks(AllBlocks.LECTERN_CONTROLLER)
|
.validBlocks(AllBlocks.LECTERN_CONTROLLER)
|
||||||
.renderer(() -> LecternControllerRenderer::new)
|
.renderer(() -> LecternControllerRenderer::new)
|
||||||
|
@ -767,6 +780,13 @@ public class AllTileEntities {
|
||||||
.validBlocks(AllBlocks.TRACK_STATION)
|
.validBlocks(AllBlocks.TRACK_STATION)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
|
public static final BlockEntityEntry<FlapDisplayTileEntity> FLAP_DISPLAY = Create.registrate()
|
||||||
|
.tileEntity("flap_display", FlapDisplayTileEntity::new)
|
||||||
|
.instance(() -> MechanicalCrafterInstance::new)
|
||||||
|
.renderer(() -> FlapDisplayRenderer::new)
|
||||||
|
.validBlocks(AllBlocks.FLAP_DISPLAY)
|
||||||
|
.register();
|
||||||
|
|
||||||
public static final BlockEntityEntry<SignalTileEntity> TRACK_SIGNAL = Create.registrate()
|
public static final BlockEntityEntry<SignalTileEntity> TRACK_SIGNAL = Create.registrate()
|
||||||
.tileEntity("track_signal", SignalTileEntity::new)
|
.tileEntity("track_signal", SignalTileEntity::new)
|
||||||
.renderer(() -> SignalRenderer::new)
|
.renderer(() -> SignalRenderer::new)
|
||||||
|
|
|
@ -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.contraptions.components.flywheel.engine.FurnaceEngineInteractions;
|
||||||
import com.simibubi.create.content.curiosities.weapons.BuiltinPotatoProjectileTypes;
|
import com.simibubi.create.content.curiosities.weapons.BuiltinPotatoProjectileTypes;
|
||||||
import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler;
|
import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.AllDataGathererBehaviours;
|
||||||
import com.simibubi.create.content.logistics.trains.GlobalRailwayManager;
|
import com.simibubi.create.content.logistics.trains.GlobalRailwayManager;
|
||||||
import com.simibubi.create.content.palettes.AllPaletteBlocks;
|
import com.simibubi.create.content.palettes.AllPaletteBlocks;
|
||||||
import com.simibubi.create.content.palettes.PalettesItemGroup;
|
import com.simibubi.create.content.palettes.PalettesItemGroup;
|
||||||
|
@ -96,6 +97,7 @@ public class Create {
|
||||||
AllEntityTypes.register();
|
AllEntityTypes.register();
|
||||||
AllTileEntities.register();
|
AllTileEntities.register();
|
||||||
AllMovementBehaviours.register();
|
AllMovementBehaviours.register();
|
||||||
|
AllDataGathererBehaviours.register();
|
||||||
AllInteractionBehaviours.register();
|
AllInteractionBehaviours.register();
|
||||||
AllWorldFeatures.register();
|
AllWorldFeatures.register();
|
||||||
AllEnchantments.register();
|
AllEnchantments.register();
|
||||||
|
|
|
@ -3,61 +3,53 @@ package com.simibubi.create.content.contraptions.components.press;
|
||||||
import static com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult.HOLD;
|
import static com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult.HOLD;
|
||||||
import static com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult.PASS;
|
import static com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult.PASS;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity.Mode;
|
import com.simibubi.create.content.contraptions.components.press.PressingBehaviour.Mode;
|
||||||
import com.simibubi.create.content.contraptions.processing.InWorldProcessing;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
|
import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||||
import com.simibubi.create.foundation.advancement.AllTriggers;
|
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult;
|
import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
|
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult;
|
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult;
|
||||||
|
|
||||||
import net.minecraftforge.items.ItemHandlerHelper;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
public class BeltPressingCallbacks {
|
public class BeltPressingCallbacks {
|
||||||
|
|
||||||
static ProcessingResult onItemReceived(TransportedItemStack transported,
|
static ProcessingResult onItemReceived(TransportedItemStack transported,
|
||||||
TransportedItemStackHandlerBehaviour handler, MechanicalPressTileEntity press) {
|
TransportedItemStackHandlerBehaviour handler, PressingBehaviour behaviour) {
|
||||||
if (press.getSpeed() == 0)
|
if (behaviour.specifics.getKineticSpeed() == 0)
|
||||||
return PASS;
|
return PASS;
|
||||||
if (press.running)
|
if (behaviour.running)
|
||||||
return HOLD;
|
return HOLD;
|
||||||
if (!press.getRecipe(transported.stack)
|
if (!behaviour.specifics.tryProcessOnBelt(transported, null, true))
|
||||||
.isPresent())
|
|
||||||
return PASS;
|
return PASS;
|
||||||
|
|
||||||
press.start(Mode.BELT);
|
behaviour.start(Mode.BELT);
|
||||||
return HOLD;
|
return HOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ProcessingResult whenItemHeld(TransportedItemStack transported, TransportedItemStackHandlerBehaviour handler,
|
static ProcessingResult whenItemHeld(TransportedItemStack transported, TransportedItemStackHandlerBehaviour handler,
|
||||||
MechanicalPressTileEntity pressTe) {
|
PressingBehaviour behaviour) {
|
||||||
|
|
||||||
if (pressTe.getSpeed() == 0)
|
if (behaviour.specifics.getKineticSpeed() == 0)
|
||||||
return PASS;
|
return PASS;
|
||||||
if (!pressTe.running)
|
if (!behaviour.running)
|
||||||
return PASS;
|
return PASS;
|
||||||
if (pressTe.runningTicks != MechanicalPressTileEntity.CYCLE / 2)
|
if (behaviour.runningTicks != PressingBehaviour.CYCLE / 2)
|
||||||
return HOLD;
|
return HOLD;
|
||||||
|
|
||||||
Optional<PressingRecipe> recipe = pressTe.getRecipe(transported.stack);
|
behaviour.particleItems.clear();
|
||||||
pressTe.pressedItems.clear();
|
ArrayList<ItemStack> results = new ArrayList<>();
|
||||||
pressTe.pressedItems.add(transported.stack);
|
if (!behaviour.specifics.tryProcessOnBelt(transported, results, false))
|
||||||
|
|
||||||
if (!recipe.isPresent())
|
|
||||||
return PASS;
|
return PASS;
|
||||||
|
|
||||||
boolean bulk = MechanicalPressTileEntity.canProcessInBulk() || transported.stack.getCount() == 1;
|
boolean bulk = behaviour.specifics.canProcessInBulk() || transported.stack.getCount() == 1;
|
||||||
|
|
||||||
List<TransportedItemStack> collect = InWorldProcessing
|
List<TransportedItemStack> collect = results.stream()
|
||||||
.applyRecipeOn(bulk ? transported.stack : ItemHandlerHelper.copyStackWithSize(transported.stack, 1),
|
|
||||||
recipe.get())
|
|
||||||
.stream()
|
|
||||||
.map(stack -> {
|
.map(stack -> {
|
||||||
TransportedItemStack copy = transported.copy();
|
TransportedItemStack copy = transported.copy();
|
||||||
boolean centered = BeltHelper.isItemUpright(stack);
|
boolean centered = BeltHelper.isItemUpright(stack);
|
||||||
|
@ -84,8 +76,7 @@ public class BeltPressingCallbacks {
|
||||||
handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(collect, left));
|
handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(collect, left));
|
||||||
}
|
}
|
||||||
|
|
||||||
AllTriggers.triggerForNearbyPlayers(AllTriggers.BONK, pressTe.getLevel(), pressTe.getBlockPos(), 4);
|
behaviour.tileEntity.sendData();
|
||||||
pressTe.sendData();
|
|
||||||
return HOLD;
|
return HOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,16 @@ public class MechanicalPressRenderer extends KineticTileEntityRenderer {
|
||||||
int light, int overlay) {
|
int light, int overlay) {
|
||||||
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
|
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
|
||||||
|
|
||||||
if (Backend.canUseInstancing(te.getLevel())) return;
|
if (Backend.canUseInstancing(te.getLevel()))
|
||||||
|
return;
|
||||||
|
|
||||||
BlockState blockState = te.getBlockState();
|
BlockState blockState = te.getBlockState();
|
||||||
float renderedHeadOffset = ((MechanicalPressTileEntity) te).getRenderedHeadOffset(partialTicks);
|
PressingBehaviour pressingBehaviour = ((MechanicalPressTileEntity) te).getPressingBehaviour();
|
||||||
|
float renderedHeadOffset =
|
||||||
|
pressingBehaviour.getRenderedHeadOffset(partialTicks) * pressingBehaviour.mode.headOffset;
|
||||||
|
|
||||||
SuperByteBuffer headRender = CachedBufferer.partialFacing(AllBlockPartials.MECHANICAL_PRESS_HEAD, blockState, blockState.getValue(HORIZONTAL_FACING));
|
SuperByteBuffer headRender = CachedBufferer.partialFacing(AllBlockPartials.MECHANICAL_PRESS_HEAD, blockState,
|
||||||
|
blockState.getValue(HORIZONTAL_FACING));
|
||||||
headRender.translate(0, -renderedHeadOffset, 0)
|
headRender.translate(0, -renderedHeadOffset, 0)
|
||||||
.light(light)
|
.light(light)
|
||||||
.renderInto(ms, buffer.getBuffer(RenderType.solid()));
|
.renderInto(ms, buffer.getBuffer(RenderType.solid()));
|
||||||
|
|
|
@ -1,44 +1,34 @@
|
||||||
package com.simibubi.create.content.contraptions.components.press;
|
package com.simibubi.create.content.contraptions.components.press;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
|
||||||
import com.simibubi.create.AllRecipeTypes;
|
import com.simibubi.create.AllRecipeTypes;
|
||||||
import com.simibubi.create.AllSoundEvents;
|
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCraftingRecipe;
|
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCraftingRecipe;
|
||||||
|
import com.simibubi.create.content.contraptions.components.press.PressingBehaviour.Mode;
|
||||||
|
import com.simibubi.create.content.contraptions.components.press.PressingBehaviour.PressingBehaviourSpecifics;
|
||||||
import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe;
|
import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe;
|
||||||
import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity;
|
import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
|
import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.processing.InWorldProcessing;
|
import com.simibubi.create.content.contraptions.processing.InWorldProcessing;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||||
import com.simibubi.create.foundation.advancement.AllTriggers;
|
import com.simibubi.create.foundation.advancement.AllTriggers;
|
||||||
import com.simibubi.create.foundation.advancement.ITriggerable;
|
import com.simibubi.create.foundation.advancement.ITriggerable;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
import com.simibubi.create.foundation.item.ItemHelper;
|
import com.simibubi.create.foundation.item.ItemHelper;
|
||||||
import com.simibubi.create.foundation.item.SmartInventory;
|
import com.simibubi.create.foundation.item.SmartInventory;
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour;
|
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
|
|
||||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.NonNullList;
|
import net.minecraft.core.NonNullList;
|
||||||
import net.minecraft.core.particles.ItemParticleOption;
|
|
||||||
import net.minecraft.core.particles.ParticleTypes;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.nbt.Tag;
|
|
||||||
import net.minecraft.util.Mth;
|
|
||||||
import net.minecraft.world.Container;
|
import net.minecraft.world.Container;
|
||||||
import net.minecraft.world.entity.Entity;
|
|
||||||
import net.minecraft.world.entity.item.ItemEntity;
|
import net.minecraft.world.entity.item.ItemEntity;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.crafting.CraftingRecipe;
|
import net.minecraft.world.item.crafting.CraftingRecipe;
|
||||||
import net.minecraft.world.item.crafting.Ingredient;
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
import net.minecraft.world.item.crafting.Recipe;
|
import net.minecraft.world.item.crafting.Recipe;
|
||||||
import net.minecraft.world.level.block.SoundType;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.phys.AABB;
|
import net.minecraft.world.phys.AABB;
|
||||||
|
@ -47,64 +37,14 @@ import net.minecraftforge.items.ItemHandlerHelper;
|
||||||
import net.minecraftforge.items.ItemStackHandler;
|
import net.minecraftforge.items.ItemStackHandler;
|
||||||
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||||
|
|
||||||
public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
|
public class MechanicalPressTileEntity extends BasinOperatingTileEntity implements PressingBehaviourSpecifics {
|
||||||
|
|
||||||
private static final Object compressingRecipesKey = new Object();
|
private static final Object compressingRecipesKey = new Object();
|
||||||
public List<ItemStack> pressedItems = new ArrayList<>();
|
|
||||||
public BeltProcessingBehaviour processingBehaviour;
|
|
||||||
|
|
||||||
public int prevRunningTicks;
|
public PressingBehaviour pressingBehaviour;
|
||||||
public int runningTicks;
|
|
||||||
static final int CYCLE = 240;
|
|
||||||
static final int ENTITY_SCAN = 10;
|
|
||||||
int entityScanCooldown;
|
|
||||||
|
|
||||||
public boolean running;
|
|
||||||
public Mode mode;
|
|
||||||
public boolean finished;
|
|
||||||
|
|
||||||
public MechanicalPressTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
public MechanicalPressTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||||
super(type, pos, state);
|
super(type, pos, state);
|
||||||
mode = Mode.WORLD;
|
|
||||||
entityScanCooldown = ENTITY_SCAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
|
||||||
super.addBehaviours(behaviours);
|
|
||||||
processingBehaviour =
|
|
||||||
new BeltProcessingBehaviour(this).whenItemEnters((s, i) -> BeltPressingCallbacks.onItemReceived(s, i, this))
|
|
||||||
.whileItemHeld((s, i) -> BeltPressingCallbacks.whenItemHeld(s, i, this));
|
|
||||||
behaviours.add(processingBehaviour);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void read(CompoundTag compound, boolean clientPacket) {
|
|
||||||
running = compound.getBoolean("Running");
|
|
||||||
mode = Mode.values()[compound.getInt("Mode")];
|
|
||||||
finished = compound.getBoolean("Finished");
|
|
||||||
prevRunningTicks = runningTicks = compound.getInt("Ticks");
|
|
||||||
super.read(compound, clientPacket);
|
|
||||||
|
|
||||||
if (clientPacket) {
|
|
||||||
NBTHelper.iterateCompoundList(compound.getList("ParticleItems", Tag.TAG_COMPOUND),
|
|
||||||
c -> pressedItems.add(ItemStack.of(c)));
|
|
||||||
spawnParticles();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(CompoundTag compound, boolean clientPacket) {
|
|
||||||
compound.putBoolean("Running", running);
|
|
||||||
compound.putInt("Mode", mode.ordinal());
|
|
||||||
compound.putBoolean("Finished", finished);
|
|
||||||
compound.putInt("Ticks", runningTicks);
|
|
||||||
super.write(compound, clientPacket);
|
|
||||||
|
|
||||||
if (clientPacket) {
|
|
||||||
compound.put("ParticleItems", NBTHelper.writeCompoundList(pressedItems, ItemStack::serializeNBT));
|
|
||||||
pressedItems.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -113,119 +53,21 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
|
||||||
.expandTowards(0, 1, 0);
|
.expandTowards(0, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getRenderedHeadOffset(float partialTicks) {
|
@Override
|
||||||
if (!running)
|
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
||||||
return 0;
|
super.addBehaviours(behaviours);
|
||||||
int runningTicks = Math.abs(this.runningTicks);
|
pressingBehaviour = new PressingBehaviour(this);
|
||||||
float ticks = Mth.lerp(partialTicks, prevRunningTicks, runningTicks);
|
behaviours.add(pressingBehaviour);
|
||||||
if (runningTicks < (CYCLE * 2) / 3)
|
|
||||||
return (float) Mth.clamp(Math.pow(ticks / CYCLE * 2, 3), 0, 1) * mode.headOffset;
|
|
||||||
return Mth.clamp((CYCLE - ticks) / CYCLE * 3, 0, 1) * mode.headOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(Mode mode) {
|
public PressingBehaviour getPressingBehaviour() {
|
||||||
this.mode = mode;
|
return pressingBehaviour;
|
||||||
running = true;
|
|
||||||
prevRunningTicks = 0;
|
|
||||||
runningTicks = 0;
|
|
||||||
pressedItems.clear();
|
|
||||||
sendData();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean inWorld() {
|
|
||||||
return mode == Mode.WORLD;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean onBasin() {
|
|
||||||
return mode == Mode.BASIN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public boolean tryProcessInBasin(boolean simulate) {
|
||||||
super.tick();
|
|
||||||
|
|
||||||
if (!running || level == null) {
|
|
||||||
if (hasLevel() && !level.isClientSide) {
|
|
||||||
|
|
||||||
if (getSpeed() == 0)
|
|
||||||
return;
|
|
||||||
if (entityScanCooldown > 0)
|
|
||||||
entityScanCooldown--;
|
|
||||||
if (entityScanCooldown <= 0) {
|
|
||||||
entityScanCooldown = ENTITY_SCAN;
|
|
||||||
if (TileEntityBehaviour.get(level, worldPosition.below(2), TransportedItemStackHandlerBehaviour.TYPE) != null)
|
|
||||||
return;
|
|
||||||
if (AllBlocks.BASIN.has(level.getBlockState(worldPosition.below(2))))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class,
|
|
||||||
new AABB(worldPosition.below()).deflate(.125f))) {
|
|
||||||
if (!itemEntity.isAlive() || !itemEntity.isOnGround())
|
|
||||||
continue;
|
|
||||||
ItemStack stack = itemEntity.getItem();
|
|
||||||
Optional<PressingRecipe> recipe = getRecipe(stack);
|
|
||||||
if (!recipe.isPresent())
|
|
||||||
continue;
|
|
||||||
start(Mode.WORLD);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level.isClientSide && runningTicks == -CYCLE / 2) {
|
|
||||||
prevRunningTicks = CYCLE / 2;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runningTicks == CYCLE / 2 && getSpeed() != 0) {
|
|
||||||
if (inWorld())
|
|
||||||
applyPressingInWorld();
|
|
||||||
if (onBasin())
|
|
||||||
applyCompactingOnBasin();
|
|
||||||
|
|
||||||
if (level.getBlockState(worldPosition.below(2)).getSoundType() == SoundType.WOOL)
|
|
||||||
AllSoundEvents.MECHANICAL_PRESS_ACTIVATION_ON_BELT.playOnServer(level, worldPosition);
|
|
||||||
else
|
|
||||||
AllSoundEvents.MECHANICAL_PRESS_ACTIVATION.playOnServer(level, worldPosition, .5f, .75f + (Math.abs(getSpeed()) / 1024f));
|
|
||||||
|
|
||||||
if (!level.isClientSide)
|
|
||||||
sendData();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!level.isClientSide && runningTicks > CYCLE) {
|
|
||||||
finished = true;
|
|
||||||
running = false;
|
|
||||||
|
|
||||||
if (onBasin() && matchBasinRecipe(currentRecipe)
|
|
||||||
&& getBasin().filter(BasinTileEntity::canContinueProcessing)
|
|
||||||
.isPresent())
|
|
||||||
startProcessingBasin();
|
|
||||||
else
|
|
||||||
basinChecker.scheduleUpdate();
|
|
||||||
|
|
||||||
pressedItems.clear();
|
|
||||||
sendData();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
prevRunningTicks = runningTicks;
|
|
||||||
runningTicks += getRunningTickSpeed();
|
|
||||||
if (prevRunningTicks < CYCLE / 2 && runningTicks >= CYCLE / 2) {
|
|
||||||
runningTicks = CYCLE / 2;
|
|
||||||
// Pause the ticks until a packet is received
|
|
||||||
if (level.isClientSide && !isVirtual())
|
|
||||||
runningTicks = -(CYCLE / 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void applyCompactingOnBasin() {
|
|
||||||
if (level.isClientSide)
|
|
||||||
return;
|
|
||||||
pressedItems.clear();
|
|
||||||
applyBasinRecipe();
|
applyBasinRecipe();
|
||||||
|
|
||||||
Optional<BasinTileEntity> basin = getBasin();
|
Optional<BasinTileEntity> basin = getBasin();
|
||||||
if (basin.isPresent()) {
|
if (basin.isPresent()) {
|
||||||
SmartInventory inputs = basin.get()
|
SmartInventory inputs = basin.get()
|
||||||
|
@ -234,32 +76,24 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
|
||||||
ItemStack stackInSlot = inputs.getItem(slot);
|
ItemStack stackInSlot = inputs.getItem(slot);
|
||||||
if (stackInSlot.isEmpty())
|
if (stackInSlot.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
pressedItems.add(stackInSlot);
|
pressingBehaviour.particleItems.add(stackInSlot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendData();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void applyPressingInWorld() {
|
return true;
|
||||||
AABB bb = new AABB(worldPosition.below(1));
|
}
|
||||||
boolean bulk = canProcessInBulk();
|
|
||||||
pressedItems.clear();
|
@Override
|
||||||
if (level.isClientSide)
|
public boolean tryProcessInWorld(ItemEntity itemEntity, boolean simulate) {
|
||||||
return;
|
|
||||||
for (Entity entity : level.getEntities(null, bb)) {
|
|
||||||
if (!(entity instanceof ItemEntity))
|
|
||||||
continue;
|
|
||||||
if (!entity.isAlive() || !entity.isOnGround())
|
|
||||||
continue;
|
|
||||||
ItemEntity itemEntity = (ItemEntity) entity;
|
|
||||||
ItemStack item = itemEntity.getItem();
|
ItemStack item = itemEntity.getItem();
|
||||||
pressedItems.add(item);
|
|
||||||
sendData();
|
|
||||||
Optional<PressingRecipe> recipe = getRecipe(item);
|
Optional<PressingRecipe> recipe = getRecipe(item);
|
||||||
if (!recipe.isPresent())
|
if (!recipe.isPresent())
|
||||||
continue;
|
return false;
|
||||||
|
if (simulate)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (bulk || item.getCount() == 1) {
|
pressingBehaviour.particleItems.add(item);
|
||||||
|
if (canProcessInBulk() || item.getCount() == 1) {
|
||||||
InWorldProcessing.applyRecipeOn(itemEntity, recipe.get());
|
InWorldProcessing.applyRecipeOn(itemEntity, recipe.get());
|
||||||
} else {
|
} else {
|
||||||
for (ItemStack result : InWorldProcessing.applyRecipeOn(ItemHandlerHelper.copyStackWithSize(item, 1),
|
for (ItemStack result : InWorldProcessing.applyRecipeOn(ItemHandlerHelper.copyStackWithSize(item, 1),
|
||||||
|
@ -274,59 +108,31 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
AllTriggers.triggerForNearbyPlayers(AllTriggers.BONK, level, worldPosition, 4);
|
AllTriggers.triggerForNearbyPlayers(AllTriggers.BONK, level, worldPosition, 4);
|
||||||
entityScanCooldown = 0;
|
return true;
|
||||||
|
|
||||||
if (!bulk)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canProcessInBulk() {
|
@Override
|
||||||
return AllConfigs.SERVER.recipes.bulkPressing.get();
|
public boolean tryProcessOnBelt(TransportedItemStack input, List<ItemStack> outputList, boolean simulate) {
|
||||||
|
Optional<PressingRecipe> recipe = getRecipe(input.stack);
|
||||||
|
if (!recipe.isPresent())
|
||||||
|
return false;
|
||||||
|
if (simulate)
|
||||||
|
return true;
|
||||||
|
pressingBehaviour.particleItems.add(input.stack);
|
||||||
|
outputList.addAll(InWorldProcessing.applyRecipeOn(
|
||||||
|
canProcessInBulk() ? input.stack : ItemHandlerHelper.copyStackWithSize(input.stack, 1), recipe.get()));
|
||||||
|
AllTriggers.triggerForNearbyPlayers(AllTriggers.BONK, level, worldPosition, 4);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRunningTickSpeed() {
|
@Override
|
||||||
if (getSpeed() == 0)
|
public void onPressingCompleted() {
|
||||||
return 0;
|
if (pressingBehaviour.onBasin() && matchBasinRecipe(currentRecipe)
|
||||||
return (int) Mth.lerp(Mth.clamp(Math.abs(getSpeed()) / 512f, 0, 1), 1, 60);
|
&& getBasin().filter(BasinTileEntity::canContinueProcessing)
|
||||||
}
|
.isPresent())
|
||||||
|
startProcessingBasin();
|
||||||
protected void spawnParticles() {
|
else
|
||||||
if (pressedItems.isEmpty())
|
basinChecker.scheduleUpdate();
|
||||||
return;
|
|
||||||
|
|
||||||
if (mode == Mode.BASIN)
|
|
||||||
pressedItems.forEach(stack -> makeCompactingParticleEffect(VecHelper.getCenterOf(worldPosition.below(2)), stack));
|
|
||||||
if (mode == Mode.BELT)
|
|
||||||
pressedItems.forEach(stack -> makePressingParticleEffect(VecHelper.getCenterOf(worldPosition.below(2))
|
|
||||||
.add(0, 8 / 16f, 0), stack));
|
|
||||||
if (mode == Mode.WORLD)
|
|
||||||
pressedItems.forEach(stack -> makePressingParticleEffect(VecHelper.getCenterOf(worldPosition.below(1))
|
|
||||||
.add(0, -1 / 4f, 0), stack));
|
|
||||||
|
|
||||||
pressedItems.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void makePressingParticleEffect(Vec3 pos, ItemStack stack) {
|
|
||||||
if (level == null || !level.isClientSide)
|
|
||||||
return;
|
|
||||||
for (int i = 0; i < 20; i++) {
|
|
||||||
Vec3 motion = VecHelper.offsetRandomly(Vec3.ZERO, level.random, .125f)
|
|
||||||
.multiply(1, 0, 1);
|
|
||||||
level.addParticle(new ItemParticleOption(ParticleTypes.ITEM, stack), pos.x, pos.y - .25f, pos.z, motion.x,
|
|
||||||
motion.y + .125f, motion.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void makeCompactingParticleEffect(Vec3 pos, ItemStack stack) {
|
|
||||||
if (level == null || !level.isClientSide)
|
|
||||||
return;
|
|
||||||
for (int i = 0; i < 20; i++) {
|
|
||||||
Vec3 motion = VecHelper.offsetRandomly(Vec3.ZERO, level.random, .175f)
|
|
||||||
.multiply(1, 0, 1);
|
|
||||||
level.addParticle(new ItemParticleOption(ParticleTypes.ITEM, stack), pos.x, pos.y, pos.z, motion.x,
|
|
||||||
motion.y + .25f, motion.z);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final RecipeWrapper pressingInv = new RecipeWrapper(new ItemStackHandler(1));
|
private static final RecipeWrapper pressingInv = new RecipeWrapper(new ItemStackHandler(1));
|
||||||
|
@ -350,35 +156,50 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <C extends Container> boolean matchStaticFilters(Recipe<C> recipe) {
|
protected <C extends Container> boolean matchStaticFilters(Recipe<C> recipe) {
|
||||||
return (recipe instanceof CraftingRecipe && !(recipe instanceof MechanicalCraftingRecipe)
|
return (recipe instanceof CraftingRecipe && !(recipe instanceof MechanicalCraftingRecipe) && canCompress(recipe)
|
||||||
&& canCompress(recipe) && !AllRecipeTypes.shouldIgnoreInAutomation(recipe))
|
&& !AllRecipeTypes.shouldIgnoreInAutomation(recipe))
|
||||||
|| recipe.getType() == AllRecipeTypes.COMPACTING.getType();
|
|| recipe.getType() == AllRecipeTypes.COMPACTING.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getKineticSpeed() {
|
||||||
|
return getSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canProcessInBulk() {
|
||||||
|
return AllConfigs.SERVER.recipes.bulkPressing.get();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object getRecipeCacheKey() {
|
protected Object getRecipeCacheKey() {
|
||||||
return compressingRecipesKey;
|
return compressingRecipesKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getParticleAmount() {
|
||||||
|
return 15;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startProcessingBasin() {
|
public void startProcessingBasin() {
|
||||||
if (running && runningTicks <= CYCLE / 2)
|
if (pressingBehaviour.running && pressingBehaviour.runningTicks <= PressingBehaviour.CYCLE / 2)
|
||||||
return;
|
return;
|
||||||
super.startProcessingBasin();
|
super.startProcessingBasin();
|
||||||
start(Mode.BASIN);
|
pressingBehaviour.start(Mode.BASIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onBasinRemoved() {
|
protected void onBasinRemoved() {
|
||||||
pressedItems.clear();
|
pressingBehaviour.particleItems.clear();
|
||||||
running = false;
|
pressingBehaviour.running = false;
|
||||||
runningTicks = 0;
|
pressingBehaviour.runningTicks = 0;
|
||||||
sendData();
|
sendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isRunning() {
|
protected boolean isRunning() {
|
||||||
return running;
|
return pressingBehaviour.running;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -386,16 +207,4 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
|
||||||
return Optional.of(AllTriggers.PRESS_COMPACT);
|
return Optional.of(AllTriggers.PRESS_COMPACT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Mode {
|
|
||||||
WORLD(1), BELT(19f / 16f), BASIN(22f / 16f)
|
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
float headOffset;
|
|
||||||
|
|
||||||
Mode(float headOffset) {
|
|
||||||
this.headOffset = headOffset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,8 @@ public class PressInstance extends ShaftInstance implements DynamicInstance {
|
||||||
.getModel(AllBlockPartials.MECHANICAL_PRESS_HEAD, blockState)
|
.getModel(AllBlockPartials.MECHANICAL_PRESS_HEAD, blockState)
|
||||||
.createInstance();
|
.createInstance();
|
||||||
|
|
||||||
Quaternion q = Vector3f.YP.rotationDegrees(AngleHelper.horizontalAngle(blockState.getValue(MechanicalPressBlock.HORIZONTAL_FACING)));
|
Quaternion q = Vector3f.YP
|
||||||
|
.rotationDegrees(AngleHelper.horizontalAngle(blockState.getValue(MechanicalPressBlock.HORIZONTAL_FACING)));
|
||||||
|
|
||||||
pressHead.setRotation(q);
|
pressHead.setRotation(q);
|
||||||
|
|
||||||
|
@ -45,7 +46,9 @@ public class PressInstance extends ShaftInstance implements DynamicInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getRenderedHeadOffset(MechanicalPressTileEntity press) {
|
private float getRenderedHeadOffset(MechanicalPressTileEntity press) {
|
||||||
return press.getRenderedHeadOffset(AnimationTickHolder.getPartialTicks());
|
PressingBehaviour pressingBehaviour = press.getPressingBehaviour();
|
||||||
|
return pressingBehaviour.getRenderedHeadOffset(AnimationTickHolder.getPartialTicks())
|
||||||
|
* pressingBehaviour.mode.headOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,305 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.press;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.AllSoundEvents;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.particles.ItemParticleOption;
|
||||||
|
import net.minecraft.core.particles.ParticleTypes;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.item.ItemEntity;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.SoundType;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
|
public class PressingBehaviour extends BeltProcessingBehaviour {
|
||||||
|
|
||||||
|
public static final int CYCLE = 240;
|
||||||
|
public static final int ENTITY_SCAN = 10;
|
||||||
|
|
||||||
|
public List<ItemStack> particleItems = new ArrayList<>();
|
||||||
|
|
||||||
|
public PressingBehaviourSpecifics specifics;
|
||||||
|
public int prevRunningTicks;
|
||||||
|
public int runningTicks;
|
||||||
|
public boolean running;
|
||||||
|
public boolean finished;
|
||||||
|
public Mode mode;
|
||||||
|
|
||||||
|
int entityScanCooldown;
|
||||||
|
|
||||||
|
public interface PressingBehaviourSpecifics {
|
||||||
|
public boolean tryProcessInBasin(boolean simulate);
|
||||||
|
|
||||||
|
public boolean tryProcessOnBelt(TransportedItemStack input, List<ItemStack> outputList, boolean simulate);
|
||||||
|
|
||||||
|
public boolean tryProcessInWorld(ItemEntity itemEntity, boolean simulate);
|
||||||
|
|
||||||
|
public boolean canProcessInBulk();
|
||||||
|
|
||||||
|
public void onPressingCompleted();
|
||||||
|
|
||||||
|
public int getParticleAmount();
|
||||||
|
|
||||||
|
public float getKineticSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends SmartTileEntity & PressingBehaviourSpecifics> PressingBehaviour(T te) {
|
||||||
|
super(te);
|
||||||
|
this.specifics = te;
|
||||||
|
mode = Mode.WORLD;
|
||||||
|
entityScanCooldown = ENTITY_SCAN;
|
||||||
|
whenItemEnters((s, i) -> BeltPressingCallbacks.onItemReceived(s, i, this));
|
||||||
|
whileItemHeld((s, i) -> BeltPressingCallbacks.whenItemHeld(s, i, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(CompoundTag compound, boolean clientPacket) {
|
||||||
|
running = compound.getBoolean("Running");
|
||||||
|
mode = Mode.values()[compound.getInt("Mode")];
|
||||||
|
finished = compound.getBoolean("Finished");
|
||||||
|
prevRunningTicks = runningTicks = compound.getInt("Ticks");
|
||||||
|
super.read(compound, clientPacket);
|
||||||
|
|
||||||
|
if (clientPacket) {
|
||||||
|
NBTHelper.iterateCompoundList(compound.getList("ParticleItems", Tag.TAG_COMPOUND),
|
||||||
|
c -> particleItems.add(ItemStack.of(c)));
|
||||||
|
spawnParticles();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(CompoundTag compound, boolean clientPacket) {
|
||||||
|
compound.putBoolean("Running", running);
|
||||||
|
compound.putInt("Mode", mode.ordinal());
|
||||||
|
compound.putBoolean("Finished", finished);
|
||||||
|
compound.putInt("Ticks", runningTicks);
|
||||||
|
super.write(compound, clientPacket);
|
||||||
|
|
||||||
|
if (clientPacket) {
|
||||||
|
compound.put("ParticleItems", NBTHelper.writeCompoundList(particleItems, ItemStack::serializeNBT));
|
||||||
|
particleItems.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getRenderedHeadOffset(float partialTicks) {
|
||||||
|
if (!running)
|
||||||
|
return 0;
|
||||||
|
int runningTicks = Math.abs(this.runningTicks);
|
||||||
|
float ticks = Mth.lerp(partialTicks, prevRunningTicks, runningTicks);
|
||||||
|
if (runningTicks < (CYCLE * 2) / 3)
|
||||||
|
return (float) Mth.clamp(Math.pow(ticks / CYCLE * 2, 3), 0, 1);
|
||||||
|
return Mth.clamp((CYCLE - ticks) / CYCLE * 3, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start(Mode mode) {
|
||||||
|
this.mode = mode;
|
||||||
|
running = true;
|
||||||
|
prevRunningTicks = 0;
|
||||||
|
runningTicks = 0;
|
||||||
|
particleItems.clear();
|
||||||
|
tileEntity.sendData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean inWorld() {
|
||||||
|
return mode == Mode.WORLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onBasin() {
|
||||||
|
return mode == Mode.BASIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
|
||||||
|
Level level = getWorld();
|
||||||
|
BlockPos worldPosition = getPos();
|
||||||
|
|
||||||
|
if (!running || level == null) {
|
||||||
|
if (level != null && !level.isClientSide) {
|
||||||
|
|
||||||
|
if (specifics.getKineticSpeed() == 0)
|
||||||
|
return;
|
||||||
|
if (entityScanCooldown > 0)
|
||||||
|
entityScanCooldown--;
|
||||||
|
if (entityScanCooldown <= 0) {
|
||||||
|
entityScanCooldown = ENTITY_SCAN;
|
||||||
|
|
||||||
|
if (TileEntityBehaviour.get(level, worldPosition.below(2),
|
||||||
|
TransportedItemStackHandlerBehaviour.TYPE) != null)
|
||||||
|
return;
|
||||||
|
if (AllBlocks.BASIN.has(level.getBlockState(worldPosition.below(2))))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class,
|
||||||
|
new AABB(worldPosition.below()).deflate(.125f))) {
|
||||||
|
if (!itemEntity.isAlive() || !itemEntity.isOnGround())
|
||||||
|
continue;
|
||||||
|
if (!specifics.tryProcessInWorld(itemEntity, true))
|
||||||
|
continue;
|
||||||
|
start(Mode.WORLD);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level.isClientSide && runningTicks == -CYCLE / 2) {
|
||||||
|
prevRunningTicks = CYCLE / 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runningTicks == CYCLE / 2 && specifics.getKineticSpeed() != 0) {
|
||||||
|
if (inWorld())
|
||||||
|
applyInWorld();
|
||||||
|
if (onBasin())
|
||||||
|
applyOnBasin();
|
||||||
|
|
||||||
|
if (level.getBlockState(worldPosition.below(2))
|
||||||
|
.getSoundType() == SoundType.WOOL)
|
||||||
|
AllSoundEvents.MECHANICAL_PRESS_ACTIVATION_ON_BELT.playOnServer(level, worldPosition);
|
||||||
|
else
|
||||||
|
AllSoundEvents.MECHANICAL_PRESS_ACTIVATION.playOnServer(level, worldPosition, .5f,
|
||||||
|
.75f + (Math.abs(specifics.getKineticSpeed()) / 1024f));
|
||||||
|
|
||||||
|
if (!level.isClientSide)
|
||||||
|
tileEntity.sendData();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!level.isClientSide && runningTicks > CYCLE) {
|
||||||
|
finished = true;
|
||||||
|
running = false;
|
||||||
|
particleItems.clear();
|
||||||
|
specifics.onPressingCompleted();
|
||||||
|
tileEntity.sendData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
prevRunningTicks = runningTicks;
|
||||||
|
runningTicks += getRunningTickSpeed();
|
||||||
|
if (prevRunningTicks < CYCLE / 2 && runningTicks >= CYCLE / 2) {
|
||||||
|
runningTicks = CYCLE / 2;
|
||||||
|
// Pause the ticks until a packet is received
|
||||||
|
if (level.isClientSide && !tileEntity.isVirtual())
|
||||||
|
runningTicks = -(CYCLE / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void applyOnBasin() {
|
||||||
|
Level level = getWorld();
|
||||||
|
if (level.isClientSide)
|
||||||
|
return;
|
||||||
|
particleItems.clear();
|
||||||
|
if (specifics.tryProcessInBasin(false))
|
||||||
|
tileEntity.sendData();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void applyInWorld() {
|
||||||
|
Level level = getWorld();
|
||||||
|
BlockPos worldPosition = getPos();
|
||||||
|
AABB bb = new AABB(worldPosition.below(1));
|
||||||
|
boolean bulk = specifics.canProcessInBulk();
|
||||||
|
|
||||||
|
particleItems.clear();
|
||||||
|
|
||||||
|
if (level.isClientSide)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (Entity entity : level.getEntities(null, bb)) {
|
||||||
|
if (!(entity instanceof ItemEntity itemEntity))
|
||||||
|
continue;
|
||||||
|
if (!entity.isAlive() || !entity.isOnGround())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
entityScanCooldown = 0;
|
||||||
|
if (specifics.tryProcessInWorld(itemEntity, false))
|
||||||
|
tileEntity.sendData();
|
||||||
|
if (!bulk)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRunningTickSpeed() {
|
||||||
|
float speed = specifics.getKineticSpeed();
|
||||||
|
if (speed == 0)
|
||||||
|
return 0;
|
||||||
|
return (int) Mth.lerp(Mth.clamp(Math.abs(speed) / 512f, 0, 1), 1, 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void spawnParticles() {
|
||||||
|
if (particleItems.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
BlockPos worldPosition = getPos();
|
||||||
|
|
||||||
|
if (mode == Mode.BASIN)
|
||||||
|
particleItems
|
||||||
|
.forEach(stack -> makeCompactingParticleEffect(VecHelper.getCenterOf(worldPosition.below(2)), stack));
|
||||||
|
if (mode == Mode.BELT)
|
||||||
|
particleItems.forEach(stack -> makePressingParticleEffect(VecHelper.getCenterOf(worldPosition.below(2))
|
||||||
|
.add(0, 8 / 16f, 0), stack));
|
||||||
|
if (mode == Mode.WORLD)
|
||||||
|
particleItems.forEach(stack -> makePressingParticleEffect(VecHelper.getCenterOf(worldPosition.below(1))
|
||||||
|
.add(0, -1 / 4f, 0), stack));
|
||||||
|
|
||||||
|
particleItems.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void makePressingParticleEffect(Vec3 pos, ItemStack stack) {
|
||||||
|
makePressingParticleEffect(pos, stack, specifics.getParticleAmount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void makePressingParticleEffect(Vec3 pos, ItemStack stack, int amount) {
|
||||||
|
Level level = getWorld();
|
||||||
|
if (level == null || !level.isClientSide)
|
||||||
|
return;
|
||||||
|
for (int i = 0; i < amount; i++) {
|
||||||
|
Vec3 motion = VecHelper.offsetRandomly(Vec3.ZERO, level.random, .125f)
|
||||||
|
.multiply(1, 0, 1);
|
||||||
|
motion = motion.add(0, amount != 1 ? 0.125f : 1 / 16f, 0);
|
||||||
|
level.addParticle(new ItemParticleOption(ParticleTypes.ITEM, stack), pos.x, pos.y - .25f, pos.z, motion.x,
|
||||||
|
motion.y, motion.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void makeCompactingParticleEffect(Vec3 pos, ItemStack stack) {
|
||||||
|
Level level = getWorld();
|
||||||
|
if (level == null || !level.isClientSide)
|
||||||
|
return;
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
Vec3 motion = VecHelper.offsetRandomly(Vec3.ZERO, level.random, .175f)
|
||||||
|
.multiply(1, 0, 1);
|
||||||
|
level.addParticle(new ItemParticleOption(ParticleTypes.ITEM, stack), pos.x, pos.y, pos.z, motion.x,
|
||||||
|
motion.y + .25f, motion.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Mode {
|
||||||
|
WORLD(1), BELT(19f / 16f), BASIN(22f / 16f);
|
||||||
|
|
||||||
|
public float headOffset;
|
||||||
|
|
||||||
|
Mode(float headOffset) {
|
||||||
|
this.headOffset = headOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,6 +9,8 @@ import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock;
|
||||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelTileEntity;
|
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelTileEntity;
|
||||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelBlock;
|
import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelBlock;
|
||||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelTileEntity;
|
import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelTileEntity;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererBlock;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.AccumulatedItemCountDataSource;
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
|
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
@ -44,6 +46,7 @@ public class BeltTunnelInteractionHandler {
|
||||||
boolean onServer = !world.isClientSide || beltInventory.belt.isVirtual();
|
boolean onServer = !world.isClientSide || beltInventory.belt.isVirtual();
|
||||||
boolean removed = false;
|
boolean removed = false;
|
||||||
BeltTunnelTileEntity nextTunnel = getTunnelOnSegment(beltInventory, upcomingSegment);
|
BeltTunnelTileEntity nextTunnel = getTunnelOnSegment(beltInventory, upcomingSegment);
|
||||||
|
int transferred = current.stack.getCount();
|
||||||
|
|
||||||
if (nextTunnel instanceof BrassTunnelTileEntity) {
|
if (nextTunnel instanceof BrassTunnelTileEntity) {
|
||||||
BrassTunnelTileEntity brassTunnel = (BrassTunnelTileEntity) nextTunnel;
|
BrassTunnelTileEntity brassTunnel = (BrassTunnelTileEntity) nextTunnel;
|
||||||
|
@ -82,7 +85,8 @@ public class BeltTunnelInteractionHandler {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ItemStack toinsert = ItemHandlerHelper.copyStackWithSize(current.stack, 1);
|
ItemStack toinsert = ItemHandlerHelper.copyStackWithSize(current.stack, 1);
|
||||||
if (!behaviour.handleInsertion(toinsert, d, false).isEmpty())
|
if (!behaviour.handleInsertion(toinsert, d, false)
|
||||||
|
.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
if (onServer)
|
if (onServer)
|
||||||
flapTunnel(beltInventory, upcomingSegment, d, false);
|
flapTunnel(beltInventory, upcomingSegment, d, false);
|
||||||
|
@ -98,6 +102,10 @@ public class BeltTunnelInteractionHandler {
|
||||||
if (onServer) {
|
if (onServer) {
|
||||||
flapTunnel(beltInventory, currentSegment, movementFacing, false);
|
flapTunnel(beltInventory, currentSegment, movementFacing, false);
|
||||||
flapTunnel(beltInventory, upcomingSegment, movementFacing.getOpposite(), true);
|
flapTunnel(beltInventory, upcomingSegment, movementFacing.getOpposite(), true);
|
||||||
|
|
||||||
|
if (nextTunnel != null)
|
||||||
|
DataGathererBlock.sendToGatherers(world, nextTunnel.getBlockPos(),
|
||||||
|
(dgte, b) -> b.itemReceived(dgte, transferred), AccumulatedItemCountDataSource.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removed)
|
if (removed)
|
||||||
|
@ -140,7 +148,8 @@ public class BeltTunnelInteractionHandler {
|
||||||
|
|
||||||
public static BeltTunnelTileEntity getTunnelOnPosition(Level world, BlockPos pos) {
|
public static BeltTunnelTileEntity getTunnelOnPosition(Level world, BlockPos pos) {
|
||||||
pos = pos.above();
|
pos = pos.above();
|
||||||
if (!(world.getBlockState(pos).getBlock() instanceof BeltTunnelBlock))
|
if (!(world.getBlockState(pos)
|
||||||
|
.getBlock() instanceof BeltTunnelBlock))
|
||||||
return null;
|
return null;
|
||||||
BlockEntity te = world.getBlockEntity(pos);
|
BlockEntity te = world.getBlockEntity(pos);
|
||||||
if (te == null || !(te instanceof BeltTunnelTileEntity))
|
if (te == null || !(te instanceof BeltTunnelTileEntity))
|
||||||
|
|
|
@ -12,6 +12,7 @@ import com.simibubi.create.content.contraptions.relays.elementary.BracketedTileE
|
||||||
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
||||||
import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock;
|
import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock;
|
||||||
import com.simibubi.create.content.logistics.block.redstone.NixieTubeBlock;
|
import com.simibubi.create.content.logistics.block.redstone.NixieTubeBlock;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.track.TrackBlock;
|
import com.simibubi.create.content.logistics.trains.track.TrackBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.track.TrackShape;
|
import com.simibubi.create.content.logistics.trains.track.TrackShape;
|
||||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||||
|
@ -203,6 +204,8 @@ public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenc
|
||||||
state = state.setValue(updateProperty, true);
|
state = state.setValue(updateProperty, true);
|
||||||
else if (sideState.getBlock() instanceof NixieTubeBlock && NixieTubeBlock.getFacing(sideState) == d)
|
else if (sideState.getBlock() instanceof NixieTubeBlock && NixieTubeBlock.getFacing(sideState) == d)
|
||||||
state = state.setValue(updateProperty, true);
|
state = state.setValue(updateProperty, true);
|
||||||
|
else if (sideState.getBlock() instanceof FlapDisplayBlock)
|
||||||
|
state = state.setValue(updateProperty, true);
|
||||||
else if (isFacingBracket(level, pos, d))
|
else if (isFacingBracket(level, pos, d))
|
||||||
state = state.setValue(updateProperty, true);
|
state = state.setValue(updateProperty, true);
|
||||||
return state;
|
return state;
|
||||||
|
|
|
@ -0,0 +1,185 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.DataGathererSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.DeathCounterDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.ScoreboardDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataGathererTarget;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.LecternDataTarget;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.SignDataTarget;
|
||||||
|
import com.tterrag.registrate.util.nullness.NonNullConsumer;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
public class AllDataGathererBehaviours {
|
||||||
|
|
||||||
|
public static final HashMap<ResourceLocation, DataGathererBehaviour>
|
||||||
|
|
||||||
|
GATHERER_BEHAVIOURS = new HashMap<>();
|
||||||
|
|
||||||
|
public static final HashMap<ResourceLocation, List<DataGathererSource>>
|
||||||
|
|
||||||
|
SOURCES_BY_BLOCK = new HashMap<>(), SOURCES_BY_TILE = new HashMap<>();
|
||||||
|
|
||||||
|
public static final HashMap<ResourceLocation, DataGathererTarget>
|
||||||
|
|
||||||
|
TARGETS_BY_BLOCK = new HashMap<>(), TARGETS_BY_TILE = new HashMap<>();
|
||||||
|
|
||||||
|
public static DataGathererBehaviour register(ResourceLocation id, DataGathererBehaviour behaviour) {
|
||||||
|
if (GATHERER_BEHAVIOURS.containsKey(id))
|
||||||
|
Create.LOGGER.warn("Data Gatherer Behaviour for " + id.toString() + " was overridden");
|
||||||
|
behaviour.id = id;
|
||||||
|
GATHERER_BEHAVIOURS.put(id, behaviour);
|
||||||
|
return behaviour;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assign(DataGathererBehaviour behaviour, Block block) {
|
||||||
|
assignBlock(behaviour, block.getRegistryName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assign(DataGathererBehaviour behaviour, BlockEntityType<?> teType) {
|
||||||
|
assignTileEntity(behaviour, teType.getRegistryName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assignBlock(DataGathererBehaviour behaviour, ResourceLocation blockId) {
|
||||||
|
if (behaviour instanceof DataGathererSource source)
|
||||||
|
SOURCES_BY_BLOCK.computeIfAbsent(blockId, r -> new ArrayList<>())
|
||||||
|
.add(source);
|
||||||
|
if (behaviour instanceof DataGathererTarget target)
|
||||||
|
TARGETS_BY_BLOCK.put(blockId, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assignTileEntity(DataGathererBehaviour behaviour, ResourceLocation tileId) {
|
||||||
|
if (behaviour instanceof DataGathererSource source)
|
||||||
|
SOURCES_BY_TILE.computeIfAbsent(tileId, r -> new ArrayList<>())
|
||||||
|
.add(source);
|
||||||
|
if (behaviour instanceof DataGathererTarget target)
|
||||||
|
TARGETS_BY_TILE.put(tileId, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <B extends Block> NonNullConsumer<? super B> assignDataBehaviour(DataGathererBehaviour behaviour,
|
||||||
|
String... suffix) {
|
||||||
|
return b -> {
|
||||||
|
ResourceLocation registryName = b.getRegistryName();
|
||||||
|
String idSuffix = behaviour instanceof DataGathererSource ? "_source" : "_target";
|
||||||
|
if (suffix.length > 0)
|
||||||
|
idSuffix += "_" + suffix[0];
|
||||||
|
assignBlock(register(new ResourceLocation(registryName.getNamespace(), registryName.getPath() + idSuffix),
|
||||||
|
behaviour), registryName);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <B extends BlockEntityType<?>> NonNullConsumer<? super B> assignDataBehaviourTE(
|
||||||
|
DataGathererBehaviour behaviour, String... suffix) {
|
||||||
|
return b -> {
|
||||||
|
ResourceLocation registryName = b.getRegistryName();
|
||||||
|
String idSuffix = behaviour instanceof DataGathererSource ? "_source" : "_target";
|
||||||
|
if (suffix.length > 0)
|
||||||
|
idSuffix += "_" + suffix[0];
|
||||||
|
assignTileEntity(
|
||||||
|
register(new ResourceLocation(registryName.getNamespace(), registryName.getPath() + idSuffix),
|
||||||
|
behaviour),
|
||||||
|
registryName);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static DataGathererSource getSource(ResourceLocation resourceLocation) {
|
||||||
|
DataGathererBehaviour available = GATHERER_BEHAVIOURS.getOrDefault(resourceLocation, null);
|
||||||
|
if (available instanceof DataGathererSource source)
|
||||||
|
return source;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static DataGathererTarget getTarget(ResourceLocation resourceLocation) {
|
||||||
|
DataGathererBehaviour available = GATHERER_BEHAVIOURS.getOrDefault(resourceLocation, null);
|
||||||
|
if (available instanceof DataGathererTarget target)
|
||||||
|
return target;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static List<DataGathererSource> sourcesOf(LevelAccessor level, BlockPos pos) {
|
||||||
|
BlockState blockState = level.getBlockState(pos);
|
||||||
|
BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||||
|
|
||||||
|
List<DataGathererSource> sourcesOfBlock = sourcesOf(blockState);
|
||||||
|
List<DataGathererSource> sourcesOfTE = blockEntity == null ? Collections.emptyList() : sourcesOf(blockEntity);
|
||||||
|
|
||||||
|
if (sourcesOfTE.isEmpty())
|
||||||
|
return sourcesOfBlock;
|
||||||
|
return sourcesOfTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static DataGathererTarget targetOf(LevelAccessor level, BlockPos pos) {
|
||||||
|
BlockState blockState = level.getBlockState(pos);
|
||||||
|
BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||||
|
|
||||||
|
DataGathererTarget targetOfBlock = targetOf(blockState);
|
||||||
|
DataGathererTarget targetOfTE = blockEntity == null ? null : targetOf(blockEntity);
|
||||||
|
|
||||||
|
if (targetOfTE == null)
|
||||||
|
return targetOfBlock;
|
||||||
|
return targetOfTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<DataGathererSource> sourcesOf(BlockState state) {
|
||||||
|
return sourcesOf(state.getBlock());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<DataGathererSource> sourcesOf(BlockEntity tileEntity) {
|
||||||
|
return SOURCES_BY_TILE.getOrDefault(tileEntity.getType()
|
||||||
|
.getRegistryName(), Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<DataGathererSource> sourcesOf(Block block) {
|
||||||
|
return SOURCES_BY_BLOCK.getOrDefault(block.getRegistryName(), Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static DataGathererTarget targetOf(BlockState state) {
|
||||||
|
return targetOf(state.getBlock());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static DataGathererTarget targetOf(BlockEntity tileEntity) {
|
||||||
|
return TARGETS_BY_TILE.get(tileEntity.getType()
|
||||||
|
.getRegistryName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static DataGathererTarget targetOf(Block block) {
|
||||||
|
return TARGETS_BY_BLOCK.get(block.getRegistryName());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
public static void register() {
|
||||||
|
assign(register(Create.asResource("sign_data_target"), new SignDataTarget()), BlockEntityType.SIGN);
|
||||||
|
assign(register(Create.asResource("lectern_data_target"), new LecternDataTarget()), BlockEntityType.LECTERN);
|
||||||
|
assign(register(Create.asResource("death_count_data_source"), new DeathCounterDataSource()),
|
||||||
|
Blocks.RESPAWN_ANCHOR);
|
||||||
|
assign(register(Create.asResource("scoreboard_data_source"), new ScoreboardDataSource()),
|
||||||
|
BlockEntityType.COMMAND_BLOCK);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
public abstract class DataGathererBehaviour {
|
||||||
|
|
||||||
|
public ResourceLocation id;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data;
|
||||||
|
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.AllShapes;
|
||||||
|
import com.simibubi.create.AllTileEntities;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.DataGathererSource;
|
||||||
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
|
import com.simibubi.create.foundation.block.WrenchableDirectionalBlock;
|
||||||
|
import com.simibubi.create.foundation.gui.ScreenOpener;
|
||||||
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.client.player.LocalPlayer;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.InteractionHand;
|
||||||
|
import net.minecraft.world.InteractionResult;
|
||||||
|
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.Level;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
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.BlockStateProperties;
|
||||||
|
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||||
|
import net.minecraft.world.level.pathfinder.PathComputationType;
|
||||||
|
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 DataGathererBlock extends WrenchableDirectionalBlock implements ITE<DataGathererTileEntity> {
|
||||||
|
|
||||||
|
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
|
||||||
|
|
||||||
|
public DataGathererBlock(Properties p_i48415_1_) {
|
||||||
|
super(p_i48415_1_);
|
||||||
|
registerDefaultState(defaultBlockState().setValue(POWERED, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||||
|
BlockState placed = super.getStateForPlacement(context);
|
||||||
|
placed = placed.setValue(FACING, context.getClickedFace());
|
||||||
|
return placed.setValue(POWERED, shouldBePowered(placed, context.getLevel(), context.getClickedPos()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void notifyGatherers(LevelAccessor level, BlockPos pos) {
|
||||||
|
forEachAttachedGatherer(level, pos, DataGathererTileEntity::updateGatheredData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T extends DataGathererSource> void sendToGatherers(LevelAccessor level, BlockPos pos,
|
||||||
|
BiConsumer<DataGathererTileEntity, T> callback, Class<T> type) {
|
||||||
|
forEachAttachedGatherer(level, pos, dgte -> {
|
||||||
|
if (type.isInstance(dgte.activeSource))
|
||||||
|
callback.accept(dgte, (T) dgte.activeSource);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void forEachAttachedGatherer(LevelAccessor level, BlockPos pos,
|
||||||
|
Consumer<DataGathererTileEntity> callback) {
|
||||||
|
for (Direction d : Iterate.directions) {
|
||||||
|
BlockPos offsetPos = pos.relative(d);
|
||||||
|
BlockState blockState = level.getBlockState(offsetPos);
|
||||||
|
if (!AllBlocks.DATA_GATHERER.has(blockState))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BlockEntity blockEntity = level.getBlockEntity(offsetPos);
|
||||||
|
if (!(blockEntity instanceof DataGathererTileEntity dgte))
|
||||||
|
continue;
|
||||||
|
if (dgte.activeSource == null)
|
||||||
|
continue;
|
||||||
|
if (dgte.getDirection() != d.getOpposite())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
callback.accept(dgte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
|
||||||
|
boolean isMoving) {
|
||||||
|
if (worldIn.isClientSide)
|
||||||
|
return;
|
||||||
|
boolean powered = shouldBePowered(state, worldIn, pos);
|
||||||
|
boolean previouslyPowered = state.getValue(POWERED);
|
||||||
|
if (previouslyPowered != powered) {
|
||||||
|
worldIn.setBlock(pos, state.cycle(POWERED), 2);
|
||||||
|
if (!powered)
|
||||||
|
withTileEntityDo(worldIn, pos, DataGathererTileEntity::onNoLongerPowered);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldBePowered(BlockState state, Level worldIn, BlockPos pos) {
|
||||||
|
boolean powered = false;
|
||||||
|
for (Direction d : Iterate.directions) {
|
||||||
|
if (d.getOpposite() == state.getValue(FACING))
|
||||||
|
continue;
|
||||||
|
if (worldIn.getSignal(pos.relative(d), d) == 0)
|
||||||
|
continue;
|
||||||
|
powered = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return powered;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createBlockStateDefinition(Builder<Block, BlockState> builder) {
|
||||||
|
super.createBlockStateDefinition(builder.add(POWERED));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand,
|
||||||
|
BlockHitResult pHit) {
|
||||||
|
if (pPlayer == null)
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
if (pPlayer.isSteppingCarefully())
|
||||||
|
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(DataGathererTileEntity te, Player player) {
|
||||||
|
if (!(player instanceof LocalPlayer))
|
||||||
|
return;
|
||||||
|
if (te.targetOffset.equals(BlockPos.ZERO)) {
|
||||||
|
player.displayClientMessage(Lang.translate("data_gatherer.invalid"), true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ScreenOpener.open(new DataGathererScreen(te));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPathfindable(BlockState pState, BlockGetter pLevel, BlockPos pPos, PathComputationType pType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
|
||||||
|
return AllShapes.DATA_GATHERER.get(pState.getValue(FACING));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<DataGathererTileEntity> getTileEntityClass() {
|
||||||
|
return DataGathererTileEntity.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockEntityType<? extends DataGathererTileEntity> getTileEntityType() {
|
||||||
|
return AllTileEntities.DATA_GATHERER.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,150 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.CreateClient;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataGathererTarget;
|
||||||
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
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;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.Event.Result;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
|
|
||||||
|
@EventBusSubscriber
|
||||||
|
public class DataGathererBlockItem extends BlockItem {
|
||||||
|
|
||||||
|
public DataGathererBlockItem(Block pBlock, Properties pProperties) {
|
||||||
|
super(pBlock, pProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void gathererItemAlwaysPlacesWhenUsed(PlayerInteractEvent.RightClickBlock event) {
|
||||||
|
ItemStack usedItem = event.getItemStack();
|
||||||
|
if (usedItem.getItem() instanceof DataGathererBlockItem) {
|
||||||
|
if (AllBlocks.DATA_GATHERER.has(event.getWorld()
|
||||||
|
.getBlockState(event.getPos())))
|
||||||
|
return;
|
||||||
|
event.setUseBlock(Result.DENY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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("data_gatherer.clear"), true);
|
||||||
|
stack.setTag(null);
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stack.hasTag()) {
|
||||||
|
if (level.isClientSide)
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
CompoundTag stackTag = stack.getOrCreateTag();
|
||||||
|
stackTag.put("SelectedPos", NbtUtils.writeBlockPos(pos));
|
||||||
|
player.displayClientMessage(Lang.translate("data_gatherer.set"), true);
|
||||||
|
stack.setTag(stackTag);
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompoundTag tag = stack.getTag();
|
||||||
|
CompoundTag teTag = new CompoundTag();
|
||||||
|
|
||||||
|
BlockPos selectedPos = NbtUtils.readBlockPos(tag.getCompound("SelectedPos"));
|
||||||
|
BlockPos placedPos = pos.relative(pContext.getClickedFace(), state.getMaterial()
|
||||||
|
.isReplaceable() ? 0 : 1);
|
||||||
|
|
||||||
|
if (!selectedPos.closerThan(placedPos, AllConfigs.SERVER.logistics.dataGathererRange.get())) {
|
||||||
|
player.displayClientMessage(Lang.translate("data_gatherer.too_far")
|
||||||
|
.withStyle(ChatFormatting.RED), true);
|
||||||
|
return InteractionResult.FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
teTag.put("TargetOffset", 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("data_gatherer.success")
|
||||||
|
.withStyle(ChatFormatting.GREEN), true);
|
||||||
|
return useOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BlockPos lastShownPos = null;
|
||||||
|
private static AABB lastShownAABB = null;
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public static void clientTick() {
|
||||||
|
Player player = Minecraft.getInstance().player;
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
|
ItemStack heldItemMainhand = player.getMainHandItem();
|
||||||
|
if (!(heldItemMainhand.getItem() instanceof DataGathererBlockItem))
|
||||||
|
return;
|
||||||
|
if (!heldItemMainhand.hasTag())
|
||||||
|
return;
|
||||||
|
CompoundTag stackTag = heldItemMainhand.getOrCreateTag();
|
||||||
|
if (!stackTag.contains("SelectedPos"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BlockPos selectedPos = NbtUtils.readBlockPos(stackTag.getCompound("SelectedPos"));
|
||||||
|
|
||||||
|
if (!selectedPos.equals(lastShownPos)) {
|
||||||
|
lastShownAABB = getBounds(selectedPos);
|
||||||
|
lastShownPos = selectedPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateClient.OUTLINER.showAABB("target", lastShownAABB)
|
||||||
|
.colored(0xffcb74)
|
||||||
|
.lineWidth(1 / 16f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
private static AABB getBounds(BlockPos pos) {
|
||||||
|
Level world = Minecraft.getInstance().level;
|
||||||
|
DataGathererTarget target = AllDataGathererBehaviours.targetOf(world, pos);
|
||||||
|
|
||||||
|
if (target != null)
|
||||||
|
return target.getMultiblockBounds(world, pos);
|
||||||
|
|
||||||
|
BlockState state = world.getBlockState(pos);
|
||||||
|
VoxelShape shape = state.getShape(world, pos);
|
||||||
|
return shape.isEmpty() ? new AABB(BlockPos.ZERO)
|
||||||
|
: shape.bounds()
|
||||||
|
.move(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.DataGathererSource;
|
||||||
|
import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
public class DataGathererConfigurationPacket extends TileEntityConfigurationPacket<DataGathererTileEntity> {
|
||||||
|
|
||||||
|
private CompoundTag configData;
|
||||||
|
private int targetLine;
|
||||||
|
|
||||||
|
public DataGathererConfigurationPacket(BlockPos pos, CompoundTag configData, int targetLine) {
|
||||||
|
super(pos);
|
||||||
|
this.configData = configData;
|
||||||
|
this.targetLine = targetLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataGathererConfigurationPacket(FriendlyByteBuf buffer) {
|
||||||
|
super(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeSettings(FriendlyByteBuf buffer) {
|
||||||
|
buffer.writeNbt(configData);
|
||||||
|
buffer.writeInt(targetLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void readSettings(FriendlyByteBuf buffer) {
|
||||||
|
configData = buffer.readNbt();
|
||||||
|
targetLine = buffer.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applySettings(DataGathererTileEntity te) {
|
||||||
|
te.targetLine = targetLine;
|
||||||
|
|
||||||
|
if (!configData.contains("Id")) {
|
||||||
|
te.notifyUpdate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceLocation id = new ResourceLocation(configData.getString("Id"));
|
||||||
|
DataGathererSource source = AllDataGathererBehaviours.getSource(id);
|
||||||
|
if (source == null) {
|
||||||
|
te.notifyUpdate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (te.activeSource == null || te.activeSource != source) {
|
||||||
|
te.activeSource = source;
|
||||||
|
te.setSourceConfig(configData.copy());
|
||||||
|
} else {
|
||||||
|
te.getSourceConfig()
|
||||||
|
.merge(configData);
|
||||||
|
}
|
||||||
|
|
||||||
|
te.updateGatheredData();
|
||||||
|
te.notifyUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
|
||||||
|
public class DataGathererContext {
|
||||||
|
|
||||||
|
private LevelAccessor level;
|
||||||
|
private DataGathererTileEntity te;
|
||||||
|
|
||||||
|
public Object flapDisplayContext;
|
||||||
|
|
||||||
|
public DataGathererContext(LevelAccessor level, DataGathererTileEntity te) {
|
||||||
|
this.level = level;
|
||||||
|
this.te = te;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LevelAccessor level() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataGathererTileEntity te() {
|
||||||
|
return te;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockEntity getSourceTE() {
|
||||||
|
return level.getBlockEntity(getSourcePos());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockPos getSourcePos() {
|
||||||
|
return te.getSourcePosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockEntity getTargetTE() {
|
||||||
|
return level.getBlockEntity(getTargetPos());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockPos getTargetPos() {
|
||||||
|
return te.getTargetPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundTag sourceConfig() {
|
||||||
|
return te.getSourceConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,382 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.DataGathererSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.SingleLineDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataGathererTarget;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataTargetStats;
|
||||||
|
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.UIRenderHelper;
|
||||||
|
import com.simibubi.create.foundation.gui.element.GuiGameElement;
|
||||||
|
import com.simibubi.create.foundation.gui.widget.IconButton;
|
||||||
|
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.gui.widget.TooltipArea;
|
||||||
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
import com.simibubi.create.foundation.utility.Pair;
|
||||||
|
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.client.gui.components.AbstractWidget;
|
||||||
|
import net.minecraft.client.gui.components.EditBox;
|
||||||
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.Items;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
public class DataGathererScreen extends AbstractSimiScreen {
|
||||||
|
|
||||||
|
private static final ItemStack FALLBACK = new ItemStack(Items.BARRIER);
|
||||||
|
|
||||||
|
private AllGuiTextures background;
|
||||||
|
private DataGathererTileEntity te;
|
||||||
|
private IconButton confirmButton;
|
||||||
|
|
||||||
|
BlockState sourceState;
|
||||||
|
BlockState targetState;
|
||||||
|
ItemStack sourceIcon = FALLBACK;
|
||||||
|
ItemStack targetIcon = FALLBACK;
|
||||||
|
List<DataGathererSource> sources;
|
||||||
|
DataGathererTarget target;
|
||||||
|
|
||||||
|
ScrollInput sourceTypeSelector;
|
||||||
|
Label sourceTypeLabel;
|
||||||
|
ScrollInput targetLineSelector;
|
||||||
|
Label targetLineLabel;
|
||||||
|
|
||||||
|
Couple<Set<Pair<AbstractWidget, String>>> configWidgets;
|
||||||
|
|
||||||
|
public DataGathererScreen(DataGathererTileEntity te) {
|
||||||
|
this.background = AllGuiTextures.DATA_GATHERER;
|
||||||
|
this.te = te;
|
||||||
|
sources = Collections.emptyList();
|
||||||
|
configWidgets = Couple.create(HashSet::new);
|
||||||
|
target = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
setWindowSize(background.width, background.height);
|
||||||
|
super.init();
|
||||||
|
clearWidgets();
|
||||||
|
|
||||||
|
int x = guiLeft;
|
||||||
|
int y = guiTop;
|
||||||
|
|
||||||
|
if (sourceState == null || targetState == null)
|
||||||
|
initGathererOptions();
|
||||||
|
|
||||||
|
confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM);
|
||||||
|
confirmButton.withCallback(this::onClose);
|
||||||
|
addRenderableWidget(confirmButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
if (sourceState != null && sourceState.getBlock() != minecraft.level.getBlockState(te.getSourcePosition())
|
||||||
|
.getBlock()
|
||||||
|
|| targetState != null && targetState.getBlock() != minecraft.level.getBlockState(te.getTargetPosition())
|
||||||
|
.getBlock())
|
||||||
|
initGathererOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initGathererOptions() {
|
||||||
|
sourceState = minecraft.level.getBlockState(te.getSourcePosition());
|
||||||
|
targetState = minecraft.level.getBlockState(te.getTargetPosition());
|
||||||
|
|
||||||
|
Item asItem;
|
||||||
|
int x = guiLeft;
|
||||||
|
int y = guiTop;
|
||||||
|
|
||||||
|
Block sourceBlock = sourceState.getBlock();
|
||||||
|
Block targetBlock = targetState.getBlock();
|
||||||
|
|
||||||
|
asItem = sourceBlock.asItem();
|
||||||
|
sourceIcon = asItem == null || asItem == Items.AIR ? FALLBACK : new ItemStack(asItem);
|
||||||
|
asItem = targetBlock.asItem();
|
||||||
|
targetIcon = asItem == null || asItem == Items.AIR ? FALLBACK : new ItemStack(asItem);
|
||||||
|
|
||||||
|
sources = AllDataGathererBehaviours.sourcesOf(minecraft.level, te.getSourcePosition());
|
||||||
|
target = AllDataGathererBehaviours.targetOf(minecraft.level, te.getTargetPosition());
|
||||||
|
|
||||||
|
removeWidget(targetLineSelector);
|
||||||
|
removeWidget(targetLineLabel);
|
||||||
|
removeWidget(sourceTypeSelector);
|
||||||
|
removeWidget(sourceTypeLabel);
|
||||||
|
|
||||||
|
configWidgets.forEach(s -> s.forEach(p -> removeWidget(p.getFirst())));
|
||||||
|
|
||||||
|
targetLineSelector = null;
|
||||||
|
sourceTypeSelector = null;
|
||||||
|
|
||||||
|
if (target != null) {
|
||||||
|
DataTargetStats stats = target.provideStats(new DataGathererContext(minecraft.level, te));
|
||||||
|
int rows = stats.maxRows();
|
||||||
|
int startIndex = Math.min(te.targetLine, rows);
|
||||||
|
|
||||||
|
targetLineLabel = new Label(x + 65, y + 109, TextComponent.EMPTY).withShadow();
|
||||||
|
targetLineLabel.text = target.getLineOptionText(startIndex);
|
||||||
|
|
||||||
|
if (rows > 1) {
|
||||||
|
targetLineSelector = new ScrollInput(x + 61, y + 105, 135, 16).withRange(0, rows)
|
||||||
|
.titled(Lang.translate("data_gatherer.display_on"))
|
||||||
|
.inverted()
|
||||||
|
.calling(i -> targetLineLabel.text = target.getLineOptionText(i))
|
||||||
|
.setState(startIndex);
|
||||||
|
addRenderableWidget(targetLineSelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
addRenderableWidget(targetLineLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sources.isEmpty()) {
|
||||||
|
int startIndex = Math.max(sources.indexOf(te.activeSource), 0);
|
||||||
|
|
||||||
|
sourceTypeLabel = new Label(x + 65, y + 30, TextComponent.EMPTY).withShadow();
|
||||||
|
sourceTypeLabel.text = sources.get(startIndex)
|
||||||
|
.getName();
|
||||||
|
|
||||||
|
if (sources.size() > 1) {
|
||||||
|
List<Component> options = sources.stream()
|
||||||
|
.map(DataGathererSource::getName)
|
||||||
|
.toList();
|
||||||
|
sourceTypeSelector = new SelectionScrollInput(x + 61, y + 26, 135, 16).forOptions(options)
|
||||||
|
.writingTo(sourceTypeLabel)
|
||||||
|
.titled(Lang.translate("data_gatherer.information_type"))
|
||||||
|
.calling(this::initGathererSourceSubOptions)
|
||||||
|
.setState(startIndex);
|
||||||
|
sourceTypeSelector.onChanged();
|
||||||
|
addRenderableWidget(sourceTypeSelector);
|
||||||
|
} else
|
||||||
|
initGathererSourceSubOptions(0);
|
||||||
|
|
||||||
|
addRenderableWidget(sourceTypeLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initGathererSourceSubOptions(int i) {
|
||||||
|
DataGathererSource source = sources.get(i);
|
||||||
|
source.populateData(new DataGathererContext(te.getLevel(), te));
|
||||||
|
|
||||||
|
if (targetLineSelector != null)
|
||||||
|
targetLineSelector
|
||||||
|
.titled(source instanceof SingleLineDataSource ? Lang.translate("data_gatherer.display_on")
|
||||||
|
: Lang.translate("data_gatherer.display_on_multiline"));
|
||||||
|
|
||||||
|
configWidgets.forEach(s -> {
|
||||||
|
s.forEach(p -> removeWidget(p.getFirst()));
|
||||||
|
s.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
DataGathererContext context = new DataGathererContext(minecraft.level, te);
|
||||||
|
configWidgets.forEachWithContext((s, first) -> source.initConfigurationWidgets(context,
|
||||||
|
new LineBuilder(s, guiLeft + 60, guiTop + (first ? 51 : 72)), first));
|
||||||
|
|
||||||
|
configWidgets.forEach(s -> s.forEach(p -> {
|
||||||
|
loadValue(te.getSourceConfig(), p);
|
||||||
|
if (p.getFirst() instanceof TooltipArea)
|
||||||
|
addRenderableOnly(p.getFirst());
|
||||||
|
else
|
||||||
|
addRenderableWidget(p.getFirst());
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LineBuilder {
|
||||||
|
|
||||||
|
private Set<Pair<AbstractWidget, String>> targetSet;
|
||||||
|
private int x;
|
||||||
|
private int y;
|
||||||
|
|
||||||
|
public LineBuilder(Set<Pair<AbstractWidget, String>> targetSet, int x, int y) {
|
||||||
|
this.targetSet = targetSet;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineBuilder addScrollInput(int x, int width, BiConsumer<ScrollInput, Label> inputTransform,
|
||||||
|
String dataKey) {
|
||||||
|
ScrollInput input = new ScrollInput(x + this.x, y - 4, width, 18);
|
||||||
|
addScrollInput(input, inputTransform, dataKey);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineBuilder addSelectionScrollInput(int x, int width,
|
||||||
|
BiConsumer<SelectionScrollInput, Label> inputTransform, String dataKey) {
|
||||||
|
SelectionScrollInput input = new SelectionScrollInput(x + this.x, y - 4, width, 18);
|
||||||
|
addScrollInput(input, inputTransform, dataKey);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends ScrollInput> void addScrollInput(T input, BiConsumer<T, Label> inputTransform,
|
||||||
|
String dataKey) {
|
||||||
|
Label label = new Label(input.x + 5, y, TextComponent.EMPTY);
|
||||||
|
label.withShadow();
|
||||||
|
inputTransform.accept(input, label);
|
||||||
|
input.writingTo(label);
|
||||||
|
targetSet.add(Pair.of(label, "Dummy"));
|
||||||
|
targetSet.add(Pair.of(input, dataKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineBuilder addTextInput(int x, int width, BiConsumer<EditBox, TooltipArea> inputTransform,
|
||||||
|
String dataKey) {
|
||||||
|
EditBox input = new EditBox(font, x + this.x + 5, y, width - 9, 8, TextComponent.EMPTY);
|
||||||
|
input.setBordered(false);
|
||||||
|
input.setTextColor(0xffffff);
|
||||||
|
input.changeFocus(false);
|
||||||
|
input.mouseClicked(0, 0, 0);
|
||||||
|
TooltipArea tooltipArea = new TooltipArea(this.x + x, y - 4, width, 18);
|
||||||
|
inputTransform.accept(input, tooltipArea);
|
||||||
|
targetSet.add(Pair.of(input, dataKey));
|
||||||
|
targetSet.add(Pair.of(tooltipArea, "Dummy"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveValue(CompoundTag data, Pair<AbstractWidget, String> widget) {
|
||||||
|
AbstractWidget w = widget.getFirst();
|
||||||
|
String key = widget.getSecond();
|
||||||
|
if (w instanceof EditBox eb)
|
||||||
|
data.putString(key, eb.getValue());
|
||||||
|
if (w instanceof ScrollInput si)
|
||||||
|
data.putInt(key, si.getState());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadValue(CompoundTag data, Pair<AbstractWidget, String> widget) {
|
||||||
|
AbstractWidget w = widget.getFirst();
|
||||||
|
String key = widget.getSecond();
|
||||||
|
if (!data.contains(key))
|
||||||
|
return;
|
||||||
|
if (w instanceof EditBox eb)
|
||||||
|
eb.setValue(data.getString(key));
|
||||||
|
if (w instanceof ScrollInput si)
|
||||||
|
si.setState(data.getInt(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClose() {
|
||||||
|
super.onClose();
|
||||||
|
CompoundTag sourceData = new CompoundTag();
|
||||||
|
|
||||||
|
if (!sources.isEmpty()) {
|
||||||
|
sourceData.putString("Id",
|
||||||
|
sources.get(sourceTypeSelector == null ? 0 : sourceTypeSelector.getState()).id.toString());
|
||||||
|
configWidgets.forEach(s -> s.forEach(p -> saveValue(sourceData, p)));
|
||||||
|
}
|
||||||
|
|
||||||
|
AllPackets.channel.sendToServer(new DataGathererConfigurationPacket(te.getBlockPos(), sourceData,
|
||||||
|
targetLineSelector == null ? 0 : targetLineSelector.getState()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
int x = guiLeft;
|
||||||
|
int y = guiTop;
|
||||||
|
|
||||||
|
background.render(ms, x, y, this);
|
||||||
|
MutableComponent header = Lang.translate("data_gatherer.title");
|
||||||
|
font.draw(ms, header, x + background.width / 2 - font.width(header) / 2, y + 4, 0x442000);
|
||||||
|
|
||||||
|
if (sources.isEmpty())
|
||||||
|
font.drawShadow(ms, Lang.translate("data_gatherer.no_source"), x + 65, y + 30, 0xD3D3D3);
|
||||||
|
if (target == null)
|
||||||
|
font.drawShadow(ms, Lang.translate("data_gatherer.no_target"), x + 65, y + 109, 0xD3D3D3);
|
||||||
|
|
||||||
|
if (!sourceIcon.isEmpty())
|
||||||
|
minecraft.getItemRenderer()
|
||||||
|
.renderGuiItem(sourceIcon, x + 37, y + 26);
|
||||||
|
if (!targetIcon.isEmpty())
|
||||||
|
minecraft.getItemRenderer()
|
||||||
|
.renderGuiItem(targetIcon, x + 37, y + 105);
|
||||||
|
|
||||||
|
configWidgets.forEachWithContext((s, first) -> s.forEach(p -> {
|
||||||
|
if (p.getSecond()
|
||||||
|
.equals("Dummy"))
|
||||||
|
return;
|
||||||
|
renderWidgetBG(ms, p.getFirst(), first);
|
||||||
|
}));
|
||||||
|
|
||||||
|
ms.pushPose();
|
||||||
|
TransformStack.cast(ms)
|
||||||
|
.pushPose()
|
||||||
|
.translate(x + background.width + 4, y + background.height + 4, 100)
|
||||||
|
.scale(40)
|
||||||
|
.rotateX(-22)
|
||||||
|
.rotateY(63);
|
||||||
|
GuiGameElement.of(te.getBlockState()
|
||||||
|
.setValue(DataGathererBlock.FACING, Direction.UP))
|
||||||
|
.render(ms);
|
||||||
|
ms.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderWidgetBG(PoseStack ms, AbstractWidget aw, boolean firstLine) {
|
||||||
|
int x = aw.x;
|
||||||
|
int width = aw.getWidth();
|
||||||
|
int y = guiTop + (firstLine ? 46 : 67);
|
||||||
|
|
||||||
|
if (aw instanceof EditBox) {
|
||||||
|
x -= 5;
|
||||||
|
width += 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIRenderHelper.drawStretched(ms, x, y, width, 18, -100, AllGuiTextures.DATA_AREA);
|
||||||
|
AllGuiTextures.DATA_AREA_START.render(ms, x, y);
|
||||||
|
AllGuiTextures.DATA_AREA_END.render(ms, x + width - 2, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderWindowForeground(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
super.renderWindowForeground(ms, mouseX, mouseY, partialTicks);
|
||||||
|
int mX = mouseX - guiLeft;
|
||||||
|
int mY = mouseY - guiTop;
|
||||||
|
|
||||||
|
if (sourceState != null && mX >= 33 && mX < 53 && mY >= 24 && mY < 44) {
|
||||||
|
renderComponentTooltip(ms,
|
||||||
|
ImmutableList.of(Lang.translate("data_gatherer.reading_from"), sourceState.getBlock()
|
||||||
|
.getName()
|
||||||
|
.withStyle(s -> s.withColor(sources.isEmpty() ? 0xF68989 : 0xF2C16D)),
|
||||||
|
Lang.translate("data_gatherer.attached_side"), Lang.translate("data_gatherer.view_compatible")
|
||||||
|
.withStyle(ChatFormatting.GRAY)),
|
||||||
|
mouseX, mouseY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetState != null && mX >= 33 && mX < 53 && mY >= 102 && mY < 122) {
|
||||||
|
renderComponentTooltip(ms,
|
||||||
|
ImmutableList.of(Lang.translate("data_gatherer.writing_to"), targetState.getBlock()
|
||||||
|
.getName()
|
||||||
|
.withStyle(s -> s.withColor(target == null ? 0xF68989 : 0xF2C16D)),
|
||||||
|
Lang.translate("data_gatherer.targeted_location"), Lang.translate("data_gatherer.view_compatible")
|
||||||
|
.withStyle(ChatFormatting.GRAY)),
|
||||||
|
mouseX, mouseY);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void removeWidget(GuiEventListener p_169412_) {
|
||||||
|
if (p_169412_ != null)
|
||||||
|
super.removeWidget(p_169412_);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,172 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.DataGathererSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataGathererTarget;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.NbtUtils;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
public class DataGathererTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
|
protected BlockPos targetOffset;
|
||||||
|
|
||||||
|
public DataGathererSource activeSource;
|
||||||
|
private CompoundTag sourceConfig;
|
||||||
|
|
||||||
|
public DataGathererTarget activeTarget;
|
||||||
|
public int targetLine;
|
||||||
|
|
||||||
|
public int refreshTicks;
|
||||||
|
|
||||||
|
public DataGathererTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||||
|
super(type, pos, state);
|
||||||
|
targetOffset = BlockPos.ZERO;
|
||||||
|
sourceConfig = new CompoundTag();
|
||||||
|
targetLine = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
|
||||||
|
if (activeSource == null)
|
||||||
|
return;
|
||||||
|
if (level.isClientSide)
|
||||||
|
return;
|
||||||
|
refreshTicks++;
|
||||||
|
if (refreshTicks < activeSource.getPassiveRefreshTicks())
|
||||||
|
return;
|
||||||
|
tickSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tickSource() {
|
||||||
|
refreshTicks = 0;
|
||||||
|
if (getBlockState().getOptionalValue(DataGathererBlock.POWERED)
|
||||||
|
.orElse(true))
|
||||||
|
return;
|
||||||
|
if (!level.isClientSide)
|
||||||
|
updateGatheredData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onNoLongerPowered() {
|
||||||
|
if (activeSource == null)
|
||||||
|
return;
|
||||||
|
refreshTicks = 0;
|
||||||
|
activeSource.onSignalReset(new DataGathererContext(level, this));
|
||||||
|
updateGatheredData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateGatheredData() {
|
||||||
|
BlockPos sourcePosition = getSourcePosition();
|
||||||
|
BlockPos targetPosition = getTargetPosition();
|
||||||
|
|
||||||
|
if (!level.isAreaLoaded(targetPosition, 1) || !level.isAreaLoaded(sourcePosition, 1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
DataGathererTarget target = AllDataGathererBehaviours.targetOf(level, targetPosition);
|
||||||
|
List<DataGathererSource> sources = AllDataGathererBehaviours.sourcesOf(level, sourcePosition);
|
||||||
|
boolean notify = false;
|
||||||
|
|
||||||
|
if (activeTarget != target) {
|
||||||
|
activeTarget = target;
|
||||||
|
notify = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeSource != null && !sources.contains(activeSource)) {
|
||||||
|
activeSource = null;
|
||||||
|
sourceConfig = new CompoundTag();
|
||||||
|
notify = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notify)
|
||||||
|
notifyUpdate();
|
||||||
|
if (activeSource == null || activeTarget == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DataGathererContext context = new DataGathererContext(level, this);
|
||||||
|
activeSource.transferData(context, activeTarget, targetLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeSafe(CompoundTag tag, boolean clientPacket) {
|
||||||
|
super.writeSafe(tag, clientPacket);
|
||||||
|
writeGatheredData(tag, clientPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void write(CompoundTag tag, boolean clientPacket) {
|
||||||
|
super.write(tag, clientPacket);
|
||||||
|
writeGatheredData(tag, clientPacket);
|
||||||
|
if (clientPacket && activeTarget != null)
|
||||||
|
tag.putString("TargetType", activeTarget.id.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeGatheredData(CompoundTag tag, boolean clientPacket) {
|
||||||
|
tag.put("TargetOffset", NbtUtils.writeBlockPos(targetOffset));
|
||||||
|
tag.putInt("TargetLine", targetLine);
|
||||||
|
|
||||||
|
if (activeSource != null) {
|
||||||
|
CompoundTag data = sourceConfig.copy();
|
||||||
|
data.putString("Id", activeSource.id.toString());
|
||||||
|
tag.put("Source", data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void read(CompoundTag tag, boolean clientPacket) {
|
||||||
|
super.read(tag, clientPacket);
|
||||||
|
targetOffset = NbtUtils.readBlockPos(tag.getCompound("TargetOffset"));
|
||||||
|
targetLine = tag.getInt("TargetLine");
|
||||||
|
|
||||||
|
if (clientPacket && tag.contains("TargetType"))
|
||||||
|
activeTarget = AllDataGathererBehaviours.getTarget(new ResourceLocation(tag.getString("TargetType")));
|
||||||
|
|
||||||
|
if (!tag.contains("Source"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CompoundTag data = tag.getCompound("Source");
|
||||||
|
activeSource = AllDataGathererBehaviours.getSource(new ResourceLocation(data.getString("Id")));
|
||||||
|
sourceConfig = new CompoundTag();
|
||||||
|
if (activeSource != null)
|
||||||
|
sourceConfig = data.copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void target(BlockPos targetPosition) {
|
||||||
|
this.targetOffset = targetPosition.subtract(worldPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockPos getSourcePosition() {
|
||||||
|
return worldPosition.relative(getDirection());
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundTag getSourceConfig() {
|
||||||
|
return sourceConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSourceConfig(CompoundTag sourceConfig) {
|
||||||
|
this.sourceConfig = sourceConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Direction getDirection() {
|
||||||
|
return getBlockState().getOptionalValue(DataGathererBlock.FACING)
|
||||||
|
.orElse(Direction.UP)
|
||||||
|
.getOpposite();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockPos getTargetPosition() {
|
||||||
|
return worldPosition.offset(targetOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererBlock;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererTileEntity;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataTargetStats;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
|
||||||
|
public class AccumulatedItemCountDataSource extends NumericSingleLineDataSource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MutableComponent provideLine(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
return new TextComponent(String.valueOf(context.sourceConfig()
|
||||||
|
.getInt("Collected")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void itemReceived(DataGathererTileEntity te, int amount) {
|
||||||
|
if (te.getBlockState()
|
||||||
|
.getOptionalValue(DataGathererBlock.POWERED)
|
||||||
|
.orElse(true))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int collected = te.getSourceConfig()
|
||||||
|
.getInt("Collected");
|
||||||
|
te.getSourceConfig()
|
||||||
|
.putInt("Collected", collected + amount);
|
||||||
|
te.updateGatheredData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey() {
|
||||||
|
return "accumulate_items";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPassiveRefreshTicks() {
|
||||||
|
return 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSignalReset(DataGathererContext context) {
|
||||||
|
context.sourceConfig()
|
||||||
|
.remove("Collected");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean allowsLabeling(DataGathererContext context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererBehaviour;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererScreen.LineBuilder;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataGathererTarget;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataTargetStats;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.FlapDisplayDataTarget;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.network.chat.TranslatableComponent;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public abstract class DataGathererSource extends DataGathererBehaviour {
|
||||||
|
|
||||||
|
public static final List<MutableComponent> EMPTY = ImmutableList.of(new TextComponent(""));
|
||||||
|
public static final MutableComponent EMPTY_LINE = new TextComponent("");
|
||||||
|
public static final MutableComponent WHITESPACE = new TextComponent(" ");
|
||||||
|
|
||||||
|
public abstract List<MutableComponent> provideText(DataGathererContext context, DataTargetStats stats);
|
||||||
|
|
||||||
|
public void transferData(DataGathererContext context, DataGathererTarget activeTarget, int line) {
|
||||||
|
DataTargetStats stats = activeTarget.provideStats(context);
|
||||||
|
|
||||||
|
if (activeTarget instanceof FlapDisplayDataTarget fddt) {
|
||||||
|
List<List<MutableComponent>> flapDisplayText = provideFlapDisplayText(context, stats);
|
||||||
|
fddt.acceptFlapText(line, flapDisplayText, context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MutableComponent> text = provideText(context, stats);
|
||||||
|
activeTarget.acceptText(line, text, context);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSignalReset(DataGathererContext context) {};
|
||||||
|
|
||||||
|
public void populateData(DataGathererContext context) {};
|
||||||
|
|
||||||
|
public int getPassiveRefreshTicks() {
|
||||||
|
return 100;
|
||||||
|
};
|
||||||
|
|
||||||
|
protected String getTranslationKey() {
|
||||||
|
return id.getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getName() {
|
||||||
|
return new TranslatableComponent(id.getNamespace() + ".data_source." + getTranslationKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadFlapDisplayLayout(DataGathererContext context, FlapDisplayTileEntity flapDisplay,
|
||||||
|
FlapDisplayLayout layout) {
|
||||||
|
if (!layout.isLayout("Default"))
|
||||||
|
layout.loadDefault(flapDisplay.getMaxCharCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<List<MutableComponent>> provideFlapDisplayText(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
return provideText(context, stats).stream()
|
||||||
|
.map(Arrays::asList)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void initConfigurationWidgets(DataGathererContext context, LineBuilder builder, boolean isFirstLine) {}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.stats.Stats;
|
||||||
|
|
||||||
|
public class DeathCounterDataSource extends StatTrackingDataSource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int updatedScoreOf(ServerPlayer player) {
|
||||||
|
return player.getStats()
|
||||||
|
.getValue(Stats.CUSTOM.get(Stats.DEATHS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey() {
|
||||||
|
return "player_deaths";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getObjectiveName() {
|
||||||
|
return "deaths";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Component getObjectiveDisplayName() {
|
||||||
|
return Lang.translate("data_source.scoreboard.objective.deaths");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import static com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection.WIDE_MONOSPACE;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererScreen.LineBuilder;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataTargetStats;
|
||||||
|
import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchTileEntity;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.entity.SignBlockEntity;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public class FillLevelDataSource extends NumericSingleLineDataSource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MutableComponent provideLine(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
BlockEntity te = context.getSourceTE();
|
||||||
|
if (!(te instanceof StockpileSwitchTileEntity sste))
|
||||||
|
return EMPTY_LINE;
|
||||||
|
|
||||||
|
float currentLevel = sste.currentLevel;
|
||||||
|
if (usePercent(context))
|
||||||
|
return new TextComponent(Mth.clamp((int) (currentLevel * 100), 0, 100) + "%");
|
||||||
|
|
||||||
|
String label = context.sourceConfig()
|
||||||
|
.getString("Label");
|
||||||
|
|
||||||
|
int labelSize = label.isEmpty() ? 0 : label.length() + 1;
|
||||||
|
int length = Math.min(stats.maxColumns() - labelSize, 32);
|
||||||
|
|
||||||
|
if (context.getTargetTE() instanceof SignBlockEntity)
|
||||||
|
length = (int) (length * 6f / 9f);
|
||||||
|
if (context.getTargetTE() instanceof FlapDisplayTileEntity)
|
||||||
|
length = sizeForWideChars(length);
|
||||||
|
|
||||||
|
int filledLength = (int) (currentLevel * length);
|
||||||
|
|
||||||
|
if (length < 1)
|
||||||
|
return EMPTY_LINE;
|
||||||
|
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
int emptySpaces = length - filledLength;
|
||||||
|
for (int i = 0; i < filledLength; i++)
|
||||||
|
s.append("\u2588");
|
||||||
|
for (int i = 0; i < emptySpaces; i++)
|
||||||
|
s.append("\u2592");
|
||||||
|
|
||||||
|
return new TextComponent(s.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean usePercent(DataGathererContext context) {
|
||||||
|
return context.sourceConfig()
|
||||||
|
.getInt("Mode") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey() {
|
||||||
|
return "fill_level";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFlapDisplayLayoutName(DataGathererContext context) {
|
||||||
|
return usePercent(context) ? super.getFlapDisplayLayoutName(context) : "Progress";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FlapDisplaySection createSectionForValue(DataGathererContext context, int size) {
|
||||||
|
return usePercent(context) ? super.createSectionForValue(context, size)
|
||||||
|
: new FlapDisplaySection(size * FlapDisplaySection.MONOSPACE, "pixel", false, false).wideFlaps();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int sizeForWideChars(int size) {
|
||||||
|
return (int) (size * FlapDisplaySection.MONOSPACE / WIDE_MONOSPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void initConfigurationWidgets(DataGathererContext context, LineBuilder builder, boolean isFirstLine) {
|
||||||
|
super.initConfigurationWidgets(context, builder, isFirstLine);
|
||||||
|
if (isFirstLine)
|
||||||
|
return;
|
||||||
|
builder.addSelectionScrollInput(0, 120,
|
||||||
|
(si, l) -> si.forOptions(Lang.translatedOptions("data_source.fill_level", "percent", "progress_bar"))
|
||||||
|
.titled(Lang.translate("data_source.fill_level.display")),
|
||||||
|
"Mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean allowsLabeling(DataGathererContext context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataTargetStats;
|
||||||
|
import com.simibubi.create.content.logistics.block.redstone.ContentObserverTileEntity;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
|
||||||
|
public class ItemCountDataSource extends NumericSingleLineDataSource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MutableComponent provideLine(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
BlockEntity sourceTE = context.getSourceTE();
|
||||||
|
if (!(sourceTE instanceof ContentObserverTileEntity cote))
|
||||||
|
return ZERO;
|
||||||
|
|
||||||
|
InvManipulationBehaviour invManipulationBehaviour = cote.getBehaviour(InvManipulationBehaviour.TYPE);
|
||||||
|
FilteringBehaviour filteringBehaviour = cote.getBehaviour(FilteringBehaviour.TYPE);
|
||||||
|
IItemHandler handler = invManipulationBehaviour.getInventory();
|
||||||
|
|
||||||
|
if (handler == null)
|
||||||
|
return ZERO;
|
||||||
|
|
||||||
|
int collected = 0;
|
||||||
|
for (int i = 0; i < handler.getSlots(); i++) {
|
||||||
|
ItemStack stack = handler.extractItem(i, handler.getSlotLimit(i), true);
|
||||||
|
if (stack.isEmpty())
|
||||||
|
continue;
|
||||||
|
if (!filteringBehaviour.test(stack))
|
||||||
|
continue;
|
||||||
|
collected += stack.getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TextComponent(String.valueOf(collected));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey() {
|
||||||
|
return "count_items";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean allowsLabeling(DataGathererContext context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.redstone.ContentObserverTileEntity;
|
||||||
|
import com.simibubi.create.foundation.item.CountedItemStackList;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour;
|
||||||
|
import com.simibubi.create.foundation.utility.IntAttached;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
|
||||||
|
public class ItemListDataSource extends ValueListDataSource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<IntAttached<MutableComponent>> provideEntries(DataGathererContext context, int maxRows) {
|
||||||
|
BlockEntity sourceTE = context.getSourceTE();
|
||||||
|
if (!(sourceTE instanceof ContentObserverTileEntity cote))
|
||||||
|
return new ArrayList<IntAttached<MutableComponent>>().stream();
|
||||||
|
|
||||||
|
InvManipulationBehaviour invManipulationBehaviour = cote.getBehaviour(InvManipulationBehaviour.TYPE);
|
||||||
|
FilteringBehaviour filteringBehaviour = cote.getBehaviour(FilteringBehaviour.TYPE);
|
||||||
|
IItemHandler handler = invManipulationBehaviour.getInventory();
|
||||||
|
|
||||||
|
if (handler == null)
|
||||||
|
return new ArrayList<IntAttached<MutableComponent>>().stream();
|
||||||
|
|
||||||
|
return new CountedItemStackList(handler, filteringBehaviour).getTopNames(maxRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey() {
|
||||||
|
return "list_items";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean valueFirst() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.mutable.MutableObject;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererTileEntity;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataTargetStats;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
public class ItemNameDataSource extends SingleLineDataSource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MutableComponent provideLine(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
DataGathererTileEntity gatherer = context.te();
|
||||||
|
Direction direction = gatherer.getDirection();
|
||||||
|
MutableBlockPos pos = gatherer.getSourcePosition()
|
||||||
|
.mutable();
|
||||||
|
|
||||||
|
MutableComponent combined = EMPTY_LINE.copy();
|
||||||
|
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
TransportedItemStackHandlerBehaviour behaviour =
|
||||||
|
TileEntityBehaviour.get(context.level(), pos, TransportedItemStackHandlerBehaviour.TYPE);
|
||||||
|
pos.move(direction);
|
||||||
|
|
||||||
|
if (behaviour == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
MutableObject<ItemStack> stackHolder = new MutableObject<>();
|
||||||
|
behaviour.handleCenteredProcessingOnAllItems(.25f, tis -> {
|
||||||
|
stackHolder.setValue(tis.stack);
|
||||||
|
return TransportedResult.doNothing();
|
||||||
|
});
|
||||||
|
|
||||||
|
ItemStack stack = stackHolder.getValue();
|
||||||
|
if (stack != null && !stack.isEmpty())
|
||||||
|
combined = combined.append(stack.getHoverName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return combined;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey() {
|
||||||
|
return "combine_item_names";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean allowsLabeling(DataGathererContext context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFlapDisplayLayoutName(DataGathererContext context) {
|
||||||
|
return "Number";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererBlock;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererScreen.LineBuilder;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererTileEntity;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataTargetStats;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.FloatTag;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public class ItemThoughputDataSource extends AccumulatedItemCountDataSource {
|
||||||
|
|
||||||
|
static final int POOL_SIZE = 10;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MutableComponent provideLine(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
CompoundTag conf = context.sourceConfig();
|
||||||
|
if (conf.contains("Inactive"))
|
||||||
|
return new TextComponent("0");
|
||||||
|
|
||||||
|
double interval = 20 * Math.pow(60, conf.getInt("Interval"));
|
||||||
|
double rate = conf.getFloat("Rate") * interval;
|
||||||
|
|
||||||
|
if (rate > 0) {
|
||||||
|
long previousTime = conf.getLong("LastReceived");
|
||||||
|
long gameTime = context.te()
|
||||||
|
.getLevel()
|
||||||
|
.getGameTime();
|
||||||
|
int diff = (int) (gameTime - previousTime);
|
||||||
|
if (diff > 0) {
|
||||||
|
// Too long since last item
|
||||||
|
int lastAmount = conf.getInt("LastReceivedAmount");
|
||||||
|
double timeBetweenStacks = lastAmount / rate;
|
||||||
|
if (diff > timeBetweenStacks * 2)
|
||||||
|
conf.putBoolean("Inactive", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TextComponent(IHaveGoggleInformation.format(rate));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void itemReceived(DataGathererTileEntity te, int amount) {
|
||||||
|
if (te.getBlockState()
|
||||||
|
.getOptionalValue(DataGathererBlock.POWERED)
|
||||||
|
.orElse(true))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CompoundTag conf = te.getSourceConfig();
|
||||||
|
long gameTime = te.getLevel()
|
||||||
|
.getGameTime();
|
||||||
|
|
||||||
|
if (!conf.contains("LastReceived")) {
|
||||||
|
conf.putLong("LastReceived", gameTime);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long previousTime = conf.getLong("LastReceived");
|
||||||
|
ListTag rates = conf.getList("PrevRates", Tag.TAG_FLOAT);
|
||||||
|
|
||||||
|
if (rates.size() != POOL_SIZE) {
|
||||||
|
rates = new ListTag();
|
||||||
|
for (int i = 0; i < POOL_SIZE; i++)
|
||||||
|
rates.add(FloatTag.valueOf(-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
int poolIndex = conf.getInt("Index") % POOL_SIZE;
|
||||||
|
rates.set(poolIndex, FloatTag.valueOf((float) (amount / (double) (gameTime - previousTime))));
|
||||||
|
|
||||||
|
float rate = 0;
|
||||||
|
int validIntervals = 0;
|
||||||
|
for (int i = 0; i < POOL_SIZE; i++) {
|
||||||
|
float pooledRate = rates.getFloat(i);
|
||||||
|
if (pooledRate >= 0) {
|
||||||
|
rate += pooledRate;
|
||||||
|
validIntervals++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conf.remove("Rate");
|
||||||
|
if (validIntervals > 0) {
|
||||||
|
rate /= validIntervals;
|
||||||
|
conf.putFloat("Rate", rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
conf.remove("Inactive");
|
||||||
|
conf.putInt("LastReceivedAmount", amount);
|
||||||
|
conf.putLong("LastReceived", gameTime);
|
||||||
|
conf.putInt("Index", poolIndex + 1);
|
||||||
|
conf.put("PrevRates", rates);
|
||||||
|
te.updateGatheredData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void initConfigurationWidgets(DataGathererContext context, LineBuilder builder, boolean isFirstLine) {
|
||||||
|
super.initConfigurationWidgets(context, builder, isFirstLine);
|
||||||
|
if (isFirstLine)
|
||||||
|
return;
|
||||||
|
|
||||||
|
builder.addSelectionScrollInput(0, 80, (si, l) -> {
|
||||||
|
si.forOptions(Lang.translatedOptions("data_source.item_throughput.interval", "second", "minute", "hour"))
|
||||||
|
.titled(Lang.translate("data_source.item_throughput.interval"));
|
||||||
|
}, "Interval");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey() {
|
||||||
|
return "item_throughput";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataTargetStats;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.NixieTubeDataTarget;
|
||||||
|
import com.simibubi.create.content.logistics.block.redstone.NixieTubeTileEntity;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
|
||||||
|
public class NixieTubeDataSource extends SingleLineDataSource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey() {
|
||||||
|
return "nixie_tube";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MutableComponent provideLine(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
BlockEntity sourceTE = context.getSourceTE();
|
||||||
|
if (!(sourceTE instanceof NixieTubeTileEntity nte))
|
||||||
|
return EMPTY_LINE;
|
||||||
|
|
||||||
|
MutableComponent text = nte.getFullText();
|
||||||
|
|
||||||
|
try {
|
||||||
|
String line = text.getString();
|
||||||
|
Integer.valueOf(line);
|
||||||
|
context.flapDisplayContext = Boolean.TRUE;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean allowsLabeling(DataGathererContext context) {
|
||||||
|
return !(context.te().activeTarget instanceof NixieTubeDataTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFlapDisplayLayoutName(DataGathererContext context) {
|
||||||
|
if (isNumeric(context))
|
||||||
|
return "Number";
|
||||||
|
return super.getFlapDisplayLayoutName(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FlapDisplaySection createSectionForValue(DataGathererContext context, int size) {
|
||||||
|
if (isNumeric(context))
|
||||||
|
return new FlapDisplaySection(size * FlapDisplaySection.MONOSPACE, "numeric", false, false);
|
||||||
|
return super.createSectionForValue(context, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isNumeric(DataGathererContext context) {
|
||||||
|
return context.flapDisplayContext == Boolean.TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
|
||||||
|
public abstract class NumericSingleLineDataSource extends SingleLineDataSource {
|
||||||
|
|
||||||
|
protected static final TextComponent ZERO = new TextComponent("0");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFlapDisplayLayoutName(DataGathererContext context) {
|
||||||
|
return "Number";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FlapDisplaySection createSectionForValue(DataGathererContext context, int size) {
|
||||||
|
return new FlapDisplaySection(size * FlapDisplaySection.MONOSPACE, "numeric", false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererScreen.LineBuilder;
|
||||||
|
import com.simibubi.create.foundation.utility.IntAttached;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.scores.Objective;
|
||||||
|
|
||||||
|
public class ScoreboardDataSource extends ValueListDataSource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<IntAttached<MutableComponent>> provideEntries(DataGathererContext context, int maxRows) {
|
||||||
|
Level level = context.te()
|
||||||
|
.getLevel();
|
||||||
|
if (!(level instanceof ServerLevel sLevel))
|
||||||
|
return new ArrayList<IntAttached<MutableComponent>>().stream();
|
||||||
|
|
||||||
|
String name = context.sourceConfig()
|
||||||
|
.getString("Objective");
|
||||||
|
|
||||||
|
return showScoreboard(sLevel, name, maxRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Stream<IntAttached<MutableComponent>> showScoreboard(ServerLevel sLevel, String objectiveName,
|
||||||
|
int maxRows) {
|
||||||
|
Objective objective = sLevel.getScoreboard()
|
||||||
|
.getObjective(objectiveName);
|
||||||
|
if (objective == null)
|
||||||
|
return notFound(objectiveName).stream();
|
||||||
|
|
||||||
|
return sLevel.getScoreboard()
|
||||||
|
.getPlayerScores(objective)
|
||||||
|
.stream()
|
||||||
|
.limit(maxRows)
|
||||||
|
.map(score -> IntAttached.with(score.getScore(), new TextComponent(score.getOwner()).copy()))
|
||||||
|
.sorted(IntAttached.comparator());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImmutableList<IntAttached<MutableComponent>> notFound(String objective) {
|
||||||
|
return ImmutableList
|
||||||
|
.of(IntAttached.with(404, Lang.translate("data_source.scoreboard.objective_not_found", objective)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey() {
|
||||||
|
return "scoreboard";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initConfigurationWidgets(DataGathererContext context, LineBuilder builder, boolean isFirstLine) {
|
||||||
|
if (isFirstLine)
|
||||||
|
builder.addTextInput(0, 137, (e, t) -> {
|
||||||
|
e.setValue("");
|
||||||
|
t.withTooltip(ImmutableList.of(Lang.translate("data_source.scoreboard.objective")
|
||||||
|
.withStyle(s -> s.withColor(0x5391E1)),
|
||||||
|
Lang.translate("gui.schedule.lmb_edit")
|
||||||
|
.withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC)));
|
||||||
|
}, "Objective");
|
||||||
|
else
|
||||||
|
addFullNumberConfig(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean valueFirst() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererScreen.LineBuilder;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataTargetStats;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public abstract class SingleLineDataSource extends DataGathererSource {
|
||||||
|
|
||||||
|
protected abstract MutableComponent provideLine(DataGathererContext context, DataTargetStats stats);
|
||||||
|
|
||||||
|
protected abstract boolean allowsLabeling(DataGathererContext context);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void initConfigurationWidgets(DataGathererContext context, LineBuilder builder, boolean isFirstLine) {
|
||||||
|
if (isFirstLine && allowsLabeling(context))
|
||||||
|
addLabelingTextBox(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
protected void addLabelingTextBox(LineBuilder builder) {
|
||||||
|
builder.addTextInput(0, 137, (e, t) -> {
|
||||||
|
e.setValue("");
|
||||||
|
t.withTooltip(ImmutableList.of(Lang.translate("data_source.label")
|
||||||
|
.withStyle(s -> s.withColor(0x5391E1)),
|
||||||
|
Lang.translate("gui.schedule.lmb_edit")
|
||||||
|
.withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC)));
|
||||||
|
}, "Label");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MutableComponent> provideText(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
MutableComponent line = provideLine(context, stats);
|
||||||
|
if (line == EMPTY_LINE)
|
||||||
|
return EMPTY;
|
||||||
|
|
||||||
|
if (allowsLabeling(context)) {
|
||||||
|
String label = context.sourceConfig()
|
||||||
|
.getString("Label");
|
||||||
|
if (!label.isEmpty())
|
||||||
|
line = new TextComponent(label + " ").append(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImmutableList.of(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<List<MutableComponent>> provideFlapDisplayText(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
|
||||||
|
if (allowsLabeling(context)) {
|
||||||
|
String label = context.sourceConfig()
|
||||||
|
.getString("Label");
|
||||||
|
if (!label.isEmpty())
|
||||||
|
return ImmutableList.of(ImmutableList.of(new TextComponent(label + " "), provideLine(context, stats)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.provideFlapDisplayText(context, stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadFlapDisplayLayout(DataGathererContext context, FlapDisplayTileEntity flapDisplay,
|
||||||
|
FlapDisplayLayout layout) {
|
||||||
|
String layoutKey = getFlapDisplayLayoutName(context);
|
||||||
|
|
||||||
|
if (!allowsLabeling(context)) {
|
||||||
|
if (!layout.isLayout(layoutKey))
|
||||||
|
layout.configure(layoutKey,
|
||||||
|
ImmutableList.of(createSectionForValue(context, flapDisplay.getMaxCharCount())));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String label = context.sourceConfig()
|
||||||
|
.getString("Label");
|
||||||
|
|
||||||
|
if (label.isEmpty()) {
|
||||||
|
if (!layout.isLayout(layoutKey))
|
||||||
|
layout.configure(layoutKey,
|
||||||
|
ImmutableList.of(createSectionForValue(context, flapDisplay.getMaxCharCount())));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String layoutName = label.length() + "_Labeled_" + layoutKey;
|
||||||
|
if (layout.isLayout(layoutName))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int maxCharCount = flapDisplay.getMaxCharCount();
|
||||||
|
FlapDisplaySection labelSection = new FlapDisplaySection(
|
||||||
|
Math.min(maxCharCount, label.length() + 1) * FlapDisplaySection.MONOSPACE, "alphabet", false, false);
|
||||||
|
|
||||||
|
if (label.length() + 1 < maxCharCount)
|
||||||
|
layout.configure(layoutName,
|
||||||
|
ImmutableList.of(labelSection, createSectionForValue(context, maxCharCount - label.length() - 1)));
|
||||||
|
else
|
||||||
|
layout.configure(layoutName, ImmutableList.of(labelSection));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getFlapDisplayLayoutName(DataGathererContext context) {
|
||||||
|
return "Default";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FlapDisplaySection createSectionForValue(DataGathererContext context, int size) {
|
||||||
|
return new FlapDisplaySection(size * FlapDisplaySection.MONOSPACE, "alphabet", false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererScreen.LineBuilder;
|
||||||
|
import com.simibubi.create.foundation.utility.IntAttached;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.scores.Objective;
|
||||||
|
import net.minecraft.world.scores.Scoreboard;
|
||||||
|
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
|
||||||
|
import net.minecraft.world.scores.criteria.ObjectiveCriteria.RenderType;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public abstract class StatTrackingDataSource extends ScoreboardDataSource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<IntAttached<MutableComponent>> provideEntries(DataGathererContext context, int maxRows) {
|
||||||
|
Level level = context.te()
|
||||||
|
.getLevel();
|
||||||
|
if (!(level instanceof ServerLevel sLevel))
|
||||||
|
return new ArrayList<IntAttached<MutableComponent>>().stream();
|
||||||
|
|
||||||
|
String name = "create_auto_" + getObjectiveName();
|
||||||
|
Scoreboard scoreboard = level.getScoreboard();
|
||||||
|
if (!scoreboard.hasObjective(name))
|
||||||
|
scoreboard.addObjective(name, ObjectiveCriteria.DUMMY, getObjectiveDisplayName(), RenderType.INTEGER);
|
||||||
|
Objective objective = scoreboard.getObjective(name);
|
||||||
|
|
||||||
|
sLevel.players()
|
||||||
|
.forEach(s -> scoreboard.getOrCreatePlayerScore(s.getScoreboardName(), objective)
|
||||||
|
.setScore(updatedScoreOf(s)));
|
||||||
|
|
||||||
|
return showScoreboard(sLevel, name, maxRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String getObjectiveName();
|
||||||
|
|
||||||
|
protected abstract Component getObjectiveDisplayName();
|
||||||
|
|
||||||
|
protected abstract int updatedScoreOf(ServerPlayer player);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean valueFirst() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean shortenNumbers(DataGathererContext context) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void initConfigurationWidgets(DataGathererContext context, LineBuilder builder, boolean isFirstLine) {}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,203 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import static com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection.MONOSPACE;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererScreen.LineBuilder;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataTargetStats;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.GlobalTrainDisplayData;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public class StationSummaryDataSource extends DataGathererSource {
|
||||||
|
|
||||||
|
protected static final MutableComponent UNPREDICTABLE = new TextComponent(" ~ ");
|
||||||
|
|
||||||
|
protected static final List<MutableComponent> EMPTY_ENTRY_4 =
|
||||||
|
ImmutableList.of(WHITESPACE, new TextComponent(" . "), WHITESPACE, WHITESPACE);
|
||||||
|
protected static final List<MutableComponent> EMPTY_ENTRY_5 =
|
||||||
|
ImmutableList.of(WHITESPACE, new TextComponent(" . "), WHITESPACE, WHITESPACE, WHITESPACE);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MutableComponent> provideText(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
return EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<List<MutableComponent>> provideFlapDisplayText(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
String filter = context.sourceConfig()
|
||||||
|
.getString("Filter");
|
||||||
|
boolean hasPlatform = filter.contains("*");
|
||||||
|
|
||||||
|
List<List<MutableComponent>> list = new ArrayList<>();
|
||||||
|
GlobalTrainDisplayData.prepare(filter, stats.maxRows())
|
||||||
|
.forEach(prediction -> {
|
||||||
|
List<MutableComponent> lines = new ArrayList<>();
|
||||||
|
|
||||||
|
if (prediction.ticks == -1 || prediction.ticks >= 12000 - 15 * 20) {
|
||||||
|
lines.add(WHITESPACE);
|
||||||
|
lines.add(UNPREDICTABLE);
|
||||||
|
|
||||||
|
} else if (prediction.ticks < 200) {
|
||||||
|
lines.add(WHITESPACE);
|
||||||
|
lines.add(Lang.translate("data_source.station_summary.now"));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
int min = prediction.ticks / 1200;
|
||||||
|
int sec = (prediction.ticks / 20) % 60;
|
||||||
|
sec = Mth.ceil(sec / 15f) * 15;
|
||||||
|
if (sec == 60) {
|
||||||
|
min++;
|
||||||
|
sec = 0;
|
||||||
|
}
|
||||||
|
lines.add(min > 0 ? new TextComponent(String.valueOf(min)) : WHITESPACE);
|
||||||
|
lines.add(min > 0 ? Lang.translate("data_source.station_summary.minutes")
|
||||||
|
: Lang.translate("data_source.station_summary.seconds", sec));
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.add(prediction.train.name.copy());
|
||||||
|
lines.add(prediction.scheduleTitle);
|
||||||
|
|
||||||
|
if (!hasPlatform) {
|
||||||
|
list.add(lines);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String platform = prediction.destination;
|
||||||
|
for (String string : filter.split("\\*"))
|
||||||
|
if (!string.isEmpty())
|
||||||
|
platform = platform.replace(string, "");
|
||||||
|
platform = platform.replace("*", "?");
|
||||||
|
|
||||||
|
lines.add(new TextComponent(platform.trim()));
|
||||||
|
list.add(lines);
|
||||||
|
});
|
||||||
|
|
||||||
|
int toPad = stats.maxRows() - list.size();
|
||||||
|
for (int padding = 0; padding < toPad; padding++)
|
||||||
|
list.add(hasPlatform ? EMPTY_ENTRY_5 : EMPTY_ENTRY_4);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadFlapDisplayLayout(DataGathererContext context, FlapDisplayTileEntity flapDisplay,
|
||||||
|
FlapDisplayLayout layout) {
|
||||||
|
CompoundTag conf = context.sourceConfig();
|
||||||
|
int columnWidth = conf.getInt("NameColumn");
|
||||||
|
int columnWidth2 = conf.getInt("PlatformColumn");
|
||||||
|
boolean hasPlatform = conf.getString("Filter")
|
||||||
|
.contains("*");
|
||||||
|
|
||||||
|
String layoutName = "StationSummary" + columnWidth + hasPlatform + columnWidth2;
|
||||||
|
|
||||||
|
if (layout.isLayout(layoutName))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ArrayList<FlapDisplaySection> list = new ArrayList<>();
|
||||||
|
|
||||||
|
int timeWidth = 20;
|
||||||
|
float gapSize = 8f;
|
||||||
|
float platformWidth = columnWidth2 * MONOSPACE;
|
||||||
|
|
||||||
|
// populate
|
||||||
|
FlapDisplaySection minutes = new FlapDisplaySection(MONOSPACE, "numeric", false, false);
|
||||||
|
FlapDisplaySection time = new FlapDisplaySection(timeWidth, "arrival_time", true, true);
|
||||||
|
|
||||||
|
float totalSize = flapDisplay.xSize * 32f - 4f - gapSize * 2;
|
||||||
|
totalSize = totalSize - timeWidth - MONOSPACE;
|
||||||
|
platformWidth = Math.min(platformWidth, totalSize - gapSize);
|
||||||
|
platformWidth = (int) (platformWidth / MONOSPACE) * MONOSPACE;
|
||||||
|
|
||||||
|
if (hasPlatform)
|
||||||
|
totalSize = totalSize - gapSize - platformWidth;
|
||||||
|
if (platformWidth == 0 && hasPlatform)
|
||||||
|
totalSize += gapSize;
|
||||||
|
|
||||||
|
int trainNameWidth = (int) ((columnWidth / 100f) * totalSize / MONOSPACE);
|
||||||
|
int destinationWidth = (int) Math.round((1 - columnWidth / 100f) * totalSize / MONOSPACE);
|
||||||
|
|
||||||
|
FlapDisplaySection trainName =
|
||||||
|
new FlapDisplaySection(trainNameWidth * MONOSPACE, "alphabet", false, trainNameWidth > 0);
|
||||||
|
FlapDisplaySection destination = new FlapDisplaySection(destinationWidth * MONOSPACE, "alphabet", false,
|
||||||
|
hasPlatform && destinationWidth > 0 && platformWidth > 0);
|
||||||
|
|
||||||
|
FlapDisplaySection platform = new FlapDisplaySection(platformWidth, "numeric", false, false).rightAligned();
|
||||||
|
|
||||||
|
list.add(minutes);
|
||||||
|
list.add(time);
|
||||||
|
list.add(trainName);
|
||||||
|
list.add(destination);
|
||||||
|
|
||||||
|
if (hasPlatform)
|
||||||
|
list.add(platform);
|
||||||
|
|
||||||
|
layout.configure(layoutName, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey() {
|
||||||
|
return "station_summary";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void populateData(DataGathererContext context) {
|
||||||
|
CompoundTag conf = context.sourceConfig();
|
||||||
|
if (conf.contains("Filter"))
|
||||||
|
return;
|
||||||
|
if (!(context.getSourceTE()instanceof StationTileEntity stationTe))
|
||||||
|
return;
|
||||||
|
GlobalStation station = stationTe.getStation();
|
||||||
|
if (station == null)
|
||||||
|
return;
|
||||||
|
conf.putString("Filter", station.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void initConfigurationWidgets(DataGathererContext context, LineBuilder builder, boolean isFirstLine) {
|
||||||
|
if (isFirstLine) {
|
||||||
|
builder.addTextInput(0, 137, (e, t) -> {
|
||||||
|
e.setValue("");
|
||||||
|
t.withTooltip(ImmutableList.of(Lang.translate("data_source.station_summary.filter")
|
||||||
|
.withStyle(s -> s.withColor(0x5391E1)),
|
||||||
|
Lang.translate("gui.schedule.lmb_edit")
|
||||||
|
.withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC)));
|
||||||
|
}, "Filter");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.addScrollInput(0, 32, (si, l) -> {
|
||||||
|
si.titled(Lang.translate("data_source.station_summary.train_name_column"))
|
||||||
|
.withRange(0, 73)
|
||||||
|
.withShiftStep(12);
|
||||||
|
si.setState(50);
|
||||||
|
l.withSuffix("%");
|
||||||
|
}, "NameColumn");
|
||||||
|
|
||||||
|
builder.addScrollInput(36, 22, (si, l) -> {
|
||||||
|
si.titled(Lang.translate("data_source.station_summary.platform_column"))
|
||||||
|
.withRange(0, 16)
|
||||||
|
.withShiftStep(4);
|
||||||
|
si.setState(3);
|
||||||
|
}, "PlatformColumn");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataTargetStats;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
|
||||||
|
public class StopWatchDataSource extends SingleLineDataSource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MutableComponent provideLine(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
if (!(context.getSourceTE()instanceof CuckooClockTileEntity ccte))
|
||||||
|
return TimeOfDayDataSource.EMPTY_TIME;
|
||||||
|
if (ccte.getSpeed() == 0)
|
||||||
|
return TimeOfDayDataSource.EMPTY_TIME;
|
||||||
|
|
||||||
|
if (!context.sourceConfig()
|
||||||
|
.contains("StartTime"))
|
||||||
|
onSignalReset(context);
|
||||||
|
|
||||||
|
long started = context.sourceConfig()
|
||||||
|
.getLong("StartTime");
|
||||||
|
long current = context.te()
|
||||||
|
.getLevel()
|
||||||
|
.getGameTime();
|
||||||
|
|
||||||
|
int diff = (int) (current - started);
|
||||||
|
int hours = (diff / 60 / 60 / 20);
|
||||||
|
int minutes = (diff / 60 / 20) % 60;
|
||||||
|
int seconds = (diff / 20) % 60;
|
||||||
|
|
||||||
|
MutableComponent component = new TextComponent((hours == 0 ? "" : (hours < 10 ? " " : "") + hours + ":")
|
||||||
|
+ (minutes < 10 ? hours == 0 ? " " : "0" : "") + minutes + ":" + (seconds < 10 ? "0" : "") + seconds);
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSignalReset(DataGathererContext context) {
|
||||||
|
context.sourceConfig()
|
||||||
|
.putLong("StartTime", context.te()
|
||||||
|
.getLevel()
|
||||||
|
.getGameTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPassiveRefreshTicks() {
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean allowsLabeling(DataGathererContext context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFlapDisplayLayoutName(DataGathererContext context) {
|
||||||
|
return "Instant";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FlapDisplaySection createSectionForValue(DataGathererContext context, int size) {
|
||||||
|
return new FlapDisplaySection(size * FlapDisplaySection.MONOSPACE, "instant", false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey() {
|
||||||
|
return "stop_watch";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererScreen.LineBuilder;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataTargetStats;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public class TimeOfDayDataSource extends SingleLineDataSource {
|
||||||
|
|
||||||
|
public static final MutableComponent EMPTY_TIME = new TextComponent("--:--");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MutableComponent provideLine(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
if (!(context.level()instanceof ServerLevel sLevel))
|
||||||
|
return EMPTY_TIME;
|
||||||
|
if (!(context.getSourceTE() instanceof CuckooClockTileEntity ccte))
|
||||||
|
return EMPTY_TIME;
|
||||||
|
if (ccte.getSpeed() == 0)
|
||||||
|
return EMPTY_TIME;
|
||||||
|
|
||||||
|
boolean c12 = context.sourceConfig()
|
||||||
|
.getInt("Cycle") == 0;
|
||||||
|
boolean isNatural = sLevel.dimensionType()
|
||||||
|
.natural();
|
||||||
|
|
||||||
|
int dayTime = (int) (sLevel.getDayTime() % 24000);
|
||||||
|
int hours = (dayTime / 1000 + 6) % 24;
|
||||||
|
int minutes = (dayTime % 1000) * 60 / 1000;
|
||||||
|
MutableComponent suffix = Lang.translate("generic.daytime." + (hours > 11 ? "pm" : "am"));
|
||||||
|
|
||||||
|
minutes = minutes / 5 * 5;
|
||||||
|
if (c12) {
|
||||||
|
hours %= 12;
|
||||||
|
if (hours == 0)
|
||||||
|
hours = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isNatural) {
|
||||||
|
hours = Create.RANDOM.nextInt(70) + 24;
|
||||||
|
minutes = Create.RANDOM.nextInt(40) + 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
MutableComponent component = new TextComponent(
|
||||||
|
(hours < 10 ? " " : "") + hours + ":" + (minutes < 10 ? "0" : "") + minutes + (c12 ? " " : ""));
|
||||||
|
|
||||||
|
return c12 ? component.append(suffix) : component;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFlapDisplayLayoutName(DataGathererContext context) {
|
||||||
|
return "Instant";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FlapDisplaySection createSectionForValue(DataGathererContext context, int size) {
|
||||||
|
return new FlapDisplaySection(size * FlapDisplaySection.MONOSPACE, "instant", false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey() {
|
||||||
|
return "time_of_day";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void initConfigurationWidgets(DataGathererContext context, LineBuilder builder, boolean isFirstLine) {
|
||||||
|
super.initConfigurationWidgets(context, builder, isFirstLine);
|
||||||
|
if (isFirstLine)
|
||||||
|
return;
|
||||||
|
|
||||||
|
builder.addSelectionScrollInput(0, 60, (si, l) -> {
|
||||||
|
si.forOptions(Lang.translatedOptions("data_source.time", "12_hour", "24_hour"))
|
||||||
|
.titled(Lang.translate("data_source.time.format"));
|
||||||
|
}, "Cycle");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean allowsLabeling(DataGathererContext context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,170 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.source;
|
||||||
|
|
||||||
|
import static com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection.MONOSPACE;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.mutable.MutableInt;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererScreen.LineBuilder;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.target.DataTargetStats;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity;
|
||||||
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
import com.simibubi.create.foundation.utility.IntAttached;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.world.level.block.entity.LecternBlockEntity;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public abstract class ValueListDataSource extends DataGathererSource {
|
||||||
|
|
||||||
|
protected abstract Stream<IntAttached<MutableComponent>> provideEntries(DataGathererContext context, int maxRows);
|
||||||
|
|
||||||
|
protected abstract boolean valueFirst();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MutableComponent> provideText(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
boolean isBook = context.getTargetTE() instanceof LecternBlockEntity;
|
||||||
|
|
||||||
|
List<MutableComponent> list = provideEntries(context, stats.maxRows() * (isBook ? ENTRIES_PER_PAGE : 1))
|
||||||
|
.map(e -> createComponentsFromEntry(context, e))
|
||||||
|
.map(l -> {
|
||||||
|
MutableComponent combined = l.get(0)
|
||||||
|
.append(l.get(1));
|
||||||
|
if (l.size() > 2)
|
||||||
|
combined.append(l.get(2));
|
||||||
|
return combined;
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (isBook)
|
||||||
|
list = condensePages(list);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final int ENTRIES_PER_PAGE = 8;
|
||||||
|
|
||||||
|
private List<MutableComponent> condensePages(List<MutableComponent> list) {
|
||||||
|
List<MutableComponent> condensed = new ArrayList<>();
|
||||||
|
MutableComponent current = null;
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
MutableComponent atIndex = list.get(i);
|
||||||
|
if (current == null) {
|
||||||
|
current = atIndex;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
current.append(new TextComponent("\n"))
|
||||||
|
.append(atIndex);
|
||||||
|
if ((i + 1) % ENTRIES_PER_PAGE == 0) {
|
||||||
|
condensed.add(current);
|
||||||
|
current = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current != null)
|
||||||
|
condensed.add(current);
|
||||||
|
return condensed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<List<MutableComponent>> provideFlapDisplayText(DataGathererContext context, DataTargetStats stats) {
|
||||||
|
MutableInt highest = new MutableInt(0);
|
||||||
|
context.flapDisplayContext = highest;
|
||||||
|
return provideEntries(context, stats.maxRows()).map(e -> {
|
||||||
|
highest.setValue(Math.max(highest.getValue(), e.getFirst()));
|
||||||
|
return createComponentsFromEntry(context, e);
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<MutableComponent> createComponentsFromEntry(DataGathererContext context,
|
||||||
|
IntAttached<MutableComponent> entry) {
|
||||||
|
int number = entry.getFirst();
|
||||||
|
MutableComponent name = entry.getSecond()
|
||||||
|
.append(WHITESPACE);
|
||||||
|
|
||||||
|
if (shortenNumbers(context)) {
|
||||||
|
Couple<MutableComponent> shortened = shorten(number);
|
||||||
|
return valueFirst() ? Arrays.asList(shortened.getFirst(), shortened.getSecond(), name)
|
||||||
|
: Arrays.asList(name, shortened.getFirst(), shortened.getSecond());
|
||||||
|
}
|
||||||
|
|
||||||
|
MutableComponent formattedNumber = new TextComponent(String.valueOf(number)).append(WHITESPACE);
|
||||||
|
return valueFirst() ? Arrays.asList(formattedNumber, name) : Arrays.asList(name, formattedNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadFlapDisplayLayout(DataGathererContext context, FlapDisplayTileEntity flapDisplay,
|
||||||
|
FlapDisplayLayout layout) {
|
||||||
|
|
||||||
|
boolean valueFirst = valueFirst();
|
||||||
|
boolean shortenNumbers = shortenNumbers(context);
|
||||||
|
int valueFormat = shortenNumbers ? 0
|
||||||
|
: Math.max(4, 1 + (int) Math.log10(((MutableInt) context.flapDisplayContext).intValue()));
|
||||||
|
|
||||||
|
String layoutKey = "ValueList_" + valueFirst + "_" + valueFormat;
|
||||||
|
if (layout.isLayout(layoutKey))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int maxCharCount = flapDisplay.getMaxCharCount(1);
|
||||||
|
int numberLength = Math.min(maxCharCount, Math.max(3, valueFormat));
|
||||||
|
int nameLength = Math.max(maxCharCount - numberLength - (shortenNumbers ? 1 : 0), 0);
|
||||||
|
|
||||||
|
FlapDisplaySection name = new FlapDisplaySection(MONOSPACE * nameLength, "alphabet", false, !valueFirst);
|
||||||
|
FlapDisplaySection value =
|
||||||
|
new FlapDisplaySection(MONOSPACE * numberLength, "number", false, !shortenNumbers && valueFirst)
|
||||||
|
.rightAligned();
|
||||||
|
|
||||||
|
if (shortenNumbers) {
|
||||||
|
FlapDisplaySection suffix = new FlapDisplaySection(MONOSPACE, "shortened_numbers", false, valueFirst);
|
||||||
|
layout.configure(layoutKey,
|
||||||
|
valueFirst ? Arrays.asList(value, suffix, name) : Arrays.asList(name, value, suffix));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout.configure(layoutKey, valueFirst ? Arrays.asList(value, name) : Arrays.asList(name, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Couple<MutableComponent> shorten(int number) {
|
||||||
|
if (number >= 1000000)
|
||||||
|
return Couple.create(new TextComponent(String.valueOf(number / 1000000)),
|
||||||
|
Lang.translate("data_source.value_list.million")
|
||||||
|
.append(WHITESPACE));
|
||||||
|
if (number >= 1000)
|
||||||
|
return Couple.create(new TextComponent(String.valueOf(number / 1000)),
|
||||||
|
Lang.translate("data_source.value_list.thousand")
|
||||||
|
.append(WHITESPACE));
|
||||||
|
return Couple.create(new TextComponent(String.valueOf(number)), WHITESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean shortenNumbers(DataGathererContext context) {
|
||||||
|
return context.sourceConfig()
|
||||||
|
.getInt("Format") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void initConfigurationWidgets(DataGathererContext context, LineBuilder builder, boolean isFirstLine) {
|
||||||
|
if (isFirstLine)
|
||||||
|
addFullNumberConfig(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
protected void addFullNumberConfig(LineBuilder builder) {
|
||||||
|
builder.addSelectionScrollInput(0, 75,
|
||||||
|
(si, l) -> si.forOptions(Lang.translatedOptions("data_source.value_list", "shortened", "full_number"))
|
||||||
|
.titled(Lang.translate("data_source.value_list.display")),
|
||||||
|
"Format");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.target;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererBehaviour;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
|
|
||||||
|
public abstract class DataGathererTarget extends DataGathererBehaviour {
|
||||||
|
|
||||||
|
public abstract void acceptText(int line, List<MutableComponent> text, DataGathererContext context);
|
||||||
|
|
||||||
|
public abstract DataTargetStats provideStats(DataGathererContext context);
|
||||||
|
|
||||||
|
public AABB getMultiblockBounds(LevelAccessor level, BlockPos pos) {
|
||||||
|
VoxelShape shape = level.getBlockState(pos)
|
||||||
|
.getShape(level, pos);
|
||||||
|
if (shape.isEmpty())
|
||||||
|
return new AABB(pos);
|
||||||
|
return shape.bounds()
|
||||||
|
.move(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getLineOptionText(int line) {
|
||||||
|
return Lang.translate("data_target.line", line + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void reserve(int line, BlockEntity target, DataGathererContext context) {
|
||||||
|
if (line == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CompoundTag tag = target.getTileData();
|
||||||
|
CompoundTag compound = tag.getCompound("DataGatherer");
|
||||||
|
compound.putLong("Line" + line, context.te()
|
||||||
|
.getBlockPos()
|
||||||
|
.asLong());
|
||||||
|
tag.put("DataGatherer", compound);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReserved(int line, BlockEntity target, DataGathererContext context) {
|
||||||
|
CompoundTag tag = target.getTileData();
|
||||||
|
CompoundTag compound = tag.getCompound("DataGatherer");
|
||||||
|
|
||||||
|
if (!compound.contains("Line" + line))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
long l = compound.getLong("Line" + line);
|
||||||
|
BlockPos reserved = BlockPos.of(l);
|
||||||
|
|
||||||
|
if (!reserved.equals(context.te()
|
||||||
|
.getBlockPos()) && AllBlocks.DATA_GATHERER.has(target.getLevel()
|
||||||
|
.getBlockState(reserved)))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
compound.remove("Line" + line);
|
||||||
|
if (compound.isEmpty())
|
||||||
|
tag.remove("DataGatherer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.target;
|
||||||
|
|
||||||
|
public record DataTargetStats(int maxRows, int maxColumns, DataGathererTarget type) {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.target;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.DataGathererSource;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.source.SingleLineDataSource;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Vec3i;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public class FlapDisplayDataTarget extends DataGathererTarget {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptText(int line, List<MutableComponent> text, DataGathererContext context) {}
|
||||||
|
|
||||||
|
public void acceptFlapText(int line, List<List<MutableComponent>> text, DataGathererContext context) {
|
||||||
|
FlapDisplayTileEntity controller = getController(context);
|
||||||
|
if (controller == null)
|
||||||
|
return;
|
||||||
|
if (!controller.isSpeedRequirementFulfilled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
DataGathererSource source = context.te().activeSource;
|
||||||
|
List<FlapDisplayLayout> lines = controller.getLines();
|
||||||
|
for (int i = 0; i + line < lines.size(); i++) {
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
reserve(i + line, controller, context);
|
||||||
|
if (i > 0 && isReserved(i + line, controller, context))
|
||||||
|
break;
|
||||||
|
|
||||||
|
FlapDisplayLayout layout = lines.get(i + line);
|
||||||
|
|
||||||
|
if (i >= text.size()) {
|
||||||
|
if (source instanceof SingleLineDataSource)
|
||||||
|
break;
|
||||||
|
controller.applyTextManually(i + line, null);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
source.loadFlapDisplayLayout(context, controller, layout);
|
||||||
|
|
||||||
|
for (int sectionIndex = 0; sectionIndex < layout.getSections()
|
||||||
|
.size(); sectionIndex++) {
|
||||||
|
List<MutableComponent> textLine = text.get(i);
|
||||||
|
if (textLine.size() <= sectionIndex)
|
||||||
|
break;
|
||||||
|
layout.getSections()
|
||||||
|
.get(sectionIndex)
|
||||||
|
.setText(textLine.get(sectionIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.sendData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReserved(int line, BlockEntity target, DataGathererContext context) {
|
||||||
|
return super.isReserved(line, target, context)
|
||||||
|
|| target instanceof FlapDisplayTileEntity fdte && fdte.manualLines.length > line && fdte.manualLines[line];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataTargetStats provideStats(DataGathererContext context) {
|
||||||
|
FlapDisplayTileEntity controller = getController(context);
|
||||||
|
if (controller == null)
|
||||||
|
return new DataTargetStats(1, 1, this);
|
||||||
|
return new DataTargetStats(controller.ySize * 2, controller.getMaxCharCount(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FlapDisplayTileEntity getController(DataGathererContext context) {
|
||||||
|
BlockEntity teIn = context.getTargetTE();
|
||||||
|
if (!(teIn instanceof FlapDisplayTileEntity te))
|
||||||
|
return null;
|
||||||
|
return te.getController();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public AABB getMultiblockBounds(LevelAccessor level, BlockPos pos) {
|
||||||
|
AABB baseShape = super.getMultiblockBounds(level, pos);
|
||||||
|
BlockEntity te = level.getBlockEntity(pos);
|
||||||
|
|
||||||
|
if (!(te instanceof FlapDisplayTileEntity fdte))
|
||||||
|
return baseShape;
|
||||||
|
|
||||||
|
FlapDisplayTileEntity controller = fdte.getController();
|
||||||
|
if (controller == null)
|
||||||
|
return baseShape;
|
||||||
|
|
||||||
|
Vec3i normal = controller.getDirection()
|
||||||
|
.getClockWise()
|
||||||
|
.getNormal();
|
||||||
|
return baseShape.move(controller.getBlockPos()
|
||||||
|
.subtract(pos))
|
||||||
|
.expandTowards(normal.getX() * (controller.xSize - 1), 1 - controller.ySize,
|
||||||
|
normal.getZ() * (controller.xSize - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.target;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.StringTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.Items;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.entity.LecternBlockEntity;
|
||||||
|
|
||||||
|
public class LecternDataTarget extends DataGathererTarget {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptText(int line, List<MutableComponent> text, DataGathererContext context) {
|
||||||
|
BlockEntity te = context.getTargetTE();
|
||||||
|
if (!(te instanceof LecternBlockEntity lectern))
|
||||||
|
return;
|
||||||
|
ItemStack book = lectern.getBook();
|
||||||
|
if (book.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (book.is(Items.WRITABLE_BOOK))
|
||||||
|
lectern.setBook(book = signBook(book));
|
||||||
|
if (!book.is(Items.WRITTEN_BOOK))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ListTag tag = book.getTag()
|
||||||
|
.getList("pages", Tag.TAG_STRING);
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
for (int i = 0; i - line < text.size() && i < 50; i++) {
|
||||||
|
if (tag.size() <= i)
|
||||||
|
tag.add(StringTag.valueOf(i < line ? "" : Component.Serializer.toJson(text.get(i - line))));
|
||||||
|
|
||||||
|
else if (i >= line) {
|
||||||
|
if (i - line == 0)
|
||||||
|
reserve(i, lectern, context);
|
||||||
|
if (i - line > 0 && isReserved(i - line, lectern, context))
|
||||||
|
break;
|
||||||
|
|
||||||
|
tag.set(i, StringTag.valueOf(Component.Serializer.toJson(text.get(i - line))));
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
book.getTag()
|
||||||
|
.put("pages", tag);
|
||||||
|
lectern.setBook(book);
|
||||||
|
|
||||||
|
if (changed && context.level()instanceof Level level)
|
||||||
|
level.sendBlockUpdated(context.getTargetPos(), lectern.getBlockState(), lectern.getBlockState(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataTargetStats provideStats(DataGathererContext context) {
|
||||||
|
return new DataTargetStats(50, 256, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getLineOptionText(int line) {
|
||||||
|
return Lang.translate("data_target.page", line + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack signBook(ItemStack book) {
|
||||||
|
ItemStack written = new ItemStack(Items.WRITTEN_BOOK);
|
||||||
|
CompoundTag compoundtag = book.getTag();
|
||||||
|
if (compoundtag != null)
|
||||||
|
written.setTag(compoundtag.copy());
|
||||||
|
|
||||||
|
written.addTagElement("author", StringTag.valueOf("Data Gatherer"));
|
||||||
|
written.addTagElement("filtered_title", StringTag.valueOf("Printed Book"));
|
||||||
|
written.addTagElement("title", StringTag.valueOf("Printed Book"));
|
||||||
|
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.target;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.mutable.MutableInt;
|
||||||
|
import org.apache.commons.lang3.mutable.MutableObject;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.redstone.NixieTubeBlock;
|
||||||
|
import com.simibubi.create.content.logistics.block.redstone.NixieTubeTileEntity;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public class NixieTubeDataTarget extends SingleLineDataTarget {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void acceptLine(MutableComponent text, DataGathererContext context) {
|
||||||
|
String tagElement = Component.Serializer.toJson(text);
|
||||||
|
NixieTubeBlock.walkNixies(context.level(), context.getTargetPos(), (currentPos, rowPosition) -> {
|
||||||
|
BlockEntity blockEntity = context.level()
|
||||||
|
.getBlockEntity(currentPos);
|
||||||
|
if (blockEntity instanceof NixieTubeTileEntity nixie)
|
||||||
|
nixie.displayCustomText(tagElement, rowPosition);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getWidth(DataGathererContext context) {
|
||||||
|
MutableInt count = new MutableInt(0);
|
||||||
|
NixieTubeBlock.walkNixies(context.level(), context.getTargetPos(), (currentPos, rowPosition) -> count.add(2));
|
||||||
|
return count.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public AABB getMultiblockBounds(LevelAccessor level, BlockPos pos) {
|
||||||
|
MutableObject<BlockPos> start = new MutableObject<>(null);
|
||||||
|
MutableObject<BlockPos> end = new MutableObject<>(null);
|
||||||
|
NixieTubeBlock.walkNixies(level, pos, (currentPos, rowPosition) -> {
|
||||||
|
end.setValue(currentPos);
|
||||||
|
if (start.getValue() == null)
|
||||||
|
start.setValue(currentPos);
|
||||||
|
});
|
||||||
|
|
||||||
|
BlockPos diffToCurrent = start.getValue()
|
||||||
|
.subtract(pos);
|
||||||
|
BlockPos diff = end.getValue()
|
||||||
|
.subtract(start.getValue());
|
||||||
|
|
||||||
|
return super.getMultiblockBounds(level, pos).move(diffToCurrent)
|
||||||
|
.expandTowards(Vec3.atLowerCornerOf(diff));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.target;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.entity.SignBlockEntity;
|
||||||
|
|
||||||
|
public class SignDataTarget extends DataGathererTarget {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptText(int line, List<MutableComponent> text, DataGathererContext context) {
|
||||||
|
BlockEntity te = context.getTargetTE();
|
||||||
|
if (!(te instanceof SignBlockEntity sign))
|
||||||
|
return;
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
for (int i = 0; i < text.size() && i + line < 4; i++) {
|
||||||
|
if (i == 0)
|
||||||
|
reserve(i + line, sign, context);
|
||||||
|
if (i > 0 && isReserved(i + line, sign, context))
|
||||||
|
break;
|
||||||
|
|
||||||
|
sign.setMessage(i + line, text.get(i));
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed && context.level()instanceof Level level)
|
||||||
|
level.sendBlockUpdated(context.getTargetPos(), sign.getBlockState(), sign.getBlockState(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataTargetStats provideStats(DataGathererContext context) {
|
||||||
|
return new DataTargetStats(4, 15, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.data.target;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererContext;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
|
||||||
|
public abstract class SingleLineDataTarget extends DataGathererTarget {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void acceptText(int line, List<MutableComponent> text, DataGathererContext context) {
|
||||||
|
acceptLine(text.get(0), context);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void acceptLine(MutableComponent text, DataGathererContext context);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final DataTargetStats provideStats(DataGathererContext context) {
|
||||||
|
return new DataTargetStats(1, getWidth(context), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getLineOptionText(int line) {
|
||||||
|
return Lang.translate("data_target.single_line");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract int getWidth(DataGathererContext context);
|
||||||
|
|
||||||
|
}
|
|
@ -254,12 +254,12 @@ public class EjectorTargetHandler {
|
||||||
drawOutline(currentSelection);
|
drawOutline(currentSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void drawOutline(BlockPos selection) {
|
public static void drawOutline(BlockPos selection) {
|
||||||
Level world = Minecraft.getInstance().level;
|
Level world = Minecraft.getInstance().level;
|
||||||
if (currentSelection == null)
|
if (selection == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BlockPos pos = currentSelection;
|
BlockPos pos = selection;
|
||||||
BlockState state = world.getBlockState(pos);
|
BlockState state = world.getBlockState(pos);
|
||||||
VoxelShape shape = state.getShape(world, pos);
|
VoxelShape shape = state.getShape(world, pos);
|
||||||
AABB boundingBox = shape.isEmpty() ? new AABB(BlockPos.ZERO) : shape.bounds();
|
AABB boundingBox = shape.isEmpty() ? new AABB(BlockPos.ZERO) : shape.bounds();
|
||||||
|
|
|
@ -1,37 +1,64 @@
|
||||||
package com.simibubi.create.content.logistics.block.diodes;
|
package com.simibubi.create.content.logistics.block.diodes;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.foundation.block.ITE;
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.sounds.SoundEvents;
|
||||||
|
import net.minecraft.sounds.SoundSource;
|
||||||
|
import net.minecraft.world.InteractionHand;
|
||||||
|
import net.minecraft.world.InteractionResult;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
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.Block;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
||||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||||
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
|
|
||||||
public class BrassDiodeBlock extends AbstractDiodeBlock implements ITE<BrassDiodeTileEntity> {
|
public class BrassDiodeBlock extends AbstractDiodeBlock implements ITE<BrassDiodeTileEntity> {
|
||||||
|
|
||||||
public static final BooleanProperty POWERING = BooleanProperty.create("powering");
|
public static final BooleanProperty POWERING = BooleanProperty.create("powering");
|
||||||
|
public static final BooleanProperty INVERTED = BooleanProperty.create("inverted");
|
||||||
|
|
||||||
public BrassDiodeBlock(Properties properties) {
|
public BrassDiodeBlock(Properties properties) {
|
||||||
super(properties);
|
super(properties);
|
||||||
registerDefaultState(defaultBlockState().setValue(POWERED, false)
|
registerDefaultState(defaultBlockState().setValue(POWERED, false)
|
||||||
.setValue(POWERING, false));
|
.setValue(POWERING, false)
|
||||||
|
.setValue(INVERTED, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player player, InteractionHand pHand,
|
||||||
|
BlockHitResult pHit) {
|
||||||
|
if (!player.mayBuild())
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
if (player.isShiftKeyDown())
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
if (AllItems.WRENCH.isIn(player.getItemInHand(pHand)))
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
if (pLevel.isClientSide)
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
pLevel.setBlock(pPos, pState.cycle(INVERTED), 3);
|
||||||
|
float f = !pState.getValue(INVERTED) ? 0.6F : 0.5F;
|
||||||
|
pLevel.playSound(null, pPos, SoundEvents.LEVER_CLICK, SoundSource.BLOCKS, 0.3F, f);
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void createBlockStateDefinition(Builder<Block, BlockState> builder) {
|
protected void createBlockStateDefinition(Builder<Block, BlockState> builder) {
|
||||||
builder.add(POWERED, POWERING, FACING);
|
builder.add(POWERED, POWERING, FACING, INVERTED);
|
||||||
super.createBlockStateDefinition(builder);
|
super.createBlockStateDefinition(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getOutputSignal(BlockGetter worldIn, BlockPos pos, BlockState state) {
|
protected int getOutputSignal(BlockGetter worldIn, BlockPos pos, BlockState state) {
|
||||||
return state.getValue(POWERING) ? 15 : 0;
|
return state.getValue(POWERING) ^ state.getValue(INVERTED) ? 15 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class BrassDiodeGenerator extends AbstractDiodeGenerator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getModelIndex(BlockState state) {
|
protected int getModelIndex(BlockState state) {
|
||||||
return (state.getValue(BrassDiodeBlock.POWERING) ? 2 : 0)
|
return (state.getValue(BrassDiodeBlock.POWERING) ^ state.getValue(BrassDiodeBlock.INVERTED) ? 2 : 0)
|
||||||
+ (state.getValue(BrassDiodeBlock.POWERED) ? 1 : 0);
|
+ (state.getValue(BrassDiodeBlock.POWERED) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.simibubi.create.content.logistics.block.redstone;
|
||||||
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED;
|
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllShapes;
|
import com.simibubi.create.AllShapes;
|
||||||
|
@ -16,6 +17,8 @@ import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
|
@ -78,7 +81,28 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock
|
||||||
|
|
||||||
if (!display && dye == null)
|
if (!display && dye == null)
|
||||||
return InteractionResult.PASS;
|
return InteractionResult.PASS;
|
||||||
|
if (world.isClientSide)
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
|
||||||
|
CompoundTag tag = heldItem.getTagElement("display");
|
||||||
|
String tagElement = tag != null && tag.contains("Name", Tag.TAG_STRING) ? tag.getString("Name") : null;
|
||||||
|
|
||||||
|
walkNixies(world, pos, (currentPos, rowPosition) -> {
|
||||||
|
if (display)
|
||||||
|
withTileEntityDo(world, currentPos, te -> te.displayCustomText(tagElement, rowPosition));
|
||||||
|
if (dye != null)
|
||||||
|
world.setBlockAndUpdate(currentPos, withColor(state, dye));
|
||||||
|
});
|
||||||
|
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void walkNixies(LevelAccessor world, BlockPos start, BiConsumer<BlockPos, Integer> callback) {
|
||||||
|
BlockState state = world.getBlockState(start);
|
||||||
|
if (!(state.getBlock() instanceof NixieTubeBlock))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BlockPos currentPos = start;
|
||||||
Direction left = state.getValue(FACING)
|
Direction left = state.getValue(FACING)
|
||||||
.getOpposite();
|
.getOpposite();
|
||||||
|
|
||||||
|
@ -89,10 +113,6 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock
|
||||||
|
|
||||||
Direction right = left.getOpposite();
|
Direction right = left.getOpposite();
|
||||||
|
|
||||||
if (world.isClientSide)
|
|
||||||
return InteractionResult.SUCCESS;
|
|
||||||
|
|
||||||
BlockPos currentPos = pos;
|
|
||||||
while (true) {
|
while (true) {
|
||||||
BlockPos nextPos = currentPos.relative(left);
|
BlockPos nextPos = currentPos.relative(left);
|
||||||
if (!areNixieBlocksEqual(world.getBlockState(nextPos), state))
|
if (!areNixieBlocksEqual(world.getBlockState(nextPos), state))
|
||||||
|
@ -104,20 +124,13 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
final int rowPosition = index;
|
final int rowPosition = index;
|
||||||
|
callback.accept(currentPos, rowPosition);
|
||||||
if (display)
|
|
||||||
withTileEntityDo(world, currentPos, te -> te.displayCustomNameOf(heldItem, rowPosition));
|
|
||||||
if (dye != null)
|
|
||||||
world.setBlockAndUpdate(currentPos, withColor(state, dye));
|
|
||||||
|
|
||||||
BlockPos nextPos = currentPos.relative(right);
|
BlockPos nextPos = currentPos.relative(right);
|
||||||
if (!areNixieBlocksEqual(world.getBlockState(nextPos), state))
|
if (!areNixieBlocksEqual(world.getBlockState(nextPos), state))
|
||||||
break;
|
break;
|
||||||
currentPos = nextPos;
|
currentPos = nextPos;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return InteractionResult.SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
package com.simibubi.create.content.logistics.block.redstone;
|
package com.simibubi.create.content.logistics.block.redstone;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.simibubi.create.AllBlockPartials;
|
import com.simibubi.create.AllBlockPartials;
|
||||||
|
@ -15,6 +13,7 @@ import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||||
import com.simibubi.create.foundation.utility.Color;
|
import com.simibubi.create.foundation.utility.Color;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
import com.simibubi.create.foundation.utility.DyeHelper;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
@ -33,32 +32,7 @@ import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
public class NixieTubeRenderer extends SafeTileEntityRenderer<NixieTubeTileEntity> {
|
public class NixieTubeRenderer extends SafeTileEntityRenderer<NixieTubeTileEntity> {
|
||||||
|
|
||||||
private Random r = new Random();
|
private static Random r = new Random();
|
||||||
|
|
||||||
public static final Map<DyeColor, Couple<Integer>> DYE_TABLE = new ImmutableMap.Builder<DyeColor, Couple<Integer>>()
|
|
||||||
|
|
||||||
// DyeColor, ( Front RGB, Back RGB )
|
|
||||||
.put(DyeColor.BLACK, Couple.create(0x45403B, 0x21201F))
|
|
||||||
.put(DyeColor.RED, Couple.create(0xB13937, 0x632737))
|
|
||||||
.put(DyeColor.GREEN, Couple.create(0x208A46, 0x1D6045))
|
|
||||||
.put(DyeColor.BROWN, Couple.create(0xAC855C, 0x68533E))
|
|
||||||
|
|
||||||
.put(DyeColor.BLUE, Couple.create(0x5391E1, 0x504B90))
|
|
||||||
.put(DyeColor.GRAY, Couple.create(0x5D666F, 0x313538))
|
|
||||||
.put(DyeColor.LIGHT_GRAY, Couple.create(0x95969B, 0x707070))
|
|
||||||
.put(DyeColor.PURPLE, Couple.create(0x9F54AE, 0x63366C))
|
|
||||||
|
|
||||||
.put(DyeColor.CYAN, Couple.create(0x3EABB4, 0x3C7872))
|
|
||||||
.put(DyeColor.PINK, Couple.create(0xD5A8CB, 0xB86B95))
|
|
||||||
.put(DyeColor.LIME, Couple.create(0xA3DF55, 0x4FB16F))
|
|
||||||
.put(DyeColor.YELLOW, Couple.create(0xE6D756, 0xE9AC29))
|
|
||||||
|
|
||||||
.put(DyeColor.LIGHT_BLUE, Couple.create(0x69CED2, 0x508AA5))
|
|
||||||
.put(DyeColor.ORANGE, Couple.create(0xEE9246, 0xD94927))
|
|
||||||
.put(DyeColor.MAGENTA, Couple.create(0xF062B0, 0xC04488))
|
|
||||||
.put(DyeColor.WHITE, Couple.create(0xEDEAE5, 0xBBB6B0))
|
|
||||||
|
|
||||||
.build();
|
|
||||||
|
|
||||||
public NixieTubeRenderer(BlockEntityRendererProvider.Context context) {}
|
public NixieTubeRenderer(BlockEntityRendererProvider.Context context) {}
|
||||||
|
|
||||||
|
@ -107,12 +81,12 @@ public class NixieTubeRenderer extends SafeTileEntityRenderer<NixieTubeTileEntit
|
||||||
ms.popPose();
|
ms.popPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawTube(PoseStack ms, MultiBufferSource buffer, String c, float height, DyeColor color) {
|
public static void drawTube(PoseStack ms, MultiBufferSource buffer, String c, float height, DyeColor color) {
|
||||||
Font fontRenderer = Minecraft.getInstance().font;
|
Font fontRenderer = Minecraft.getInstance().font;
|
||||||
float charWidth = fontRenderer.width(c);
|
float charWidth = fontRenderer.width(c);
|
||||||
float shadowOffset = .5f;
|
float shadowOffset = .5f;
|
||||||
float flicker = r.nextFloat();
|
float flicker = r.nextFloat();
|
||||||
Couple<Integer> couple = DYE_TABLE.get(color);
|
Couple<Integer> couple = DyeHelper.DYE_TABLE.get(color);
|
||||||
int brightColor = couple.getFirst();
|
int brightColor = couple.getFirst();
|
||||||
int darkColor = couple.getSecond();
|
int darkColor = couple.getSecond();
|
||||||
int flickeringBrightColor = Color.mixColors(brightColor, darkColor, flicker / 4);
|
int flickeringBrightColor = Color.mixColors(brightColor, darkColor, flicker / 4);
|
||||||
|
|
|
@ -2,46 +2,32 @@ package com.simibubi.create.content.logistics.block.redstone;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import com.simibubi.create.content.logistics.block.data.DataGathererBlock;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonParseException;
|
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity.SignalState;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity.SignalState;
|
||||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
import com.simibubi.create.foundation.utility.DynamicComponent;
|
||||||
|
|
||||||
import net.minecraft.commands.CommandSource;
|
|
||||||
import net.minecraft.commands.CommandSourceStack;
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
import net.minecraft.network.chat.Component;
|
|
||||||
import net.minecraft.network.chat.ComponentUtils;
|
|
||||||
import net.minecraft.network.chat.TextComponent;
|
import net.minecraft.network.chat.TextComponent;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.phys.Vec2;
|
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
|
|
||||||
public class NixieTubeTileEntity extends SmartTileEntity {
|
public class NixieTubeTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
private static final Couple<String> EMPTY = Couple.create("", "");
|
private static final Couple<String> EMPTY = Couple.create("", "");
|
||||||
|
|
||||||
private boolean hasCustomText;
|
|
||||||
private int redstoneStrength;
|
private int redstoneStrength;
|
||||||
private JsonElement rawCustomText;
|
private Optional<DynamicComponent> customText;
|
||||||
private int customTextIndex;
|
private int nixieIndex;
|
||||||
private Component parsedCustomText;
|
|
||||||
private Couple<String> displayedStrings;
|
private Couple<String> displayedStrings;
|
||||||
|
|
||||||
private WeakReference<SignalTileEntity> cachedSignalTE;
|
private WeakReference<SignalTileEntity> cachedSignalTE;
|
||||||
|
@ -49,7 +35,7 @@ public class NixieTubeTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
public NixieTubeTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
public NixieTubeTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||||
super(type, pos, state);
|
super(type, pos, state);
|
||||||
hasCustomText = false;
|
customText = Optional.empty();
|
||||||
redstoneStrength = 0;
|
redstoneStrength = 0;
|
||||||
cachedSignalTE = new WeakReference<>(null);
|
cachedSignalTE = new WeakReference<>(null);
|
||||||
}
|
}
|
||||||
|
@ -57,17 +43,9 @@ public class NixieTubeTileEntity extends SmartTileEntity {
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
|
if (!level.isClientSide)
|
||||||
|
return;
|
||||||
|
|
||||||
// Dynamic text components have to be ticked manually and re-sent to the client
|
|
||||||
if (level instanceof ServerLevel && hasCustomText) {
|
|
||||||
Couple<String> currentStrings = displayedStrings;
|
|
||||||
parsedCustomText = parseCustomText();
|
|
||||||
updateDisplayedStrings();
|
|
||||||
if (currentStrings == null || !currentStrings.equals(displayedStrings))
|
|
||||||
sendData();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level.isClientSide) {
|
|
||||||
signalState = null;
|
signalState = null;
|
||||||
SignalTileEntity signalTileEntity = cachedSignalTE.get();
|
SignalTileEntity signalTileEntity = cachedSignalTE.get();
|
||||||
|
|
||||||
|
@ -83,7 +61,6 @@ public class NixieTubeTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
signalState = signalTileEntity.getState();
|
signalState = signalTileEntity.getState();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
@ -94,7 +71,7 @@ public class NixieTubeTileEntity extends SmartTileEntity {
|
||||||
//
|
//
|
||||||
|
|
||||||
public boolean reactsToRedstone() {
|
public boolean reactsToRedstone() {
|
||||||
return !hasCustomText;
|
return customText.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Couple<String> getDisplayedStrings() {
|
public Couple<String> getDisplayedStrings() {
|
||||||
|
@ -103,40 +80,47 @@ public class NixieTubeTileEntity extends SmartTileEntity {
|
||||||
return displayedStrings;
|
return displayedStrings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MutableComponent getFullText() {
|
||||||
|
return customText.map(DynamicComponent::get)
|
||||||
|
.orElse(new TextComponent("" + redstoneStrength));
|
||||||
|
}
|
||||||
|
|
||||||
public void updateRedstoneStrength(int signalStrength) {
|
public void updateRedstoneStrength(int signalStrength) {
|
||||||
clearCustomText();
|
clearCustomText();
|
||||||
redstoneStrength = signalStrength;
|
redstoneStrength = signalStrength;
|
||||||
|
DataGathererBlock.notifyGatherers(level, worldPosition);
|
||||||
notifyUpdate();
|
notifyUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void displayCustomNameOf(ItemStack stack, int nixiePositionInRow) {
|
public void displayCustomText(String tagElement, int nixiePositionInRow) {
|
||||||
CompoundTag compoundnbt = stack.getTagElement("display");
|
if (tagElement == null)
|
||||||
if (compoundnbt != null && compoundnbt.contains("Name", Tag.TAG_STRING)) {
|
return;
|
||||||
hasCustomText = true;
|
if (customText.filter(d -> d.sameAs(tagElement))
|
||||||
rawCustomText = getJsonFromString(compoundnbt.getString("Name"));
|
.isPresent())
|
||||||
customTextIndex = nixiePositionInRow;
|
return;
|
||||||
parsedCustomText = parseCustomText();
|
|
||||||
|
DynamicComponent component = customText.orElseGet(DynamicComponent::new);
|
||||||
|
component.displayCustomText(level, worldPosition, tagElement);
|
||||||
|
customText = Optional.of(component);
|
||||||
|
nixieIndex = nixiePositionInRow;
|
||||||
|
DataGathererBlock.notifyGatherers(level, worldPosition);
|
||||||
notifyUpdate();
|
notifyUpdate();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void updateDisplayedStrings() {
|
public void updateDisplayedStrings() {
|
||||||
if (signalState != null)
|
if (signalState != null)
|
||||||
return;
|
return;
|
||||||
if (!hasCustomText) {
|
customText.map(DynamicComponent::resolve)
|
||||||
displayedStrings = Couple.create(redstoneStrength < 10 ? "0" : "1", String.valueOf(redstoneStrength % 10));
|
.ifPresentOrElse(
|
||||||
} else {
|
fullText -> displayedStrings =
|
||||||
String fullText = parsedCustomText.getString();
|
Couple.create(charOrEmpty(fullText, nixieIndex * 2), charOrEmpty(fullText, nixieIndex * 2 + 1)),
|
||||||
int index = customTextIndex * 2;
|
() -> displayedStrings =
|
||||||
displayedStrings = Couple.create(charOrEmpty(fullText, index), charOrEmpty(fullText, index + 1));
|
Couple.create(redstoneStrength < 10 ? "0" : "1", String.valueOf(redstoneStrength % 10)));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearCustomText() {
|
public void clearCustomText() {
|
||||||
hasCustomText = false;
|
nixieIndex = 0;
|
||||||
rawCustomText = null;
|
customText = Optional.empty();
|
||||||
customTextIndex = 0;
|
|
||||||
parsedCustomText = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -145,34 +129,21 @@ public class NixieTubeTileEntity extends SmartTileEntity {
|
||||||
protected void read(CompoundTag nbt, boolean clientPacket) {
|
protected void read(CompoundTag nbt, boolean clientPacket) {
|
||||||
super.read(nbt, clientPacket);
|
super.read(nbt, clientPacket);
|
||||||
|
|
||||||
if (nbt.contains("RawCustomText", Tag.TAG_STRING)) {
|
if (nbt.contains("CustomText")) {
|
||||||
rawCustomText = getJsonFromString(nbt.getString("RawCustomText"));
|
DynamicComponent component = customText.orElseGet(DynamicComponent::new);
|
||||||
// Check if string forms valid JSON
|
component.read(level, worldPosition, nbt);
|
||||||
if (rawCustomText != null && !rawCustomText.isJsonNull()) {
|
|
||||||
Component deserializedComponent = parseCustomText();
|
if (component.isValid()) {
|
||||||
// Check if JSON forms valid component
|
customText = Optional.of(component);
|
||||||
if (deserializedComponent != null) {
|
nixieIndex = nbt.getInt("CustomTextIndex");
|
||||||
try {
|
} else {
|
||||||
// Try to deserialize previously parsed component
|
customText = Optional.empty();
|
||||||
parsedCustomText = Component.Serializer.fromJson(nbt.getString("CustomText"));
|
nixieIndex = 0;
|
||||||
} catch (JsonParseException e) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
if (parsedCustomText == null) {
|
|
||||||
// Use test component to ensure field isn't null
|
|
||||||
parsedCustomText = deserializedComponent;
|
|
||||||
}
|
|
||||||
hasCustomText = true;
|
|
||||||
customTextIndex = nbt.getInt("CustomTextIndex");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasCustomText) {
|
if (customText.isEmpty())
|
||||||
clearCustomText();
|
|
||||||
redstoneStrength = nbt.getInt("RedstoneStrength");
|
redstoneStrength = nbt.getInt("RedstoneStrength");
|
||||||
}
|
|
||||||
|
|
||||||
if (clientPacket)
|
if (clientPacket)
|
||||||
updateDisplayedStrings();
|
updateDisplayedStrings();
|
||||||
}
|
}
|
||||||
|
@ -181,57 +152,18 @@ public class NixieTubeTileEntity extends SmartTileEntity {
|
||||||
protected void write(CompoundTag nbt, boolean clientPacket) {
|
protected void write(CompoundTag nbt, boolean clientPacket) {
|
||||||
super.write(nbt, clientPacket);
|
super.write(nbt, clientPacket);
|
||||||
|
|
||||||
if (hasCustomText) {
|
if (customText.isPresent()) {
|
||||||
nbt.putString("RawCustomText", rawCustomText.toString());
|
nbt.putInt("CustomTextIndex", nixieIndex);
|
||||||
nbt.putInt("CustomTextIndex", customTextIndex);
|
customText.get()
|
||||||
nbt.putString("CustomText", Component.Serializer.toJson(parsedCustomText));
|
.write(nbt);
|
||||||
} else {
|
} else
|
||||||
nbt.putInt("RedstoneStrength", redstoneStrength);
|
nbt.putInt("RedstoneStrength", redstoneStrength);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private JsonElement getJsonFromString(String string) {
|
|
||||||
try {
|
|
||||||
return JsonParser.parseString(string);
|
|
||||||
} catch (JsonParseException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String charOrEmpty(String string, int index) {
|
private String charOrEmpty(String string, int index) {
|
||||||
return string.length() <= index ? " " : string.substring(index, index + 1);
|
return string.length() <= index ? " " : string.substring(index, index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Component parseCustomText() {
|
|
||||||
try {
|
|
||||||
return parseDynamicComponent(Component.Serializer.fromJson(rawCustomText));
|
|
||||||
} catch (JsonParseException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Component parseDynamicComponent(Component customText) {
|
|
||||||
if (level instanceof ServerLevel) {
|
|
||||||
try {
|
|
||||||
return ComponentUtils.updateForEntity(getCommandSource(null), customText, null, 0);
|
|
||||||
} catch (CommandSyntaxException e) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return customText;
|
|
||||||
}
|
|
||||||
|
|
||||||
// From SignTileEntity
|
|
||||||
public CommandSourceStack getCommandSource(@Nullable ServerPlayer p_195539_1_) {
|
|
||||||
String s = p_195539_1_ == null ? "Nixie Tube"
|
|
||||||
: p_195539_1_.getName()
|
|
||||||
.getString();
|
|
||||||
Component itextcomponent =
|
|
||||||
(Component) (p_195539_1_ == null ? new TextComponent("Nixie Tube") : p_195539_1_.getDisplayName());
|
|
||||||
return new CommandSourceStack(CommandSource.NULL, Vec3.atCenterOf(this.worldPosition), Vec2.ZERO,
|
|
||||||
(ServerLevel) this.level, 2, s, itextcomponent, this.level.getServer(), p_195539_1_);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
|
public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.simibubi.create.content.logistics.block.redstone;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererBlock;
|
||||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
||||||
|
@ -145,8 +146,10 @@ public class StockpileSwitchTileEntity extends SmartTileEntity {
|
||||||
if (update)
|
if (update)
|
||||||
scheduleBlockTick();
|
scheduleBlockTick();
|
||||||
|
|
||||||
if (changed || update)
|
if (changed || update) {
|
||||||
sendData();
|
DataGathererBlock.notifyGatherers(level, worldPosition);
|
||||||
|
notifyUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void scheduleBlockTick() {
|
protected void scheduleBlockTick() {
|
||||||
|
|
|
@ -19,6 +19,7 @@ import com.simibubi.create.AllKeys;
|
||||||
import com.simibubi.create.CreateClient;
|
import com.simibubi.create.CreateClient;
|
||||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||||
import com.simibubi.create.content.logistics.trains.entity.TrainPacket;
|
import com.simibubi.create.content.logistics.trains.entity.TrainPacket;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.GlobalTrainDisplayData;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup;
|
||||||
import com.simibubi.create.foundation.networking.AllPackets;
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
|
|
||||||
|
@ -91,6 +92,7 @@ public class GlobalRailwayManager {
|
||||||
sync = new TrackGraphSync();
|
sync = new TrackGraphSync();
|
||||||
movingTrains = new LinkedList<>();
|
movingTrains = new LinkedList<>();
|
||||||
waitingTrains = new LinkedList<>();
|
waitingTrains = new LinkedList<>();
|
||||||
|
GlobalTrainDisplayData.statusByDestination.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void markTracksDirty() {
|
public void markTracksDirty() {
|
||||||
|
@ -176,6 +178,10 @@ public class GlobalRailwayManager {
|
||||||
for (TrackGraph graph : trackNetworks.values())
|
for (TrackGraph graph : trackNetworks.values())
|
||||||
graph.tickPoints(false);
|
graph.tickPoints(false);
|
||||||
|
|
||||||
|
GlobalTrainDisplayData.updateTick = level.getGameTime() % 100 == 0;
|
||||||
|
if (GlobalTrainDisplayData.updateTick)
|
||||||
|
GlobalTrainDisplayData.refresh();
|
||||||
|
|
||||||
// if (AllKeys.isKeyDown(GLFW.GLFW_KEY_K))
|
// if (AllKeys.isKeyDown(GLFW.GLFW_KEY_K))
|
||||||
// trackNetworks.values()
|
// trackNetworks.values()
|
||||||
// .forEach(TrackGraph::debugViewReserved);
|
// .forEach(TrackGraph::debugViewReserved);
|
||||||
|
|
|
@ -50,6 +50,7 @@ public class Navigation {
|
||||||
|
|
||||||
public GlobalStation destination;
|
public GlobalStation destination;
|
||||||
public double distanceToDestination;
|
public double distanceToDestination;
|
||||||
|
public double distanceStartedAt;
|
||||||
public boolean destinationBehindTrain;
|
public boolean destinationBehindTrain;
|
||||||
List<Couple<TrackNode>> currentPath;
|
List<Couple<TrackNode>> currentPath;
|
||||||
|
|
||||||
|
@ -135,7 +136,8 @@ public class Navigation {
|
||||||
MutableObject<Pair<UUID, Boolean>> trackingCrossSignal = new MutableObject<>(null);
|
MutableObject<Pair<UUID, Boolean>> trackingCrossSignal = new MutableObject<>(null);
|
||||||
waitingForChainedGroups.clear();
|
waitingForChainedGroups.clear();
|
||||||
|
|
||||||
// Adding 50 to the distance due to unresolved inaccuracies in TravellingPoint::travel
|
// Adding 50 to the distance due to unresolved inaccuracies in
|
||||||
|
// TravellingPoint::travel
|
||||||
signalScout.travel(train.graph, (distanceToDestination + 50) * speedMod, controlSignalScout(),
|
signalScout.travel(train.graph, (distanceToDestination + 50) * speedMod, controlSignalScout(),
|
||||||
(distance, couple) -> {
|
(distance, couple) -> {
|
||||||
// > scanDistance and not following down a cross signal
|
// > scanDistance and not following down a cross signal
|
||||||
|
@ -358,7 +360,7 @@ public class Navigation {
|
||||||
distanceToDestination = distance;
|
distanceToDestination = distance;
|
||||||
|
|
||||||
if (noneFound) {
|
if (noneFound) {
|
||||||
distanceToDestination = 0;
|
distanceToDestination = distanceStartedAt = 0;
|
||||||
currentPath = new ArrayList<>();
|
currentPath = new ArrayList<>();
|
||||||
if (this.destination != null)
|
if (this.destination != null)
|
||||||
cancelNavigation();
|
cancelNavigation();
|
||||||
|
@ -370,6 +372,9 @@ public class Navigation {
|
||||||
train.reservedSignalBlocks.clear();
|
train.reservedSignalBlocks.clear();
|
||||||
train.navigation.waitingForSignal = null;
|
train.navigation.waitingForSignal = null;
|
||||||
|
|
||||||
|
if (this.destination == null && !simulate)
|
||||||
|
distanceStartedAt = distance;
|
||||||
|
|
||||||
if (this.destination == destination)
|
if (this.destination == destination)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -677,6 +682,7 @@ public class Navigation {
|
||||||
return tag;
|
return tag;
|
||||||
tag.putUUID("Destination", destination.id);
|
tag.putUUID("Destination", destination.id);
|
||||||
tag.putDouble("DistanceToDestination", distanceToDestination);
|
tag.putDouble("DistanceToDestination", distanceToDestination);
|
||||||
|
tag.putDouble("DistanceStartedAt", distanceStartedAt);
|
||||||
tag.putBoolean("BehindTrain", destinationBehindTrain);
|
tag.putBoolean("BehindTrain", destinationBehindTrain);
|
||||||
tag.put("Path", NBTHelper.writeCompoundList(currentPath, c -> {
|
tag.put("Path", NBTHelper.writeCompoundList(currentPath, c -> {
|
||||||
CompoundTag nbt = new CompoundTag();
|
CompoundTag nbt = new CompoundTag();
|
||||||
|
@ -700,6 +706,7 @@ public class Navigation {
|
||||||
if (destination == null)
|
if (destination == null)
|
||||||
return;
|
return;
|
||||||
distanceToDestination = tag.getDouble("DistanceToDestination");
|
distanceToDestination = tag.getDouble("DistanceToDestination");
|
||||||
|
distanceStartedAt = tag.getDouble("DistanceStartedAt");
|
||||||
destinationBehindTrain = tag.getBoolean("BehindTrain");
|
destinationBehindTrain = tag.getBoolean("BehindTrain");
|
||||||
currentPath.clear();
|
currentPath.clear();
|
||||||
NBTHelper.iterateCompoundList(tag.getList("Path", Tag.TAG_COMPOUND),
|
NBTHelper.iterateCompoundList(tag.getList("Path", Tag.TAG_COMPOUND),
|
||||||
|
|
|
@ -0,0 +1,300 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.management.display;
|
||||||
|
|
||||||
|
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllShapes;
|
||||||
|
import com.simibubi.create.AllTileEntities;
|
||||||
|
import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel;
|
||||||
|
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
||||||
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
|
||||||
|
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.nbt.Tag;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.InteractionHand;
|
||||||
|
import net.minecraft.world.InteractionResult;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.item.DyeColor;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.Items;
|
||||||
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||||
|
import net.minecraft.world.level.BlockGetter;
|
||||||
|
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.SimpleWaterloggedBlock;
|
||||||
|
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.BlockStateProperties;
|
||||||
|
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||||
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
import net.minecraft.world.level.material.Fluids;
|
||||||
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
|
import net.minecraft.world.ticks.LevelTickAccess;
|
||||||
|
|
||||||
|
public class FlapDisplayBlock extends HorizontalKineticBlock
|
||||||
|
implements ITE<FlapDisplayTileEntity>, IWrenchable, ICogWheel, SimpleWaterloggedBlock {
|
||||||
|
|
||||||
|
public static final BooleanProperty UP = BooleanProperty.create("up");
|
||||||
|
public static final BooleanProperty DOWN = BooleanProperty.create("down");
|
||||||
|
|
||||||
|
public FlapDisplayBlock(Properties p_49795_) {
|
||||||
|
super(p_49795_);
|
||||||
|
registerDefaultState(defaultBlockState().setValue(UP, false)
|
||||||
|
.setValue(DOWN, false)
|
||||||
|
.setValue(WATERLOGGED, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean areStatesKineticallyEquivalent(BlockState oldState, BlockState newState) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Axis getRotationAxis(BlockState state) {
|
||||||
|
return state.getValue(HORIZONTAL_FACING)
|
||||||
|
.getAxis();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createBlockStateDefinition(Builder<Block, BlockState> builder) {
|
||||||
|
super.createBlockStateDefinition(builder.add(UP, DOWN, WATERLOGGED));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpeedLevel getMinimumRequiredSpeedLevel() {
|
||||||
|
return SpeedLevel.MEDIUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||||
|
Direction face = context.getClickedFace();
|
||||||
|
BlockPos clickedPos = context.getClickedPos();
|
||||||
|
BlockPos placedOnPos = clickedPos.relative(face.getOpposite());
|
||||||
|
Level level = context.getLevel();
|
||||||
|
BlockState blockState = level.getBlockState(placedOnPos);
|
||||||
|
BlockState stateForPlacement = defaultBlockState();
|
||||||
|
FluidState ifluidstate = context.getLevel()
|
||||||
|
.getFluidState(context.getClickedPos());
|
||||||
|
|
||||||
|
if ((blockState.getBlock() != this) || (context.getPlayer() != null && context.getPlayer()
|
||||||
|
.isShiftKeyDown()))
|
||||||
|
stateForPlacement = super.getStateForPlacement(context);
|
||||||
|
else {
|
||||||
|
Direction otherFacing = blockState.getValue(HORIZONTAL_FACING);
|
||||||
|
stateForPlacement = stateForPlacement.setValue(HORIZONTAL_FACING, otherFacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateColumn(level, clickedPos,
|
||||||
|
stateForPlacement.setValue(WATERLOGGED, Boolean.valueOf(ifluidstate.getType() == Fluids.WATER)), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand,
|
||||||
|
BlockHitResult ray) {
|
||||||
|
|
||||||
|
if (player.isShiftKeyDown())
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
|
||||||
|
ItemStack heldItem = player.getItemInHand(hand);
|
||||||
|
FlapDisplayTileEntity flapTe = getTileEntity(world, pos);
|
||||||
|
|
||||||
|
if (flapTe == null)
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
flapTe = flapTe.getController();
|
||||||
|
if (flapTe == null)
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
|
||||||
|
double yCoord = ray.getLocation()
|
||||||
|
.add(Vec3.atLowerCornerOf(ray.getDirection()
|
||||||
|
.getOpposite()
|
||||||
|
.getNormal())
|
||||||
|
.scale(.125f)).y;
|
||||||
|
int lineIndex = flapTe.getLineIndexAt(yCoord);
|
||||||
|
|
||||||
|
if (heldItem.isEmpty()) {
|
||||||
|
if (!flapTe.isSpeedRequirementFulfilled())
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
flapTe.applyTextManually(lineIndex, null);
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean display = heldItem.getItem() == Items.NAME_TAG && heldItem.hasCustomHoverName();
|
||||||
|
DyeColor dye = DyeColor.getColor(heldItem);
|
||||||
|
|
||||||
|
if (!display && dye == null)
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
if (dye == null && !flapTe.isSpeedRequirementFulfilled())
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
if (world.isClientSide)
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
|
||||||
|
CompoundTag tag = heldItem.getTagElement("display");
|
||||||
|
String tagElement = tag != null && tag.contains("Name", Tag.TAG_STRING) ? tag.getString("Name") : null;
|
||||||
|
|
||||||
|
if (display)
|
||||||
|
flapTe.applyTextManually(lineIndex, tagElement);
|
||||||
|
if (dye != null)
|
||||||
|
flapTe.setColour(lineIndex, dye);
|
||||||
|
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
|
||||||
|
return AllShapes.FLAP_DISPLAY.get(pState.getValue(HORIZONTAL_FACING));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<FlapDisplayTileEntity> getTileEntityClass() {
|
||||||
|
return FlapDisplayTileEntity.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockEntityType<? extends FlapDisplayTileEntity> getTileEntityType() {
|
||||||
|
return AllTileEntities.FLAP_DISPLAY.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getParticleTargetRadius() {
|
||||||
|
return .85f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getParticleInitialRadius() {
|
||||||
|
return .75f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockState updateColumn(Level level, BlockPos pos, BlockState state, boolean present) {
|
||||||
|
MutableBlockPos currentPos = new MutableBlockPos();
|
||||||
|
Axis axis = getConnectionAxis(state);
|
||||||
|
|
||||||
|
for (Direction connection : Iterate.directions) {
|
||||||
|
if (connection.getAxis() == axis)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
boolean connect = true;
|
||||||
|
Move: for (Direction movement : Iterate.directionsInAxis(axis)) {
|
||||||
|
currentPos.set(pos);
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
if (!level.isAreaLoaded(currentPos, 1))
|
||||||
|
break;
|
||||||
|
|
||||||
|
BlockState other1 = currentPos.equals(pos) ? state : level.getBlockState(currentPos);
|
||||||
|
BlockState other2 = level.getBlockState(currentPos.relative(connection));
|
||||||
|
boolean col1 = canConnect(state, other1);
|
||||||
|
boolean col2 = canConnect(state, other2);
|
||||||
|
currentPos.move(movement);
|
||||||
|
|
||||||
|
if (!col1 && !col2)
|
||||||
|
break;
|
||||||
|
if (col1 && col2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
connect = false;
|
||||||
|
break Move;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state = setConnection(state, connection, connect);
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlace(BlockState pState, Level pLevel, BlockPos pPos, BlockState pOldState, boolean pIsMoving) {
|
||||||
|
if (pOldState.getBlock() == this)
|
||||||
|
return;
|
||||||
|
LevelTickAccess<Block> blockTicks = pLevel.getBlockTicks();
|
||||||
|
if (!blockTicks.hasScheduledTick(pPos, this))
|
||||||
|
pLevel.scheduleTick(pPos, this, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, Random pRandom) {
|
||||||
|
if (pState.getBlock() != this)
|
||||||
|
return;
|
||||||
|
BlockPos belowPos =
|
||||||
|
pPos.relative(Direction.fromAxisAndDirection(getConnectionAxis(pState), AxisDirection.NEGATIVE));
|
||||||
|
BlockState belowState = pLevel.getBlockState(belowPos);
|
||||||
|
if (!canConnect(pState, belowState))
|
||||||
|
KineticTileEntity.switchToBlockState(pLevel, pPos, updateColumn(pLevel, pPos, pState, true));
|
||||||
|
withTileEntityDo(pLevel, pPos, FlapDisplayTileEntity::updateControllerStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState updateShape(BlockState state, Direction pDirection, BlockState pNeighborState,
|
||||||
|
LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) {
|
||||||
|
BlockState newState = updatedShapeInner(state, pDirection, pNeighborState, pLevel, pCurrentPos);
|
||||||
|
if (pLevel instanceof Level level)
|
||||||
|
KineticTileEntity.switchToBlockState(level, pCurrentPos, newState);
|
||||||
|
return newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockState updatedShapeInner(BlockState state, Direction pDirection, BlockState pNeighborState,
|
||||||
|
LevelAccessor pLevel, BlockPos pCurrentPos) {
|
||||||
|
if (state.getValue(BlockStateProperties.WATERLOGGED))
|
||||||
|
pLevel.scheduleTick(pCurrentPos, Fluids.WATER, Fluids.WATER.getTickDelay(pLevel));
|
||||||
|
if (!canConnect(state, pNeighborState))
|
||||||
|
return setConnection(state, pDirection, false);
|
||||||
|
if (pDirection.getAxis() == getConnectionAxis(state))
|
||||||
|
return withPropertiesOf(pNeighborState).setValue(WATERLOGGED, state.getValue(WATERLOGGED));
|
||||||
|
return setConnection(state, pDirection, getConnection(pNeighborState, pDirection.getOpposite()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FluidState getFluidState(BlockState state) {
|
||||||
|
return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false)
|
||||||
|
: Fluids.EMPTY.defaultFluidState();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean canConnect(BlockState state, BlockState other) {
|
||||||
|
return other.getBlock() == this && state.getValue(HORIZONTAL_FACING) == other.getValue(HORIZONTAL_FACING);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Axis getConnectionAxis(BlockState state) {
|
||||||
|
return state.getValue(HORIZONTAL_FACING)
|
||||||
|
.getClockWise()
|
||||||
|
.getAxis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean getConnection(BlockState state, Direction side) {
|
||||||
|
BooleanProperty property = side == Direction.DOWN ? DOWN : side == Direction.UP ? UP : null;
|
||||||
|
return property != null && state.getValue(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockState setConnection(BlockState state, Direction side, boolean connect) {
|
||||||
|
BooleanProperty property = side == Direction.DOWN ? DOWN : side == Direction.UP ? UP : null;
|
||||||
|
if (property != null)
|
||||||
|
state = state.setValue(property, connect);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) {
|
||||||
|
if (pState.hasBlockEntity() && (!pState.is(pNewState.getBlock()) || !pNewState.hasBlockEntity()))
|
||||||
|
pLevel.removeBlockEntity(pPos);
|
||||||
|
if (pIsMoving || pNewState.getBlock() == this)
|
||||||
|
return;
|
||||||
|
for (Direction d : Iterate.directionsInAxis(getConnectionAxis(pState))) {
|
||||||
|
BlockPos relative = pPos.relative(d);
|
||||||
|
BlockState adjacent = pLevel.getBlockState(relative);
|
||||||
|
if (canConnect(pState, adjacent))
|
||||||
|
KineticTileEntity.switchToBlockState(pLevel, relative, updateColumn(pLevel, relative, adjacent, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.management.display;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.mutable.MutableInt;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
|
||||||
|
public class FlapDisplayLayout {
|
||||||
|
|
||||||
|
List<FlapDisplaySection> sections;
|
||||||
|
String layoutKey;
|
||||||
|
|
||||||
|
public FlapDisplayLayout(int maxCharCount) {
|
||||||
|
loadDefault(maxCharCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadDefault(int maxCharCount) {
|
||||||
|
configure("Default", Arrays
|
||||||
|
.asList(new FlapDisplaySection(maxCharCount * FlapDisplaySection.MONOSPACE, "alphabet", false, false)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLayout(String key) {
|
||||||
|
return layoutKey.equals(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void configure(String layoutKey, List<FlapDisplaySection> sections) {
|
||||||
|
this.layoutKey = layoutKey;
|
||||||
|
this.sections = sections;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundTag write() {
|
||||||
|
CompoundTag tag = new CompoundTag();
|
||||||
|
tag.putString("Key", layoutKey);
|
||||||
|
tag.put("Sections", NBTHelper.writeCompoundList(sections, FlapDisplaySection::write));
|
||||||
|
return tag;
|
||||||
|
};
|
||||||
|
|
||||||
|
public void read(CompoundTag tag) {
|
||||||
|
String prevKey = layoutKey;
|
||||||
|
layoutKey = tag.getString("Key");
|
||||||
|
ListTag sectionsTag = tag.getList("Sections", Tag.TAG_COMPOUND);
|
||||||
|
|
||||||
|
if (!prevKey.equals(layoutKey)) {
|
||||||
|
sections = NBTHelper.readCompoundList(sectionsTag, FlapDisplaySection::load);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MutableInt index = new MutableInt(0);
|
||||||
|
NBTHelper.iterateCompoundList(sectionsTag, nbt -> sections.get(index.getAndIncrement())
|
||||||
|
.update(nbt));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FlapDisplaySection> getSections() {
|
||||||
|
return sections;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,244 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.management.display;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||||
|
import com.mojang.blaze3d.font.GlyphInfo;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack.Pose;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
import com.mojang.math.Matrix4f;
|
||||||
|
import com.simibubi.create.AllBlockPartials;
|
||||||
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||||
|
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.AnimationTickHolder;
|
||||||
|
import com.simibubi.create.foundation.utility.DyeHelper;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.Font;
|
||||||
|
import net.minecraft.client.gui.font.FontSet;
|
||||||
|
import net.minecraft.client.gui.font.glyphs.BakedGlyph;
|
||||||
|
import net.minecraft.client.gui.font.glyphs.EmptyGlyph;
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource.BufferSource;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||||
|
import net.minecraft.network.chat.Style;
|
||||||
|
import net.minecraft.network.chat.TextColor;
|
||||||
|
import net.minecraft.util.FormattedCharSink;
|
||||||
|
import net.minecraft.util.StringDecomposer;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public class FlapDisplayRenderer extends KineticTileEntityRenderer {
|
||||||
|
|
||||||
|
public FlapDisplayRenderer(BlockEntityRendererProvider.Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer,
|
||||||
|
int light, int overlay) {
|
||||||
|
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
|
||||||
|
|
||||||
|
Font fontRenderer = Minecraft.getInstance().font;
|
||||||
|
FontSet fontSet = fontRenderer.getFontSet(Style.DEFAULT_FONT);
|
||||||
|
|
||||||
|
float scale = 1 / 32f;
|
||||||
|
|
||||||
|
if (!(te instanceof FlapDisplayTileEntity flapTe))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!flapTe.isController)
|
||||||
|
return;
|
||||||
|
|
||||||
|
List<FlapDisplayLayout> lines = flapTe.getLines();
|
||||||
|
|
||||||
|
ms.pushPose();
|
||||||
|
TransformStack.cast(ms)
|
||||||
|
.centre()
|
||||||
|
.rotateY(AngleHelper.horizontalAngle(te.getBlockState()
|
||||||
|
.getValue(FlapDisplayBlock.HORIZONTAL_FACING)))
|
||||||
|
.unCentre()
|
||||||
|
.translate(0, 0, -3 / 16f);
|
||||||
|
|
||||||
|
ms.translate(0, 1, 1);
|
||||||
|
ms.scale(scale, scale, scale);
|
||||||
|
ms.scale(1, -1, 1);
|
||||||
|
ms.translate(0, 0, 1 / 2f);
|
||||||
|
|
||||||
|
for (int j = 0; j < lines.size(); j++) {
|
||||||
|
List<FlapDisplaySection> line = lines.get(j)
|
||||||
|
.getSections();
|
||||||
|
int color = flapTe.colour[j] == null ? 0xFF_D3C6BA
|
||||||
|
: DyeHelper.DYE_TABLE.get(flapTe.colour[j])
|
||||||
|
.getFirst() | 0xFF_000000;
|
||||||
|
ms.pushPose();
|
||||||
|
|
||||||
|
float w = 0;
|
||||||
|
for (FlapDisplaySection section : line) {
|
||||||
|
w += section.getSize() + (section.hasGap ? 8 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ms.translate(flapTe.xSize * 16 - w / 2 + 1, 4, 0);
|
||||||
|
|
||||||
|
Pose transform = ms.last();
|
||||||
|
FlapDisplayRenderOutput renderOutput = new FlapDisplayRenderOutput(buffer, color, transform.pose(), light,
|
||||||
|
j, !te.isSpeedRequirementFulfilled());
|
||||||
|
|
||||||
|
for (int i = 0; i < line.size(); i++) {
|
||||||
|
FlapDisplaySection section = line.get(i);
|
||||||
|
renderOutput.nextSection(section);
|
||||||
|
int ticks = AnimationTickHolder.getTicks();
|
||||||
|
String text = section.renderCharsIndividually() || !section.spinning[0] ? section.text
|
||||||
|
: section.cyclingOptions[((ticks / 3) + i * 13) % section.cyclingOptions.length];
|
||||||
|
StringDecomposer.iterateFormatted(text, Style.EMPTY, renderOutput);
|
||||||
|
ms.translate(0, 0, -1 / 4f);
|
||||||
|
renderOutput.finish(0x55000000);
|
||||||
|
ms.translate(0, 0, 1 / 4f);
|
||||||
|
ms.translate(section.size + (section.hasGap ? 8 : 1), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer instanceof BufferSource bs) {
|
||||||
|
BakedGlyph texturedglyph = fontSet.whiteGlyph();
|
||||||
|
bs.endBatch(texturedglyph.renderType(Font.DisplayMode.NORMAL));
|
||||||
|
}
|
||||||
|
|
||||||
|
ms.popPose();
|
||||||
|
ms.translate(0, 16, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ms.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
class FlapDisplayRenderOutput implements FormattedCharSink {
|
||||||
|
|
||||||
|
final MultiBufferSource bufferSource;
|
||||||
|
final float r, g, b, a;
|
||||||
|
final Matrix4f pose;
|
||||||
|
final int light;
|
||||||
|
final boolean paused;
|
||||||
|
|
||||||
|
FlapDisplaySection section;
|
||||||
|
float x;
|
||||||
|
private int lineIndex;
|
||||||
|
|
||||||
|
public FlapDisplayRenderOutput(MultiBufferSource buffer, int color, Matrix4f pose, int light, int lineIndex,
|
||||||
|
boolean paused) {
|
||||||
|
this.bufferSource = buffer;
|
||||||
|
this.lineIndex = lineIndex;
|
||||||
|
this.a = (color >> 24 & 255) / 255f;
|
||||||
|
this.r = (color >> 16 & 255) / 255f;
|
||||||
|
this.g = (color >> 8 & 255) / 255f;
|
||||||
|
this.b = (color & 255) / 255f;
|
||||||
|
this.pose = pose;
|
||||||
|
this.light = light;
|
||||||
|
this.paused = paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void nextSection(FlapDisplaySection section) {
|
||||||
|
this.section = section;
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean accept(int charIndex, Style style, int glyph) {
|
||||||
|
FontSet fontset = getFontSet();
|
||||||
|
int ticks = paused ? 0 : AnimationTickHolder.getTicks();
|
||||||
|
float time = paused ? 0 : AnimationTickHolder.getRenderTime();
|
||||||
|
float dim = 1;
|
||||||
|
|
||||||
|
if (section.renderCharsIndividually() && section.spinning[Math.min(charIndex, section.spinning.length)]) {
|
||||||
|
float speed = section.spinningTicks > 5 && section.spinningTicks < 20 ? 1.75f : 2.5f;
|
||||||
|
float cycle = (time / speed) + charIndex * 16.83f + lineIndex * 0.75f;
|
||||||
|
float partial = cycle % 1;
|
||||||
|
char cyclingGlyph = section.cyclingOptions[((int) cycle) % section.cyclingOptions.length].charAt(0);
|
||||||
|
glyph = paused ? cyclingGlyph : partial > 1 / 2f ? partial > 3 / 4f ? '_' : '-' : cyclingGlyph;
|
||||||
|
dim = 0.75f;
|
||||||
|
}
|
||||||
|
|
||||||
|
GlyphInfo glyphinfo = fontset.getGlyphInfo(glyph);
|
||||||
|
float glyphWidth = glyphinfo.getAdvance(false);
|
||||||
|
|
||||||
|
if (!section.renderCharsIndividually() && section.spinning[0]) {
|
||||||
|
glyph = ticks % 3 == 0 ? glyphWidth == 6 ? '-' : glyphWidth == 1 ? '\'' : glyph : glyph;
|
||||||
|
glyph = ticks % 3 == 2 ? glyphWidth == 6 ? '_' : glyphWidth == 1 ? '.' : glyph : glyph;
|
||||||
|
if (ticks % 3 != 1)
|
||||||
|
dim = 0.75f;
|
||||||
|
}
|
||||||
|
|
||||||
|
BakedGlyph bakedglyph =
|
||||||
|
style.isObfuscated() && glyph != 32 ? fontset.getRandomGlyph(glyphinfo) : fontset.getGlyph(glyph);
|
||||||
|
TextColor textcolor = style.getColor();
|
||||||
|
|
||||||
|
float red = this.r * dim;
|
||||||
|
float green = this.g * dim;
|
||||||
|
float blue = this.b * dim;
|
||||||
|
|
||||||
|
if (textcolor != null) {
|
||||||
|
int i = textcolor.getValue();
|
||||||
|
red = (i >> 16 & 255) / 255f;
|
||||||
|
green = (i >> 8 & 255) / 255f;
|
||||||
|
blue = (i & 255) / 255f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float standardWidth = section.wideFlaps ? FlapDisplaySection.WIDE_MONOSPACE : FlapDisplaySection.MONOSPACE;
|
||||||
|
|
||||||
|
if (section.renderCharsIndividually())
|
||||||
|
x += (standardWidth - glyphWidth) / 2f;
|
||||||
|
|
||||||
|
if (!(bakedglyph instanceof EmptyGlyph)) {
|
||||||
|
VertexConsumer vertexconsumer = bufferSource.getBuffer(renderTypeOf(bakedglyph));
|
||||||
|
bakedglyph.render(style.isItalic(), x, 0, pose, vertexconsumer, red, green, blue, a, light);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (section.renderCharsIndividually())
|
||||||
|
x += standardWidth - (standardWidth - glyphWidth) / 2f;
|
||||||
|
else
|
||||||
|
x += glyphWidth;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float finish(int bgColor) {
|
||||||
|
if (bgColor == 0)
|
||||||
|
return x;
|
||||||
|
|
||||||
|
float a = (bgColor >> 24 & 255) / 255f;
|
||||||
|
float r = (bgColor >> 16 & 255) / 255f;
|
||||||
|
float g = (bgColor >> 8 & 255) / 255f;
|
||||||
|
float b = (bgColor & 255) / 255f;
|
||||||
|
|
||||||
|
BakedGlyph bakedglyph = getFontSet().whiteGlyph();
|
||||||
|
VertexConsumer vertexconsumer = bufferSource.getBuffer(renderTypeOf(bakedglyph));
|
||||||
|
bakedglyph.renderEffect(new BakedGlyph.Effect(-1f, 9f, section.size, -2f, 0.01f, r, g, b, a), this.pose,
|
||||||
|
vertexconsumer, light);
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FontSet getFontSet() {
|
||||||
|
return Minecraft.getInstance().font.getFontSet(Style.DEFAULT_FONT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RenderType renderTypeOf(BakedGlyph bakedglyph) {
|
||||||
|
return bakedglyph.renderType(Font.DisplayMode.NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SuperByteBuffer getRotatedModel(KineticTileEntity te, BlockState state) {
|
||||||
|
return CachedBufferer.partial(AllBlockPartials.SHAFTLESS_COGWHEEL, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRenderOffScreen(KineticTileEntity pBlockEntity) {
|
||||||
|
return ((FlapDisplayTileEntity) pBlockEntity).isController;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.management.display;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
|
||||||
|
public class FlapDisplaySection {
|
||||||
|
|
||||||
|
static final Map<String, String[]> LOADED_FLAP_CYCLES = new HashMap<>();
|
||||||
|
|
||||||
|
public static final float MONOSPACE = 7;
|
||||||
|
public static final float WIDE_MONOSPACE = 9;
|
||||||
|
|
||||||
|
float size;
|
||||||
|
boolean singleFlap;
|
||||||
|
boolean hasGap;
|
||||||
|
boolean rightAligned;
|
||||||
|
boolean wideFlaps;
|
||||||
|
String cycle;
|
||||||
|
Component component;
|
||||||
|
|
||||||
|
// Client
|
||||||
|
String[] cyclingOptions;
|
||||||
|
boolean[] spinning;
|
||||||
|
int spinningTicks;
|
||||||
|
String text;
|
||||||
|
|
||||||
|
public FlapDisplaySection(float width, String cycle, boolean singleFlap, boolean hasGap) {
|
||||||
|
this.size = width;
|
||||||
|
this.cycle = cycle;
|
||||||
|
this.hasGap = hasGap;
|
||||||
|
this.singleFlap = singleFlap;
|
||||||
|
this.spinning = new boolean[singleFlap ? 1 : (int) (width / FlapDisplaySection.MONOSPACE)];
|
||||||
|
this.text = Strings.repeat(" ", spinning.length);
|
||||||
|
this.component = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlapDisplaySection rightAligned() {
|
||||||
|
rightAligned = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlapDisplaySection wideFlaps() {
|
||||||
|
wideFlaps = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(Component component) {
|
||||||
|
this.component = component;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refresh(boolean transition) {
|
||||||
|
if (component == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
String newText = component.getString();
|
||||||
|
|
||||||
|
if (!singleFlap) {
|
||||||
|
if (rightAligned)
|
||||||
|
newText = newText.trim();
|
||||||
|
newText = newText.toUpperCase(Locale.ROOT);
|
||||||
|
newText = newText.substring(0, Math.min(spinning.length, newText.length()));
|
||||||
|
String whitespace = Strings.repeat(" ", spinning.length - newText.length());
|
||||||
|
newText = rightAligned ? whitespace + newText : newText + whitespace;
|
||||||
|
if (!text.isEmpty())
|
||||||
|
for (int i = 0; i < spinning.length; i++)
|
||||||
|
spinning[i] |= text.charAt(i) != newText.charAt(i);
|
||||||
|
} else if (!text.isEmpty())
|
||||||
|
spinning[0] |= !newText.equals(text);
|
||||||
|
|
||||||
|
text = newText;
|
||||||
|
spinningTicks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick() {
|
||||||
|
if (cyclingOptions == null)
|
||||||
|
return;
|
||||||
|
int max = Math.max(4, (int) (cyclingOptions.length * 1.75f));
|
||||||
|
if (spinningTicks > max)
|
||||||
|
return;
|
||||||
|
spinningTicks++;
|
||||||
|
if (spinningTicks <= max && spinningTicks < 2)
|
||||||
|
return;
|
||||||
|
for (int i = 0; i < spinning.length; i++) {
|
||||||
|
int increasingChance = Mth.clamp(8 - spinningTicks, 1, 10);
|
||||||
|
boolean continueSpin = Create.RANDOM.nextInt(increasingChance * max / 4) != 0;
|
||||||
|
continueSpin &= max > 5 || spinningTicks < 2;
|
||||||
|
spinning[i] &= continueSpin;
|
||||||
|
|
||||||
|
if (i > 0 && Create.RANDOM.nextInt(3) > 0)
|
||||||
|
spinning[i - 1] &= continueSpin;
|
||||||
|
if (i < spinning.length - 1 && Create.RANDOM.nextInt(3) > 0)
|
||||||
|
spinning[i + 1] &= continueSpin;
|
||||||
|
if (spinningTicks > max)
|
||||||
|
spinning[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundTag write() {
|
||||||
|
CompoundTag tag = new CompoundTag();
|
||||||
|
tag.putFloat("Width", size);
|
||||||
|
tag.putString("Cycle", cycle);
|
||||||
|
if (rightAligned)
|
||||||
|
NBTHelper.putMarker(tag, "RightAligned");
|
||||||
|
if (singleFlap)
|
||||||
|
NBTHelper.putMarker(tag, "SingleFlap");
|
||||||
|
if (hasGap)
|
||||||
|
NBTHelper.putMarker(tag, "Gap");
|
||||||
|
if (wideFlaps)
|
||||||
|
NBTHelper.putMarker(tag, "Wide");
|
||||||
|
if (component != null)
|
||||||
|
tag.putString("Text", Component.Serializer.toJson(component));
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FlapDisplaySection load(CompoundTag tag) {
|
||||||
|
float width = tag.getFloat("Width");
|
||||||
|
String cycle = tag.getString("Cycle");
|
||||||
|
boolean singleFlap = tag.contains("SingleFlap");
|
||||||
|
boolean hasGap = tag.contains("Gap");
|
||||||
|
|
||||||
|
FlapDisplaySection section = new FlapDisplaySection(width, cycle, singleFlap, hasGap);
|
||||||
|
section.cyclingOptions = getFlapCycle(cycle);
|
||||||
|
section.rightAligned = tag.contains("RightAligned");
|
||||||
|
section.wideFlaps = tag.contains("Wide");
|
||||||
|
|
||||||
|
if (!tag.contains("Text"))
|
||||||
|
return section;
|
||||||
|
|
||||||
|
section.component = Component.Serializer.fromJson(tag.getString("Text"));
|
||||||
|
section.refresh(false);
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(CompoundTag tag) {
|
||||||
|
component = Component.Serializer.fromJson(tag.getString("Text"));
|
||||||
|
if (cyclingOptions == null)
|
||||||
|
cyclingOptions = getFlapCycle(cycle);
|
||||||
|
refresh(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean renderCharsIndividually() {
|
||||||
|
return !singleFlap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String[] getFlapCycle(String key) {
|
||||||
|
return LOADED_FLAP_CYCLES.computeIfAbsent(key, k -> Lang.translate("flap_display.cycles." + key)
|
||||||
|
.getString()
|
||||||
|
.split(";"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,279 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.management.display;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
|
import com.simibubi.create.foundation.utility.DynamicComponent;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.core.Vec3i;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.item.DyeColor;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
|
||||||
|
public class FlapDisplayTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
|
public List<FlapDisplayLayout> lines;
|
||||||
|
public boolean isController;
|
||||||
|
public boolean isRunning;
|
||||||
|
public int xSize, ySize;
|
||||||
|
public DyeColor[] colour;
|
||||||
|
public boolean[] manualLines;
|
||||||
|
|
||||||
|
public FlapDisplayTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||||
|
super(type, pos, state);
|
||||||
|
setLazyTickRate(10);
|
||||||
|
isController = false;
|
||||||
|
xSize = 1;
|
||||||
|
ySize = 1;
|
||||||
|
colour = new DyeColor[2];
|
||||||
|
manualLines = new boolean[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lazyTick() {
|
||||||
|
super.lazyTick();
|
||||||
|
updateControllerStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateControllerStatus() {
|
||||||
|
if (level.isClientSide)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BlockState blockState = getBlockState();
|
||||||
|
if (!(blockState.getBlock() instanceof FlapDisplayBlock))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Direction leftDirection = blockState.getValue(FlapDisplayBlock.HORIZONTAL_FACING)
|
||||||
|
.getClockWise();
|
||||||
|
boolean shouldBeController = !blockState.getValue(FlapDisplayBlock.UP)
|
||||||
|
&& level.getBlockState(worldPosition.relative(leftDirection)) != blockState;
|
||||||
|
|
||||||
|
int newXSize = 1;
|
||||||
|
int newYSize = 1;
|
||||||
|
|
||||||
|
if (shouldBeController) {
|
||||||
|
for (int xOffset = 1; xOffset < 32; xOffset++) {
|
||||||
|
if (level.getBlockState(worldPosition.relative(leftDirection.getOpposite(), xOffset)) != blockState)
|
||||||
|
break;
|
||||||
|
newXSize++;
|
||||||
|
}
|
||||||
|
for (int yOffset = 0; yOffset < 32; yOffset++) {
|
||||||
|
if (!level.getBlockState(worldPosition.relative(Direction.DOWN, yOffset))
|
||||||
|
.getOptionalValue(FlapDisplayBlock.DOWN)
|
||||||
|
.orElse(false))
|
||||||
|
break;
|
||||||
|
newYSize++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isController == shouldBeController && newXSize == xSize && newYSize == ySize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
isController = shouldBeController;
|
||||||
|
xSize = newXSize;
|
||||||
|
ySize = newYSize;
|
||||||
|
colour = Arrays.copyOf(colour, ySize * 2);
|
||||||
|
manualLines = new boolean[ySize * 2];
|
||||||
|
lines = null;
|
||||||
|
sendData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
isRunning = super.isSpeedRequirementFulfilled();
|
||||||
|
if (!level.isClientSide || !isRunning)
|
||||||
|
return;
|
||||||
|
List<FlapDisplayLayout> lines = getLines();
|
||||||
|
lines.forEach(l -> l.getSections()
|
||||||
|
.forEach(FlapDisplaySection::tick));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSpeedRequirementFulfilled() {
|
||||||
|
return isRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyTextManually(int lineIndex, String rawComponentText) {
|
||||||
|
FlapDisplayLayout layout = getLines().get(lineIndex);
|
||||||
|
if (!layout.isLayout("Default"))
|
||||||
|
layout.loadDefault(getMaxCharCount());
|
||||||
|
List<FlapDisplaySection> sections = layout.getSections();
|
||||||
|
|
||||||
|
if (rawComponentText == null) {
|
||||||
|
manualLines[lineIndex] = false;
|
||||||
|
sections.get(0)
|
||||||
|
.setText(new TextComponent(""));
|
||||||
|
notifyUpdate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonElement json = DynamicComponent.getJsonFromString(rawComponentText);
|
||||||
|
if (json == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
manualLines[lineIndex] = true;
|
||||||
|
Component text = DynamicComponent.parseCustomText(level, worldPosition, json);
|
||||||
|
sections.get(0)
|
||||||
|
.setText(text);
|
||||||
|
notifyUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColour(int lineIndex, DyeColor color) {
|
||||||
|
colour[lineIndex] = color == DyeColor.WHITE ? null : color;
|
||||||
|
notifyUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FlapDisplayLayout> getLines() {
|
||||||
|
if (lines == null)
|
||||||
|
initDefaultSections();
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initDefaultSections() {
|
||||||
|
lines = new ArrayList<>();
|
||||||
|
for (int i = 0; i < ySize * 2; i++)
|
||||||
|
lines.add(new FlapDisplayLayout(getMaxCharCount()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxCharCount() {
|
||||||
|
return getMaxCharCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxCharCount(int gaps) {
|
||||||
|
return (int) ((xSize * 16f - 2f - 4f * gaps) / 3.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void write(CompoundTag tag, boolean clientPacket) {
|
||||||
|
super.write(tag, clientPacket);
|
||||||
|
|
||||||
|
tag.putBoolean("Controller", isController);
|
||||||
|
tag.putInt("XSize", xSize);
|
||||||
|
tag.putInt("YSize", ySize);
|
||||||
|
|
||||||
|
for (int j = 0; j < manualLines.length; j++)
|
||||||
|
if (manualLines[j])
|
||||||
|
NBTHelper.putMarker(tag, "CustomLine" + j);
|
||||||
|
|
||||||
|
for (int j = 0; j < colour.length; j++)
|
||||||
|
if (colour[j] != null)
|
||||||
|
NBTHelper.writeEnum(tag, "Dye" + j, colour[j]);
|
||||||
|
|
||||||
|
List<FlapDisplayLayout> lines = getLines();
|
||||||
|
for (int i = 0; i < lines.size(); i++)
|
||||||
|
tag.put("Display" + i, lines.get(i)
|
||||||
|
.write());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void read(CompoundTag tag, boolean clientPacket) {
|
||||||
|
super.read(tag, clientPacket);
|
||||||
|
boolean wasActive = isController;
|
||||||
|
int prevX = xSize;
|
||||||
|
int prevY = ySize;
|
||||||
|
|
||||||
|
isController = tag.getBoolean("Controller");
|
||||||
|
xSize = tag.getInt("XSize");
|
||||||
|
ySize = tag.getInt("YSize");
|
||||||
|
|
||||||
|
manualLines = new boolean[ySize * 2];
|
||||||
|
for (int i = 0; i < ySize * 2; i++)
|
||||||
|
manualLines[i] = tag.contains("CustomLine" + i);
|
||||||
|
|
||||||
|
colour = new DyeColor[ySize * 2];
|
||||||
|
for (int i = 0; i < ySize * 2; i++)
|
||||||
|
colour[i] = tag.contains("Dye" + i) ? NBTHelper.readEnum(tag, "Dye" + i, DyeColor.class) : null;
|
||||||
|
|
||||||
|
if (clientPacket && wasActive != isController || prevX != xSize || prevY != ySize) {
|
||||||
|
invalidateRenderBoundingBox();
|
||||||
|
lines = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<FlapDisplayLayout> lines = getLines();
|
||||||
|
for (int i = 0; i < lines.size(); i++)
|
||||||
|
lines.get(i)
|
||||||
|
.read(tag.getCompound("Display" + i));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLineIndexAt(double yCoord) {
|
||||||
|
return (int) Mth.clamp(Math.floor(2 * (worldPosition.getY() - yCoord + 1)), 0, ySize * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlapDisplayTileEntity getController() {
|
||||||
|
if (isController)
|
||||||
|
return this;
|
||||||
|
|
||||||
|
BlockState blockState = getBlockState();
|
||||||
|
if (!(blockState.getBlock() instanceof FlapDisplayBlock))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
MutableBlockPos pos = getBlockPos().mutable();
|
||||||
|
Direction side = blockState.getValue(FlapDisplayBlock.HORIZONTAL_FACING)
|
||||||
|
.getClockWise();
|
||||||
|
|
||||||
|
for (int i = 0; i < 64; i++) {
|
||||||
|
BlockState other = level.getBlockState(pos);
|
||||||
|
|
||||||
|
if (other.getOptionalValue(FlapDisplayBlock.UP)
|
||||||
|
.orElse(false)) {
|
||||||
|
pos.move(Direction.UP);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!level.getBlockState(pos.relative(side))
|
||||||
|
.getOptionalValue(FlapDisplayBlock.UP)
|
||||||
|
.orElse(true)) {
|
||||||
|
pos.move(side);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockEntity found = level.getBlockEntity(pos);
|
||||||
|
if (found instanceof FlapDisplayTileEntity flap && flap.isController)
|
||||||
|
return flap;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AABB createRenderBoundingBox() {
|
||||||
|
AABB aabb = new AABB(worldPosition);
|
||||||
|
if (!isController)
|
||||||
|
return aabb;
|
||||||
|
Vec3i normal = getDirection().getClockWise()
|
||||||
|
.getNormal();
|
||||||
|
return aabb.expandTowards(normal.getX() * xSize, -ySize, normal.getZ() * xSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Direction getDirection() {
|
||||||
|
return getBlockState().getOptionalValue(FlapDisplayBlock.HORIZONTAL_FACING)
|
||||||
|
.orElse(Direction.SOUTH)
|
||||||
|
.getOpposite();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.management.display;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
|
||||||
|
public class GlobalTrainDisplayData {
|
||||||
|
|
||||||
|
public static final Map<String, Collection<TrainDeparturePrediction>> statusByDestination = new HashMap<>();
|
||||||
|
public static boolean updateTick = false;
|
||||||
|
|
||||||
|
public static void refresh() {
|
||||||
|
statusByDestination.clear();
|
||||||
|
for (Train train : Create.RAILWAYS.trains.values()) {
|
||||||
|
if (train.runtime.paused || train.runtime.getSchedule() == null)
|
||||||
|
continue;
|
||||||
|
if (train.derailed || train.graph == null)
|
||||||
|
continue;
|
||||||
|
for (TrainDeparturePrediction prediction : train.runtime.submitPredictions())
|
||||||
|
statusByDestination.computeIfAbsent(prediction.destination, $ -> new ArrayList<>())
|
||||||
|
.add(prediction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<TrainDeparturePrediction> prepare(String filter, int maxLines) {
|
||||||
|
return statusByDestination.entrySet()
|
||||||
|
.stream()
|
||||||
|
.filter(e -> e.getKey()
|
||||||
|
.matches(filter.replace("*", ".*")))
|
||||||
|
.flatMap(e -> e.getValue()
|
||||||
|
.stream())
|
||||||
|
.sorted()
|
||||||
|
.limit(maxLines)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TrainDeparturePrediction implements Comparable<TrainDeparturePrediction> {
|
||||||
|
public Train train;
|
||||||
|
public int ticks;
|
||||||
|
public MutableComponent scheduleTitle;
|
||||||
|
public String destination;
|
||||||
|
|
||||||
|
public TrainDeparturePrediction(Train train, int ticks, MutableComponent scheduleTitle, String destination) {
|
||||||
|
this.scheduleTitle = scheduleTitle;
|
||||||
|
this.destination = destination;
|
||||||
|
this.train = train;
|
||||||
|
this.ticks = ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getCompareTicks() {
|
||||||
|
if (ticks == -1)
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
if (ticks < 200)
|
||||||
|
return 0;
|
||||||
|
return ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(TrainDeparturePrediction o) {
|
||||||
|
int compare = Integer.compare(getCompareTicks(), o.getCompareTicks());
|
||||||
|
if (compare == 0)
|
||||||
|
return train.name.getString()
|
||||||
|
.compareTo(o.train.name.getString());
|
||||||
|
return compare;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,18 +1,25 @@
|
||||||
package com.simibubi.create.content.logistics.trains.management.schedule;
|
package com.simibubi.create.content.logistics.trains.management.schedule;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.display.GlobalTrainDisplayData.TrainDeparturePrediction;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
|
||||||
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition;
|
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.schedule.condition.TimedWaitCondition;
|
||||||
import com.simibubi.create.content.logistics.trains.management.schedule.destination.FilteredDestination;
|
import com.simibubi.create.content.logistics.trains.management.schedule.destination.FilteredDestination;
|
||||||
import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleDestination;
|
import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleDestination;
|
||||||
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
import com.simibubi.create.foundation.config.CTrains;
|
||||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
public class ScheduleRuntime {
|
public class ScheduleRuntime {
|
||||||
|
@ -34,6 +41,9 @@ public class ScheduleRuntime {
|
||||||
List<Integer> conditionProgress;
|
List<Integer> conditionProgress;
|
||||||
List<CompoundTag> conditionContext;
|
List<CompoundTag> conditionContext;
|
||||||
|
|
||||||
|
int ticksInTransit;
|
||||||
|
List<Integer> predictionTicks;
|
||||||
|
|
||||||
public ScheduleRuntime(Train train) {
|
public ScheduleRuntime(Train train) {
|
||||||
this.train = train;
|
this.train = train;
|
||||||
reset();
|
reset();
|
||||||
|
@ -44,6 +54,14 @@ public class ScheduleRuntime {
|
||||||
return;
|
return;
|
||||||
state = State.POST_TRANSIT;
|
state = State.POST_TRANSIT;
|
||||||
conditionProgress.clear();
|
conditionProgress.clear();
|
||||||
|
|
||||||
|
if (ticksInTransit > 0) {
|
||||||
|
int current = predictionTicks.get(currentEntry);
|
||||||
|
if (current > 0)
|
||||||
|
ticksInTransit = (current + ticksInTransit) / 2;
|
||||||
|
predictionTicks.set(currentEntry, ticksInTransit);
|
||||||
|
}
|
||||||
|
|
||||||
if (currentEntry >= schedule.entries.size())
|
if (currentEntry >= schedule.entries.size())
|
||||||
return;
|
return;
|
||||||
List<List<ScheduleWaitCondition>> conditions = schedule.entries.get(currentEntry).conditions;
|
List<List<ScheduleWaitCondition>> conditions = schedule.entries.get(currentEntry).conditions;
|
||||||
|
@ -67,8 +85,10 @@ public class ScheduleRuntime {
|
||||||
return;
|
return;
|
||||||
if (train.derailed)
|
if (train.derailed)
|
||||||
return;
|
return;
|
||||||
if (train.navigation.destination != null)
|
if (train.navigation.destination != null) {
|
||||||
|
ticksInTransit++;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (currentEntry >= schedule.entries.size()) {
|
if (currentEntry >= schedule.entries.size()) {
|
||||||
currentEntry = 0;
|
currentEntry = 0;
|
||||||
if (!schedule.cyclic)
|
if (!schedule.cyclic)
|
||||||
|
@ -97,8 +117,10 @@ public class ScheduleRuntime {
|
||||||
destinationReached();
|
destinationReached();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (train.navigation.startNavigation(nextStation, Double.MAX_VALUE, false) != -1)
|
if (train.navigation.startNavigation(nextStation, Double.MAX_VALUE, false) != -1) {
|
||||||
state = State.IN_TRANSIT;
|
state = State.IN_TRANSIT;
|
||||||
|
ticksInTransit = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tickConditions(Level level) {
|
public void tickConditions(Level level) {
|
||||||
|
@ -155,6 +177,8 @@ public class ScheduleRuntime {
|
||||||
paused = false;
|
paused = false;
|
||||||
isAutoSchedule = auto;
|
isAutoSchedule = auto;
|
||||||
train.status.newSchedule();
|
train.status.newSchedule();
|
||||||
|
predictionTicks = new ArrayList<>();
|
||||||
|
schedule.entries.forEach($ -> predictionTicks.add(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Schedule getSchedule() {
|
public Schedule getSchedule() {
|
||||||
|
@ -173,6 +197,121 @@ public class ScheduleRuntime {
|
||||||
state = State.PRE_TRANSIT;
|
state = State.PRE_TRANSIT;
|
||||||
conditionProgress = new ArrayList<>();
|
conditionProgress = new ArrayList<>();
|
||||||
conditionContext = new ArrayList<>();
|
conditionContext = new ArrayList<>();
|
||||||
|
predictionTicks = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<TrainDeparturePrediction> submitPredictions() {
|
||||||
|
Collection<TrainDeparturePrediction> predictions = new ArrayList<>();
|
||||||
|
int entryCount = schedule.entries.size();
|
||||||
|
int accumulatedTime = 0;
|
||||||
|
int current = currentEntry;
|
||||||
|
|
||||||
|
// Current
|
||||||
|
if (state == State.POST_TRANSIT || current >= entryCount) {
|
||||||
|
GlobalStation currentStation = train.getCurrentStation();
|
||||||
|
if (currentStation != null)
|
||||||
|
predictions.add(createPrediction(current, currentStation.name, 0));
|
||||||
|
int departureTime = estimateStayDuration(current);
|
||||||
|
if (departureTime == -1)
|
||||||
|
accumulatedTime = -1;
|
||||||
|
|
||||||
|
} else if (train.navigation.destination != null) {
|
||||||
|
CTrains conf = AllConfigs.SERVER.trains;
|
||||||
|
double speed = (conf.getTopSpeedMPT() + conf.getTurningTopSpeedMPT()) / 2;
|
||||||
|
int timeRemaining = (int) (train.navigation.distanceToDestination / speed) * 2;
|
||||||
|
|
||||||
|
if (predictionTicks.size() > current && train.navigation.distanceStartedAt != 0) {
|
||||||
|
float predictedTime = predictionTicks.get(current);
|
||||||
|
if (predictedTime > 0) {
|
||||||
|
predictedTime *=
|
||||||
|
Mth.clamp(train.navigation.distanceToDestination / train.navigation.distanceStartedAt, 0, 1);
|
||||||
|
timeRemaining = (timeRemaining + (int) predictedTime) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
accumulatedTime += timeRemaining;
|
||||||
|
predictions.add(createPrediction(current, train.navigation.destination.name, accumulatedTime));
|
||||||
|
|
||||||
|
int departureTime = estimateStayDuration(current);
|
||||||
|
if (departureTime != -1)
|
||||||
|
accumulatedTime += departureTime;
|
||||||
|
if (departureTime == -1)
|
||||||
|
accumulatedTime = -1;
|
||||||
|
|
||||||
|
} else
|
||||||
|
predictForEntry(current, accumulatedTime, predictions);
|
||||||
|
|
||||||
|
// Upcoming
|
||||||
|
for (int i = 1; i < entryCount; i++) {
|
||||||
|
int index = (i + current) % entryCount;
|
||||||
|
if (index == 0 && !schedule.cyclic)
|
||||||
|
break;
|
||||||
|
accumulatedTime = predictForEntry(index, accumulatedTime, predictions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return predictions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int predictForEntry(int index, int accumulatedTime, Collection<TrainDeparturePrediction> predictions) {
|
||||||
|
ScheduleEntry entry = schedule.entries.get(index);
|
||||||
|
if (!(entry.destination instanceof FilteredDestination filter))
|
||||||
|
return accumulatedTime;
|
||||||
|
if (predictionTicks.size() <= currentEntry)
|
||||||
|
return accumulatedTime;
|
||||||
|
if (accumulatedTime == -1) {
|
||||||
|
predictions.add(createPrediction(index, filter.nameFilter, accumulatedTime));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int predictedTime = predictionTicks.get(index);
|
||||||
|
int departureTime = estimateStayDuration(index);
|
||||||
|
|
||||||
|
if (predictedTime == -1)
|
||||||
|
accumulatedTime = -1;
|
||||||
|
else {
|
||||||
|
accumulatedTime += predictedTime;
|
||||||
|
if (departureTime != -1)
|
||||||
|
accumulatedTime += departureTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
predictions.add(createPrediction(index, filter.nameFilter, accumulatedTime));
|
||||||
|
|
||||||
|
if (departureTime == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return accumulatedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int estimateStayDuration(int index) {
|
||||||
|
if (index >= schedule.entries.size()) {
|
||||||
|
if (!schedule.cyclic)
|
||||||
|
return 100000;
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduleEntry scheduleEntry = schedule.entries.get(index);
|
||||||
|
for (List<ScheduleWaitCondition> list : scheduleEntry.conditions)
|
||||||
|
for (ScheduleWaitCondition condition : list)
|
||||||
|
if (condition instanceof TimedWaitCondition wait)
|
||||||
|
return wait.timeUnit.ticksPer * wait.value;
|
||||||
|
|
||||||
|
return 5; // TODO properly ask conditions for time prediction
|
||||||
|
}
|
||||||
|
|
||||||
|
private TrainDeparturePrediction createPrediction(int index, String destination, int time) {
|
||||||
|
if (++index >= schedule.entries.size()) {
|
||||||
|
if (!schedule.cyclic)
|
||||||
|
return new TrainDeparturePrediction(train, time, new TextComponent(" "), destination);
|
||||||
|
index %= schedule.entries.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduleEntry scheduleEntry = schedule.entries.get(index);
|
||||||
|
if (!(scheduleEntry.destination instanceof FilteredDestination fd))
|
||||||
|
return new TrainDeparturePrediction(train, time, new TextComponent(" "), destination);
|
||||||
|
|
||||||
|
String station = fd.nameFilter.replaceAll("\\*", "")
|
||||||
|
.trim();
|
||||||
|
return new TrainDeparturePrediction(train, time, new TextComponent(station), destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompoundTag write() {
|
public CompoundTag write() {
|
||||||
|
@ -185,6 +324,7 @@ public class ScheduleRuntime {
|
||||||
NBTHelper.writeEnum(tag, "State", state);
|
NBTHelper.writeEnum(tag, "State", state);
|
||||||
tag.putIntArray("ConditionProgress", conditionProgress);
|
tag.putIntArray("ConditionProgress", conditionProgress);
|
||||||
tag.put("ConditionContext", NBTHelper.writeCompoundList(conditionContext, CompoundTag::copy));
|
tag.put("ConditionContext", NBTHelper.writeCompoundList(conditionContext, CompoundTag::copy));
|
||||||
|
tag.putIntArray("TransitTimes", predictionTicks);
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +339,14 @@ public class ScheduleRuntime {
|
||||||
for (int i : tag.getIntArray("ConditionProgress"))
|
for (int i : tag.getIntArray("ConditionProgress"))
|
||||||
conditionProgress.add(i);
|
conditionProgress.add(i);
|
||||||
NBTHelper.iterateCompoundList(tag.getList("ConditionContext", Tag.TAG_COMPOUND), conditionContext::add);
|
NBTHelper.iterateCompoundList(tag.getList("ConditionContext", Tag.TAG_COMPOUND), conditionContext::add);
|
||||||
|
|
||||||
|
int[] readTransits = tag.getIntArray("TransitTimes");
|
||||||
|
if (schedule != null) {
|
||||||
|
schedule.entries.forEach($ -> predictionTicks.add(-1));
|
||||||
|
if (readTransits.length == schedule.entries.size())
|
||||||
|
for (int i = 0; i < readTransits.length; i++)
|
||||||
|
predictionTicks.set(i, readTransits[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,8 @@ public class ConnectedPillarBlock extends LayeredBlock {
|
||||||
public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, Random pRandom) {
|
public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, Random pRandom) {
|
||||||
if (pState.getBlock() != this)
|
if (pState.getBlock() != this)
|
||||||
return;
|
return;
|
||||||
BlockPos belowPos = pPos.relative(Direction.fromAxisAndDirection(pState.getValue(AXIS), AxisDirection.NEGATIVE));
|
BlockPos belowPos =
|
||||||
|
pPos.relative(Direction.fromAxisAndDirection(pState.getValue(AXIS), AxisDirection.NEGATIVE));
|
||||||
BlockState belowState = pLevel.getBlockState(belowPos);
|
BlockState belowState = pLevel.getBlockState(belowPos);
|
||||||
if (!canConnect(pState, belowState))
|
if (!canConnect(pState, belowState))
|
||||||
pLevel.setBlock(pPos, updateColumn(pLevel, pPos, pState, true), 3);
|
pLevel.setBlock(pPos, updateColumn(pLevel, pPos, pState, true), 3);
|
||||||
|
|
|
@ -30,6 +30,7 @@ import com.simibubi.create.content.curiosities.tools.BlueprintOverlayRenderer;
|
||||||
import com.simibubi.create.content.curiosities.tools.ExtendoGripRenderHandler;
|
import com.simibubi.create.content.curiosities.tools.ExtendoGripRenderHandler;
|
||||||
import com.simibubi.create.content.curiosities.zapper.ZapperItem;
|
import com.simibubi.create.content.curiosities.zapper.ZapperItem;
|
||||||
import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperRenderHandler;
|
import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperRenderHandler;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererBlockItem;
|
||||||
import com.simibubi.create.content.logistics.block.depot.EjectorTargetHandler;
|
import com.simibubi.create.content.logistics.block.depot.EjectorTargetHandler;
|
||||||
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPointHandler;
|
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPointHandler;
|
||||||
import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler;
|
import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler;
|
||||||
|
@ -156,6 +157,7 @@ public class ClientEvents {
|
||||||
TrackPlacement.clientTick();
|
TrackPlacement.clientTick();
|
||||||
TrackRemoval.clientTick();
|
TrackRemoval.clientTick();
|
||||||
TrainRelocator.clientTick();
|
TrainRelocator.clientTick();
|
||||||
|
DataGathererBlockItem.clientTick();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
|
|
|
@ -2,11 +2,13 @@ package com.simibubi.create.foundation.config;
|
||||||
|
|
||||||
public class CLogistics extends ConfigBase {
|
public class CLogistics extends ConfigBase {
|
||||||
|
|
||||||
public final ConfigInt defaultExtractionLimit = i(64, 1, 64, "defaultExtractionLimit", Comments.defaultExtractionLimit);
|
public final ConfigInt defaultExtractionLimit =
|
||||||
|
i(64, 1, 64, "defaultExtractionLimit", Comments.defaultExtractionLimit);
|
||||||
public final ConfigInt defaultExtractionTimer = i(8, 1, "defaultExtractionTimer", Comments.defaultExtractionTimer);
|
public final ConfigInt defaultExtractionTimer = i(8, 1, "defaultExtractionTimer", Comments.defaultExtractionTimer);
|
||||||
public final ConfigInt psiTimeout = i(20, 1, "psiTimeout", Comments.psiTimeout);
|
public final ConfigInt psiTimeout = i(20, 1, "psiTimeout", Comments.psiTimeout);
|
||||||
public final ConfigInt mechanicalArmRange = i(5, 1, "mechanicalArmRange", Comments.mechanicalArmRange);
|
public final ConfigInt mechanicalArmRange = i(5, 1, "mechanicalArmRange", Comments.mechanicalArmRange);
|
||||||
public final ConfigInt linkRange = i(128, 1, "linkRange", Comments.linkRange);
|
public final ConfigInt linkRange = i(128, 1, "linkRange", Comments.linkRange);
|
||||||
|
public final ConfigInt dataGathererRange = i(32, 1, "dataGathererRange", Comments.dataGathererRange);
|
||||||
public final ConfigInt vaultCapacity = i(20, 1, "vaultCapacity", Comments.vaultCapacity);
|
public final ConfigInt vaultCapacity = i(20, 1, "vaultCapacity", Comments.vaultCapacity);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -20,6 +22,8 @@ public class CLogistics extends ConfigBase {
|
||||||
static String defaultExtractionTimer =
|
static String defaultExtractionTimer =
|
||||||
"The amount of ticks a funnel waits between item transferrals, when it is not re-activated by redstone.";
|
"The amount of ticks a funnel waits between item transferrals, when it is not re-activated by redstone.";
|
||||||
static String linkRange = "Maximum possible range in blocks of redstone link connections.";
|
static String linkRange = "Maximum possible range in blocks of redstone link connections.";
|
||||||
|
static String dataGathererRange =
|
||||||
|
"Maximum possible distance in blocks between data gatherers and their target.";
|
||||||
static String psiTimeout =
|
static String psiTimeout =
|
||||||
"The amount of ticks a portable storage interface waits for transfers until letting contraptions move along.";
|
"The amount of ticks a portable storage interface waits for transfers until letting contraptions move along.";
|
||||||
static String mechanicalArmRange = "Maximum distance in blocks a Mechanical Arm can reach across.";
|
static String mechanicalArmRange = "Maximum distance in blocks a Mechanical Arm can reach across.";
|
||||||
|
|
|
@ -81,6 +81,11 @@ public enum AllGuiTextures implements ScreenElement {
|
||||||
PROJECTOR_END("projector", 0, 58, 162, 22),
|
PROJECTOR_END("projector", 0, 58, 162, 22),
|
||||||
PROJECTOR_EMPTY("projector", 0, 80, 162, 22),
|
PROJECTOR_EMPTY("projector", 0, 80, 162, 22),
|
||||||
|
|
||||||
|
DATA_GATHERER("data_gatherer", 235, 162),
|
||||||
|
DATA_AREA_START("data_gatherer", 0, 163, 2, 18),
|
||||||
|
DATA_AREA("data_gatherer", 3, 163, 1, 18),
|
||||||
|
DATA_AREA_END("data_gatherer", 5, 163, 2, 18),
|
||||||
|
|
||||||
SCHEDULE("schedule", 256, 226),
|
SCHEDULE("schedule", 256, 226),
|
||||||
SCHEDULE_CARD_DARK("schedule", 5, 233, 1, 1),
|
SCHEDULE_CARD_DARK("schedule", 5, 233, 1, 1),
|
||||||
SCHEDULE_CARD_MEDIUM("schedule", 6, 233, 1, 1),
|
SCHEDULE_CARD_MEDIUM("schedule", 6, 233, 1, 1),
|
||||||
|
|
|
@ -16,6 +16,8 @@ import net.minecraft.network.chat.TextComponent;
|
||||||
|
|
||||||
public abstract class AbstractSimiWidget extends AbstractWidget implements TickableGuiEventListener {
|
public abstract class AbstractSimiWidget extends AbstractWidget implements TickableGuiEventListener {
|
||||||
|
|
||||||
|
public static final int HEADER_RGB = 0x5391E1;
|
||||||
|
|
||||||
protected float z;
|
protected float z;
|
||||||
protected boolean wasHovered = false;
|
protected boolean wasHovered = false;
|
||||||
protected List<Component> toolTip = new LinkedList<>();
|
protected List<Component> toolTip = new LinkedList<>();
|
||||||
|
|
|
@ -5,7 +5,6 @@ import javax.annotation.Nonnull;
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
||||||
import com.simibubi.create.foundation.gui.AllIcons;
|
|
||||||
import com.simibubi.create.foundation.gui.element.ScreenElement;
|
import com.simibubi.create.foundation.gui.element.ScreenElement;
|
||||||
|
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
|
@ -20,6 +20,7 @@ public class ScrollInput extends AbstractSimiWidget {
|
||||||
protected final Component scrollToModify = Lang.translate("gui.scrollInput.scrollToModify");
|
protected final Component scrollToModify = Lang.translate("gui.scrollInput.scrollToModify");
|
||||||
protected final Component shiftScrollsFaster = Lang.translate("gui.scrollInput.shiftScrollsFaster");
|
protected final Component shiftScrollsFaster = Lang.translate("gui.scrollInput.shiftScrollsFaster");
|
||||||
protected Label displayLabel;
|
protected Label displayLabel;
|
||||||
|
protected boolean inverted;
|
||||||
|
|
||||||
protected int min, max;
|
protected int min, max;
|
||||||
protected int shiftStep;
|
protected int shiftStep;
|
||||||
|
@ -38,6 +39,11 @@ public class ScrollInput extends AbstractSimiWidget {
|
||||||
return c -> c.shift ? shiftStep : 1;
|
return c -> c.shift ? shiftStep : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ScrollInput inverted() {
|
||||||
|
inverted = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public ScrollInput withRange(int min, int max) {
|
public ScrollInput withRange(int min, int max) {
|
||||||
this.min = min;
|
this.min = min;
|
||||||
this.max = max;
|
this.max = max;
|
||||||
|
@ -91,6 +97,9 @@ public class ScrollInput extends AbstractSimiWidget {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
|
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
|
||||||
|
if (inverted)
|
||||||
|
delta *= -1;
|
||||||
|
|
||||||
StepContext context = new StepContext();
|
StepContext context = new StepContext();
|
||||||
context.control = AllKeys.ctrlDown();
|
context.control = AllKeys.ctrlDown();
|
||||||
context.shift = AllKeys.shiftDown();
|
context.shift = AllKeys.shiftDown();
|
||||||
|
@ -134,7 +143,7 @@ public class ScrollInput extends AbstractSimiWidget {
|
||||||
|
|
||||||
protected void updateTooltip() {
|
protected void updateTooltip() {
|
||||||
toolTip.clear();
|
toolTip.clear();
|
||||||
toolTip.add(title.plainCopy().withStyle(ChatFormatting.BLUE));
|
toolTip.add(title.plainCopy().withStyle(s -> s.withColor(HEADER_RGB)));
|
||||||
toolTip.add(scrollToModify.plainCopy().withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY));
|
toolTip.add(scrollToModify.plainCopy().withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY));
|
||||||
toolTip.add(shiftScrollsFaster.plainCopy().withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY));
|
toolTip.add(shiftScrollsFaster.plainCopy().withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY));
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ public class SelectionScrollInput extends ScrollInput {
|
||||||
public SelectionScrollInput(int xIn, int yIn, int widthIn, int heightIn) {
|
public SelectionScrollInput(int xIn, int yIn, int widthIn, int heightIn) {
|
||||||
super(xIn, yIn, widthIn, heightIn);
|
super(xIn, yIn, widthIn, heightIn);
|
||||||
options = new ArrayList<>();
|
options = new ArrayList<>();
|
||||||
|
inverted();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScrollInput forOptions(List<? extends Component> options) {
|
public ScrollInput forOptions(List<? extends Component> options) {
|
||||||
|
@ -32,15 +33,11 @@ public class SelectionScrollInput extends ScrollInput {
|
||||||
displayLabel.text = options.get(state);
|
displayLabel.text = options.get(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
|
|
||||||
return super.mouseScrolled(mouseX, mouseY, -delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateTooltip() {
|
protected void updateTooltip() {
|
||||||
toolTip.clear();
|
toolTip.clear();
|
||||||
toolTip.add(title.plainCopy().withStyle(ChatFormatting.BLUE));
|
toolTip.add(title.plainCopy()
|
||||||
|
.withStyle(s -> s.withColor(HEADER_RGB)));
|
||||||
int min = Math.min(this.max - 16, state - 7);
|
int min = Math.min(this.max - 16, state - 7);
|
||||||
int max = Math.max(this.min + 16, state + 8);
|
int max = Math.max(this.min + 16, state + 8);
|
||||||
min = Math.max(min, this.min);
|
min = Math.max(min, this.min);
|
||||||
|
@ -53,14 +50,21 @@ public class SelectionScrollInput extends ScrollInput {
|
||||||
max++;
|
max++;
|
||||||
for (int i = min; i < max; i++) {
|
for (int i = min; i < max; i++) {
|
||||||
if (i == state)
|
if (i == state)
|
||||||
toolTip.add(TextComponent.EMPTY.plainCopy().append("-> ").append(options.get(i)).withStyle(ChatFormatting.WHITE));
|
toolTip.add(TextComponent.EMPTY.plainCopy()
|
||||||
|
.append("-> ")
|
||||||
|
.append(options.get(i))
|
||||||
|
.withStyle(ChatFormatting.WHITE));
|
||||||
else
|
else
|
||||||
toolTip.add(TextComponent.EMPTY.plainCopy().append("> ").append(options.get(i)).withStyle(ChatFormatting.GRAY));
|
toolTip.add(TextComponent.EMPTY.plainCopy()
|
||||||
|
.append("> ")
|
||||||
|
.append(options.get(i))
|
||||||
|
.withStyle(ChatFormatting.GRAY));
|
||||||
}
|
}
|
||||||
if (max < this.max)
|
if (max < this.max)
|
||||||
toolTip.add(new TextComponent("> ...").withStyle(ChatFormatting.GRAY));
|
toolTip.add(new TextComponent("> ...").withStyle(ChatFormatting.GRAY));
|
||||||
|
|
||||||
toolTip.add(scrollToSelect.plainCopy().withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC));
|
toolTip.add(scrollToSelect.plainCopy()
|
||||||
|
.withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.simibubi.create.foundation.gui.widget;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
public class TooltipArea extends AbstractSimiWidget {
|
||||||
|
|
||||||
|
public TooltipArea(int x, int y, int width, int height) {
|
||||||
|
super(x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderButton(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
if (visible)
|
||||||
|
isHovered = mouseX >= x && mouseY >= y && mouseX < x + width && mouseY < y + height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TooltipArea withTooltip(List<Component> tooltip) {
|
||||||
|
this.toolTip = tooltip;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
package com.simibubi.create.foundation.item;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
||||||
|
import com.simibubi.create.foundation.utility.IntAttached;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
import net.minecraftforge.items.ItemHandlerHelper;
|
||||||
|
|
||||||
|
public class CountedItemStackList {
|
||||||
|
|
||||||
|
Map<Item, Set<ItemStackEntry>> items = new HashMap<>();
|
||||||
|
|
||||||
|
public CountedItemStackList(IItemHandler inventory, FilteringBehaviour filteringBehaviour) {
|
||||||
|
for (int slot = 0; slot < inventory.getSlots(); slot++) {
|
||||||
|
ItemStack extractItem = inventory.extractItem(slot, inventory.getSlotLimit(slot), true);
|
||||||
|
if (filteringBehaviour.test(extractItem))
|
||||||
|
add(extractItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<IntAttached<MutableComponent>> getTopNames(int limit) {
|
||||||
|
return items.values()
|
||||||
|
.stream()
|
||||||
|
.flatMap(s -> s.stream())
|
||||||
|
.sorted(IntAttached.comparator())
|
||||||
|
.limit(limit)
|
||||||
|
.map(entry -> IntAttached.with(entry.count(), entry.stack()
|
||||||
|
.getHoverName()
|
||||||
|
.copy()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(ItemStack stack) {
|
||||||
|
add(stack, stack.getCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(ItemStack stack, int amount) {
|
||||||
|
if (stack.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Set<ItemStackEntry> stackSet = getOrCreateItemSet(stack);
|
||||||
|
for (ItemStackEntry entry : stackSet) {
|
||||||
|
if (!entry.matches(stack))
|
||||||
|
continue;
|
||||||
|
entry.grow(amount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stackSet.add(new ItemStackEntry(stack, amount));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<ItemStackEntry> getOrCreateItemSet(ItemStack stack) {
|
||||||
|
if (!items.containsKey(stack.getItem()))
|
||||||
|
items.put(stack.getItem(), new HashSet<>());
|
||||||
|
return getItemSet(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<ItemStackEntry> getItemSet(ItemStack stack) {
|
||||||
|
return items.get(stack.getItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ItemStackEntry extends IntAttached<ItemStack> {
|
||||||
|
|
||||||
|
public ItemStackEntry(ItemStack stack) {
|
||||||
|
this(stack, stack.getCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStackEntry(ItemStack stack, int amount) {
|
||||||
|
super(amount, stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(ItemStack other) {
|
||||||
|
return ItemHandlerHelper.canItemStacksStack(other, stack());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack stack() {
|
||||||
|
return getSecond();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void grow(int amount) {
|
||||||
|
setFirst(getFirst() + amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int count() {
|
||||||
|
return getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ import com.simibubi.create.content.curiosities.weapons.PotatoCannonPacket;
|
||||||
import com.simibubi.create.content.curiosities.weapons.PotatoProjectileTypeManager;
|
import com.simibubi.create.content.curiosities.weapons.PotatoProjectileTypeManager;
|
||||||
import com.simibubi.create.content.curiosities.zapper.ZapperBeamPacket;
|
import com.simibubi.create.content.curiosities.zapper.ZapperBeamPacket;
|
||||||
import com.simibubi.create.content.curiosities.zapper.terrainzapper.ConfigureWorldshaperPacket;
|
import com.simibubi.create.content.curiosities.zapper.terrainzapper.ConfigureWorldshaperPacket;
|
||||||
|
import com.simibubi.create.content.logistics.block.data.DataGathererConfigurationPacket;
|
||||||
import com.simibubi.create.content.logistics.block.depot.EjectorElytraPacket;
|
import com.simibubi.create.content.logistics.block.depot.EjectorElytraPacket;
|
||||||
import com.simibubi.create.content.logistics.block.depot.EjectorPlacementPacket;
|
import com.simibubi.create.content.logistics.block.depot.EjectorPlacementPacket;
|
||||||
import com.simibubi.create.content.logistics.block.depot.EjectorTriggerPacket;
|
import com.simibubi.create.content.logistics.block.depot.EjectorTriggerPacket;
|
||||||
|
@ -120,6 +121,7 @@ public enum AllPackets {
|
||||||
RELOCATE_TRAIN(TrainRelocationPacket.class, TrainRelocationPacket::new, PLAY_TO_SERVER),
|
RELOCATE_TRAIN(TrainRelocationPacket.class, TrainRelocationPacket::new, PLAY_TO_SERVER),
|
||||||
CONTROLS_INPUT(ControlsInputPacket.class, ControlsInputPacket::new, PLAY_TO_SERVER),
|
CONTROLS_INPUT(ControlsInputPacket.class, ControlsInputPacket::new, PLAY_TO_SERVER),
|
||||||
REMOVE_TRACKS(TrackRemovalPacket.class, TrackRemovalPacket::new, PLAY_TO_SERVER),
|
REMOVE_TRACKS(TrackRemovalPacket.class, TrackRemovalPacket::new, PLAY_TO_SERVER),
|
||||||
|
CONFIGURE_DATA_GATHERER(DataGathererConfigurationPacket.class, DataGathererConfigurationPacket::new, PLAY_TO_SERVER),
|
||||||
|
|
||||||
// Server to Client
|
// Server to Client
|
||||||
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
|
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
|
||||||
|
|
|
@ -7,7 +7,7 @@ import java.util.List;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllItems;
|
import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity;
|
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity.Mode;
|
import com.simibubi.create.content.contraptions.components.press.PressingBehaviour.Mode;
|
||||||
import com.simibubi.create.content.contraptions.fluids.actors.SpoutTileEntity;
|
import com.simibubi.create.content.contraptions.fluids.actors.SpoutTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
|
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
|
import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
|
||||||
|
@ -79,7 +79,8 @@ public class BeltScenes {
|
||||||
scene.idle(7);
|
scene.idle(7);
|
||||||
|
|
||||||
scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, frontEnd, shaftBB.move(frontEnd), 17);
|
scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, frontEnd, shaftBB.move(frontEnd), 17);
|
||||||
scene.overlay.chaseBoundingBoxOutline(PonderPalette.BLACK, backEndCenter, connectBB.expandTowards(-4, 0, 0), 20);
|
scene.overlay.chaseBoundingBoxOutline(PonderPalette.BLACK, backEndCenter, connectBB.expandTowards(-4, 0, 0),
|
||||||
|
20);
|
||||||
scene.idle(20);
|
scene.idle(20);
|
||||||
|
|
||||||
scene.world.moveSection(shafts, util.vector.of(0, -2, 0), 0);
|
scene.world.moveSection(shafts, util.vector.of(0, -2, 0), 0);
|
||||||
|
@ -534,7 +535,8 @@ public class BeltScenes {
|
||||||
scene.world.removeItemsFromBelt(depotPos);
|
scene.world.removeItemsFromBelt(depotPos);
|
||||||
scene.world.hideSection(util.select.position(depotPos.above(2)), Direction.SOUTH);
|
scene.world.hideSection(util.select.position(depotPos.above(2)), Direction.SOUTH);
|
||||||
scene.idle(20);
|
scene.idle(20);
|
||||||
ElementLink<WorldSectionElement> spout = scene.world.showIndependentSection(util.select.position(depotPos.above(2)
|
ElementLink<WorldSectionElement> spout =
|
||||||
|
scene.world.showIndependentSection(util.select.position(depotPos.above(2)
|
||||||
.west()), Direction.SOUTH);
|
.west()), Direction.SOUTH);
|
||||||
scene.world.moveSection(spout, util.vector.of(1, 0, 0), 0);
|
scene.world.moveSection(spout, util.vector.of(1, 0, 0), 0);
|
||||||
|
|
||||||
|
@ -546,10 +548,11 @@ public class BeltScenes {
|
||||||
scene.idle(10);
|
scene.idle(10);
|
||||||
|
|
||||||
Class<MechanicalPressTileEntity> type = MechanicalPressTileEntity.class;
|
Class<MechanicalPressTileEntity> type = MechanicalPressTileEntity.class;
|
||||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BELT));
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
|
.start(Mode.BELT));
|
||||||
scene.idle(15);
|
scene.idle(15);
|
||||||
scene.world.modifyTileEntity(pressPos, type,
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
||||||
scene.world.removeItemsFromBelt(depotPos);
|
scene.world.removeItemsFromBelt(depotPos);
|
||||||
ItemStack sheet = AllItems.COPPER_SHEET.asStack();
|
ItemStack sheet = AllItems.COPPER_SHEET.asStack();
|
||||||
scene.world.createItemOnBeltLike(depotPos, Direction.UP, sheet);
|
scene.world.createItemOnBeltLike(depotPos, Direction.UP, sheet);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import com.simibubi.create.content.contraptions.components.deployer.DeployerTile
|
||||||
import com.simibubi.create.content.contraptions.components.millstone.MillstoneTileEntity;
|
import com.simibubi.create.content.contraptions.components.millstone.MillstoneTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity;
|
import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity;
|
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity.Mode;
|
import com.simibubi.create.content.contraptions.components.press.PressingBehaviour.Mode;
|
||||||
import com.simibubi.create.content.contraptions.processing.BasinBlock;
|
import com.simibubi.create.content.contraptions.processing.BasinBlock;
|
||||||
import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
|
import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
|
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
|
||||||
|
@ -314,10 +314,11 @@ public class ProcessingScenes {
|
||||||
scene.idle(10);
|
scene.idle(10);
|
||||||
|
|
||||||
Class<MechanicalPressTileEntity> type = MechanicalPressTileEntity.class;
|
Class<MechanicalPressTileEntity> type = MechanicalPressTileEntity.class;
|
||||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BELT));
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
|
.start(Mode.BELT));
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
scene.world.modifyTileEntity(pressPos, type,
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
||||||
scene.world.removeItemsFromBelt(depotPos);
|
scene.world.removeItemsFromBelt(depotPos);
|
||||||
ItemStack sheet = AllItems.COPPER_SHEET.asStack();
|
ItemStack sheet = AllItems.COPPER_SHEET.asStack();
|
||||||
scene.world.createItemOnBeltLike(depotPos, Direction.UP, sheet);
|
scene.world.createItemOnBeltLike(depotPos, Direction.UP, sheet);
|
||||||
|
@ -344,7 +345,8 @@ public class ProcessingScenes {
|
||||||
ElementLink<BeltItemElement> ingot2 = scene.world.createItemOnBelt(beltPos, Direction.SOUTH, copper);
|
ElementLink<BeltItemElement> ingot2 = scene.world.createItemOnBelt(beltPos, Direction.SOUTH, copper);
|
||||||
scene.idle(15);
|
scene.idle(15);
|
||||||
scene.world.stallBeltItem(ingot, true);
|
scene.world.stallBeltItem(ingot, true);
|
||||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BELT));
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
|
.start(Mode.BELT));
|
||||||
|
|
||||||
scene.overlay.showText(50)
|
scene.overlay.showText(50)
|
||||||
.pointAt(pressSide)
|
.pointAt(pressSide)
|
||||||
|
@ -353,8 +355,8 @@ public class ProcessingScenes {
|
||||||
.text("The Press will hold and process them automatically");
|
.text("The Press will hold and process them automatically");
|
||||||
|
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
scene.world.modifyTileEntity(pressPos, type,
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
||||||
scene.world.removeItemsFromBelt(pressPos.below(2));
|
scene.world.removeItemsFromBelt(pressPos.below(2));
|
||||||
ingot = scene.world.createItemOnBelt(pressPos.below(2), Direction.UP, sheet);
|
ingot = scene.world.createItemOnBelt(pressPos.below(2), Direction.UP, sheet);
|
||||||
scene.world.stallBeltItem(ingot, true);
|
scene.world.stallBeltItem(ingot, true);
|
||||||
|
@ -362,10 +364,11 @@ public class ProcessingScenes {
|
||||||
scene.world.stallBeltItem(ingot, false);
|
scene.world.stallBeltItem(ingot, false);
|
||||||
scene.idle(15);
|
scene.idle(15);
|
||||||
scene.world.stallBeltItem(ingot2, true);
|
scene.world.stallBeltItem(ingot2, true);
|
||||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BELT));
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
|
.start(Mode.BELT));
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
scene.world.modifyTileEntity(pressPos, type,
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
||||||
scene.world.removeItemsFromBelt(pressPos.below(2));
|
scene.world.removeItemsFromBelt(pressPos.below(2));
|
||||||
ingot2 = scene.world.createItemOnBelt(pressPos.below(2), Direction.UP, sheet);
|
ingot2 = scene.world.createItemOnBelt(pressPos.below(2), Direction.UP, sheet);
|
||||||
scene.world.stallBeltItem(ingot2, true);
|
scene.world.stallBeltItem(ingot2, true);
|
||||||
|
@ -492,10 +495,11 @@ public class ProcessingScenes {
|
||||||
30);
|
30);
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
Class<MechanicalPressTileEntity> type = MechanicalPressTileEntity.class;
|
Class<MechanicalPressTileEntity> type = MechanicalPressTileEntity.class;
|
||||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BASIN));
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
|
.start(Mode.BASIN));
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
scene.world.modifyTileEntity(pressPos, type,
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basin), copper));
|
.makeCompactingParticleEffect(util.vector.centerOf(basin), copper));
|
||||||
scene.world.modifyTileNBT(util.select.position(basin), BasinTileEntity.class, nbt -> {
|
scene.world.modifyTileNBT(util.select.position(basin), BasinTileEntity.class, nbt -> {
|
||||||
nbt.put("VisualizedItems",
|
nbt.put("VisualizedItems",
|
||||||
NBTHelper.writeCompoundList(ImmutableList.of(IntAttached.with(1, copperBlock)), ia -> ia.getValue()
|
NBTHelper.writeCompoundList(ImmutableList.of(IntAttached.with(1, copperBlock)), ia -> ia.getValue()
|
||||||
|
@ -517,10 +521,11 @@ public class ProcessingScenes {
|
||||||
|
|
||||||
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basin), Pointing.DOWN).withItem(log), 30);
|
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basin), Pointing.DOWN).withItem(log), 30);
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BASIN));
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
|
.start(Mode.BASIN));
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
scene.world.modifyTileEntity(pressPos, type,
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basin), log));
|
.makeCompactingParticleEffect(util.vector.centerOf(basin), log));
|
||||||
scene.world.modifyTileNBT(util.select.position(basin), BasinTileEntity.class, nbt -> {
|
scene.world.modifyTileNBT(util.select.position(basin), BasinTileEntity.class, nbt -> {
|
||||||
nbt.put("VisualizedItems",
|
nbt.put("VisualizedItems",
|
||||||
NBTHelper.writeCompoundList(ImmutableList.of(IntAttached.with(1, bark)), ia -> ia.getValue()
|
NBTHelper.writeCompoundList(ImmutableList.of(IntAttached.with(1, bark)), ia -> ia.getValue()
|
||||||
|
@ -632,8 +637,8 @@ public class ProcessingScenes {
|
||||||
.withItem(new ItemStack(Items.SOUL_SAND)),
|
.withItem(new ItemStack(Items.SOUL_SAND)),
|
||||||
40);
|
40);
|
||||||
scene.idle(7);
|
scene.idle(7);
|
||||||
scene.world.modifyBlock(util.grid.at(3, 1, 2), s -> s.setValue(LitBlazeBurnerBlock.FLAME_TYPE, LitBlazeBurnerBlock.FlameType.SOUL),
|
scene.world.modifyBlock(util.grid.at(3, 1, 2),
|
||||||
false);
|
s -> s.setValue(LitBlazeBurnerBlock.FLAME_TYPE, LitBlazeBurnerBlock.FlameType.SOUL), false);
|
||||||
scene.overlay.showText(60)
|
scene.overlay.showText(60)
|
||||||
.text("The flame can be transformed using a soul-infused item")
|
.text("The flame can be transformed using a soul-infused item")
|
||||||
.pointAt(util.vector.blockSurface(center.east()
|
.pointAt(util.vector.blockSurface(center.east()
|
||||||
|
@ -821,10 +826,11 @@ public class ProcessingScenes {
|
||||||
scene.idle(10);
|
scene.idle(10);
|
||||||
|
|
||||||
Class<MechanicalPressTileEntity> type = MechanicalPressTileEntity.class;
|
Class<MechanicalPressTileEntity> type = MechanicalPressTileEntity.class;
|
||||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BASIN));
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
|
.start(Mode.BASIN));
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
scene.world.modifyTileEntity(pressPos, type,
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basinPos), stack));
|
.makeCompactingParticleEffect(util.vector.centerOf(basinPos), stack));
|
||||||
scene.world.modifyTileNBT(util.select.position(basinPos), BasinTileEntity.class, nbt -> {
|
scene.world.modifyTileNBT(util.select.position(basinPos), BasinTileEntity.class, nbt -> {
|
||||||
nbt.put("VisualizedItems",
|
nbt.put("VisualizedItems",
|
||||||
NBTHelper.writeCompoundList(ImmutableList.of(IntAttached.with(1, new ItemStack(Blocks.BRICKS))),
|
NBTHelper.writeCompoundList(ImmutableList.of(IntAttached.with(1, new ItemStack(Blocks.BRICKS))),
|
||||||
|
@ -859,20 +865,22 @@ public class ProcessingScenes {
|
||||||
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basinPos), Pointing.RIGHT).withItem(nugget),
|
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basinPos), Pointing.RIGHT).withItem(nugget),
|
||||||
30);
|
30);
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BASIN));
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
|
.start(Mode.BASIN));
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
scene.world.modifyTileEntity(pressPos, type,
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basinPos), nugget));
|
.makeCompactingParticleEffect(util.vector.centerOf(basinPos), nugget));
|
||||||
|
|
||||||
ItemStack ingot = new ItemStack(Items.COPPER_INGOT);
|
ItemStack ingot = new ItemStack(Items.COPPER_INGOT);
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basinPos), Pointing.RIGHT).withItem(ingot),
|
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basinPos), Pointing.RIGHT).withItem(ingot),
|
||||||
30);
|
30);
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BASIN));
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
|
.start(Mode.BASIN));
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
scene.world.modifyTileEntity(pressPos, type,
|
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||||
pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basinPos), ingot));
|
.makeCompactingParticleEffect(util.vector.centerOf(basinPos), ingot));
|
||||||
|
|
||||||
ItemStack block = new ItemStack(Items.COPPER_BLOCK);
|
ItemStack block = new ItemStack(Items.COPPER_BLOCK);
|
||||||
scene.idle(30);
|
scene.idle(30);
|
||||||
|
|
|
@ -28,8 +28,8 @@ public abstract class SmartTileEntity extends CachedRenderBBTileEntity implement
|
||||||
private final Map<BehaviourType<?>, TileEntityBehaviour> behaviours = new HashMap<>();
|
private final Map<BehaviourType<?>, TileEntityBehaviour> behaviours = new HashMap<>();
|
||||||
private boolean initialized = false;
|
private boolean initialized = false;
|
||||||
private boolean firstNbtRead = true;
|
private boolean firstNbtRead = true;
|
||||||
private int lazyTickRate;
|
protected int lazyTickRate;
|
||||||
private int lazyTickCounter;
|
protected int lazyTickCounter;
|
||||||
|
|
||||||
// Used for simulating this TE in a client-only setting
|
// Used for simulating this TE in a client-only setting
|
||||||
private boolean virtualMode;
|
private boolean virtualMode;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue