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
|
||||
1726b1b9e04a0634e7e1fdcf1cf4cc898efc5c2f assets/create/blockstates/dark_oak_window.json
|
||||
50d4627d8e8b5adade12de764ab528ddacfa9ea5 assets/create/blockstates/dark_oak_window_pane.json
|
||||
990cdcce80e6e4ea3055c2572c5fafe3ee795b0f assets/create/blockstates/data_gatherer.json
|
||||
de0116bf32a26d697a3b999044d6fb0b1b98320e assets/create/blockstates/deepslate_pillar.json
|
||||
c3317a94c509d4bb2fe9c6f64a072334421998d3 assets/create/blockstates/deepslate_zinc_ore.json
|
||||
ac85f55d82d96fc15750e6b954297cfd1e00d04d assets/create/blockstates/deployer.json
|
||||
3660f44309279a0347347f23ce7444c6ed98cafd assets/create/blockstates/depot.json
|
||||
0270b68550e19720d0cdc9e44f63618908628192 assets/create/blockstates/diorite_pillar.json
|
||||
62cc543abb242836570d07d619fcdb4c79c75db4 assets/create/blockstates/display_board.json
|
||||
30b3422bfee9878c92521429b2536d3e0313cedb assets/create/blockstates/dripstone_pillar.json
|
||||
35fc68eb1d031d28ad09b7b603e64ae459634179 assets/create/blockstates/encased_chain_drive.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
|
||||
e8b0a401c10d1ba67ed71ba31bd5f9bc28571b65 assets/create/blockstates/powered_toggle_latch.json
|
||||
3a739f9d4276828d83f2d2750bf3227c87bcd438 assets/create/blockstates/pulley_magnet.json
|
||||
dee3cdef860bb92d439ecaaec4300b42208b025c assets/create/blockstates/pulse_extender.json
|
||||
638eb675fe3c464a0ab265c37f7d37fdf6440323 assets/create/blockstates/pulse_repeater.json
|
||||
2a825cb867b9738b34d80b4151c55f76eb95e2ef assets/create/blockstates/pulse_extender.json
|
||||
9035c427fdb0035312f617196e65a1e3814bd0fa assets/create/blockstates/pulse_repeater.json
|
||||
ea8200550190eb65d8631c7842e06d99274b3c79 assets/create/blockstates/purple_nixie_tube.json
|
||||
d06cd9a1101b18d306a786320aab12018b1325d6 assets/create/blockstates/purple_sail.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
|
||||
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
|
||||
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
|
||||
03a6020bfac9e4f979252abc8a631e6aafaa6b8b assets/create/lang/en_ud.json
|
||||
f30503db6d2841ebc7c59bf0a79b680a765613cd assets/create/lang/en_us.json
|
||||
3730041212c67067395b57218f26a403a18016c9 assets/create/lang/unfinished/de_de.json
|
||||
f1dd81b07e832b0f3187b2f52fdf3cdbea41fec1 assets/create/lang/unfinished/es_cl.json
|
||||
afc637fd921e0f17ec2b70d93b7a474d347a6a18 assets/create/lang/unfinished/es_es.json
|
||||
7258250074ffe3e50fe4803a2effe4f2b7a94c4e assets/create/lang/unfinished/fr_fr.json
|
||||
91cd404b62a87dd820cc5602622c88c65a5d5dbb assets/create/lang/unfinished/it_it.json
|
||||
7716adb1099e6b164d07390679b3a1b77397048e assets/create/lang/unfinished/ja_jp.json
|
||||
4b2b3ff736dbbfc58803432463e11850d651e631 assets/create/lang/unfinished/ko_kr.json
|
||||
23ec8c0fbb3d82e92397ef5857b2f57e2f72ae40 assets/create/lang/unfinished/nl_nl.json
|
||||
e8ef3db7b90bbc2a91bd104228c81b54bca638e7 assets/create/lang/unfinished/pl_pl.json
|
||||
0213870418b26af7f67c794973144594918fa114 assets/create/lang/unfinished/pt_br.json
|
||||
c0fccd4886228185a61af35535f3a92944d64c98 assets/create/lang/unfinished/pt_pt.json
|
||||
2cf778412184edac79cf457adb57f68475d7bcf0 assets/create/lang/unfinished/ru_ru.json
|
||||
feab3d65b3b95ecb6730d5d45fd672e4e2545ee3 assets/create/lang/unfinished/zh_cn.json
|
||||
eee611a3eecfa457050d522195f76e95a35dca81 assets/create/lang/unfinished/zh_tw.json
|
||||
dde2b8043a318bc88b6d381f9de6bfd557c0f079 assets/create/lang/en_ud.json
|
||||
0ea900a1d36f0b19568f8183844a64016c539dcf assets/create/lang/en_us.json
|
||||
c9977bb0eb8912a4260e414d8868628904d847a0 assets/create/lang/unfinished/de_de.json
|
||||
4d30c4754b8494fbbe62340b7c67ba3d2ada6721 assets/create/lang/unfinished/es_cl.json
|
||||
29c05f8ed2ec05e5bd4c73f6678946041c4e8293 assets/create/lang/unfinished/es_es.json
|
||||
027514a78a5f233c2d579694fa3c6a2c57ce3272 assets/create/lang/unfinished/fr_fr.json
|
||||
f354377f09ebc8ee7863dc24266215fc77003c11 assets/create/lang/unfinished/it_it.json
|
||||
8e8d4fe60ca6386e14c31cb4a24274cd21e92212 assets/create/lang/unfinished/ja_jp.json
|
||||
39194f6899360e4a13f0d3feac07ab25b5c18256 assets/create/lang/unfinished/ko_kr.json
|
||||
4b067fe0830950e7cc6615c8f466686b5aefee7f assets/create/lang/unfinished/nl_nl.json
|
||||
44fd3bc93eb6f2dce30a7f52a765662fb1093791 assets/create/lang/unfinished/pl_pl.json
|
||||
410f0132633089e26db9d7b70c49fc3c39541cd6 assets/create/lang/unfinished/pt_br.json
|
||||
bec4373054c1e0d2cd803572f8491e7597e292c2 assets/create/lang/unfinished/pt_pt.json
|
||||
3ff78cccb260071cf5d55af9ace4f7ed1eadb46b assets/create/lang/unfinished/ru_ru.json
|
||||
9ea4b032f852a55d9359fb931f5eb91243d87e36 assets/create/lang/unfinished/zh_cn.json
|
||||
33a7cf2b3b6014b5714fdb5f63de49474f23d2aa assets/create/lang/unfinished/zh_tw.json
|
||||
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
|
||||
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
|
||||
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
|
||||
|
@ -1783,11 +1785,13 @@ b1eace1d7fe80e2b8dc0d844621f0d485f34cbf8 assets/create/models/item/cut_veridium_
|
|||
523cd531eadaadc45fb356ca58b99a8fe206c3a7 assets/create/models/item/cyan_valve_handle.json
|
||||
f786a43e296d9f10d7c302fe3ae9cddf4ba9984e assets/create/models/item/dark_oak_window.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
|
||||
0f220a538e6a083debf68b4f1135d5f3ae4a3918 assets/create/models/item/deepslate_zinc_ore.json
|
||||
2104c1276259ab67b94f3d4fe97e14b6bc6941ac assets/create/models/item/deployer.json
|
||||
84d87f715efab45dc7bcb2e3c0870ed56fa20ee9 assets/create/models/item/depot.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
|
||||
df8cfe7e8eb527329094396e11222e9097e309d7 assets/create/models/item/diving_helmet.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
|
||||
0d17705688109e9cf81c99ef559b1183b0e6053c data/create/loot_tables/blocks/dark_oak_window.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
|
||||
841d6010e87a4bf4e35e8ccc411e5d7f513b484a data/create/loot_tables/blocks/deepslate_zinc_ore.json
|
||||
12a02b7737557a81281369826907b7e75076b8a0 data/create/loot_tables/blocks/deployer.json
|
||||
b6118279802f1a27e6e0c3d0feca86f0792f85df data/create/loot_tables/blocks/depot.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
|
||||
2186860c4a0cb47a66bdfdefcde302c599cddeea data/create/loot_tables/blocks/encased_chain_drive.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
|
||||
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/lush_ground_replaceable.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
|
||||
e157c1d3af30e409e34bbefbe15a037e6e1c8daa data/minecraft/tags/blocks/needs_iron_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": {
|
||||
"facing=north,powered=false,powering=false": {
|
||||
"facing=north,inverted=false,powered=false,powering=false": {
|
||||
"model": "create:block/diodes/pulse_extender",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,powered=false,powering=false": {
|
||||
"facing=south,inverted=false,powered=false,powering=false": {
|
||||
"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",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,powered=false,powering=false": {
|
||||
"facing=east,inverted=false,powered=false,powering=false": {
|
||||
"model": "create:block/diodes/pulse_extender",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,powered=true,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": {
|
||||
"facing=north,inverted=true,powered=false,powering=false": {
|
||||
"model": "create:block/pulse_extender_powering",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,powered=false,powering=true": {
|
||||
"facing=south,inverted=true,powered=false,powering=false": {
|
||||
"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",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,powered=false,powering=true": {
|
||||
"facing=east,inverted=true,powered=false,powering=false": {
|
||||
"model": "create:block/pulse_extender_powering",
|
||||
"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",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,powered=true,powering=true": {
|
||||
"facing=south,inverted=true,powered=true,powering=false": {
|
||||
"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",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,powered=true,powering=true": {
|
||||
"facing=east,inverted=true,powered=true,powering=false": {
|
||||
"model": "create:block/pulse_extender_powered_powering",
|
||||
"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": {
|
||||
"facing=north,powered=false,powering=false": {
|
||||
"facing=north,inverted=false,powered=false,powering=false": {
|
||||
"model": "create:block/diodes/pulse_repeater",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,powered=false,powering=false": {
|
||||
"facing=south,inverted=false,powered=false,powering=false": {
|
||||
"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",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,powered=false,powering=false": {
|
||||
"facing=east,inverted=false,powered=false,powering=false": {
|
||||
"model": "create:block/diodes/pulse_repeater",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,powered=true,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": {
|
||||
"facing=north,inverted=true,powered=false,powering=false": {
|
||||
"model": "create:block/pulse_repeater_powering",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,powered=false,powering=true": {
|
||||
"facing=south,inverted=true,powered=false,powering=false": {
|
||||
"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",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,powered=false,powering=true": {
|
||||
"facing=east,inverted=true,powered=false,powering=false": {
|
||||
"model": "create:block/pulse_repeater_powering",
|
||||
"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",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,powered=true,powering=true": {
|
||||
"facing=south,inverted=true,powered=true,powering=false": {
|
||||
"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",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,powered=true,powering=true": {
|
||||
"facing=east,inverted=true,powered=true,powering=false": {
|
||||
"model": "create:block/pulse_repeater_powered_powering",
|
||||
"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.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.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_zinc_ore": "\u01DD\u0279O \u0254u\u0131Z \u01DD\u0287\u0250\u05DFsd\u01DD\u01DD\u15E1",
|
||||
"block.create.deployer": "\u0279\u01DD\u028Eo\u05DFd\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.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.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",
|
||||
|
|
|
@ -192,11 +192,13 @@
|
|||
"block.create.cyan_valve_handle": "Cyan Valve Handle",
|
||||
"block.create.dark_oak_window": "Dark Oak Window",
|
||||
"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_zinc_ore": "Deepslate Zinc Ore",
|
||||
"block.create.deployer": "Deployer",
|
||||
"block.create.depot": "Depot",
|
||||
"block.create.diorite_pillar": "Diorite Pillar",
|
||||
"block.create.display_board": "Display Board",
|
||||
"block.create.dripstone_pillar": "Dripstone Pillar",
|
||||
"block.create.encased_chain_drive": "Encased Chain Drive",
|
||||
"block.create.encased_fan": "Encased Fan",
|
||||
|
@ -1433,6 +1435,72 @@
|
|||
"create.contraption.controls.stop_controlling": "Stopped controlling contraption",
|
||||
"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.overlay2": "This is a sample overlay",
|
||||
"create.gui.config.overlay3": "Click or drag with your mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1439",
|
||||
"_": "Missing Localizations: 1503",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "Türkiser Ventilgriff",
|
||||
"block.create.dark_oak_window": "Schwarzeichenholzfenster",
|
||||
"block.create.dark_oak_window_pane": "Schwarzeichenholzfensterscheibe",
|
||||
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
||||
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||
"block.create.deployer": "Einsatzgerät",
|
||||
"block.create.depot": "Depot",
|
||||
"block.create.diorite_pillar": "Dioritsäule",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||
"block.create.encased_chain_drive": "Ummantelter Kettenriemen",
|
||||
"block.create.encased_fan": "Ummantelter Lüfter",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "Dies ist ein Beispiel Overlay",
|
||||
"create.gui.config.overlay3": "Klicke oder ziehe mit deiner Maus",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 450",
|
||||
"_": "Missing Localizations: 514",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "Válvula Cian",
|
||||
"block.create.dark_oak_window": "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_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||
"block.create.deployer": "Desplegador",
|
||||
"block.create.depot": "Depósito",
|
||||
"block.create.diorite_pillar": "Pilar de Diorita",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||
"block.create.encased_chain_drive": "Conductor en Cadena Encubierto",
|
||||
"block.create.encased_fan": "Ventilador Encubierto",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "Este es un overlay de ejemplo",
|
||||
"create.gui.config.overlay3": "Haz clic o arrastra con el mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 121",
|
||||
"_": "Missing Localizations: 185",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "Asa de válvula cian",
|
||||
"block.create.dark_oak_window": "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_zinc_ore": "Mena de cinc de pizarra profunda",
|
||||
"block.create.deployer": "Desplegador",
|
||||
"block.create.depot": "Depósito",
|
||||
"block.create.diorite_pillar": "Pilar de diorita",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "Pilar de espeleotema",
|
||||
"block.create.encased_chain_drive": "Cadena de transmisión revestida",
|
||||
"block.create.encased_fan": "Ventilador revestido",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "Esta es una muestra de la superposición",
|
||||
"create.gui.config.overlay3": "Haga clic o arrastre con el ratón",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1701",
|
||||
"_": "Missing Localizations: 1765",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "Vanne cyan",
|
||||
"block.create.dark_oak_window": "fenêtre 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_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||
"block.create.deployer": "Déployeur",
|
||||
"block.create.depot": "Dépot",
|
||||
"block.create.diorite_pillar": "UNLOCALIZED: Diorite Pillar",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||
"block.create.encased_chain_drive": "Chaine de transmission",
|
||||
"block.create.encased_fan": "Ventilateur enchâssé",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "UNLOCALIZED: This is a sample overlay",
|
||||
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1390",
|
||||
"_": "Missing Localizations: 1454",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "Maniglia per valvola ciano",
|
||||
"block.create.dark_oak_window": "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_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||
"block.create.deployer": "Installatore",
|
||||
"block.create.depot": "Deposito",
|
||||
"block.create.diorite_pillar": "Pilastro di diorite",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||
"block.create.encased_chain_drive": "Trasmissione a catena incassata",
|
||||
"block.create.encased_fan": "Ventilatore incassato",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "Questo overlay è di esempio",
|
||||
"create.gui.config.overlay3": "Cliccalo o trascinalo col mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 116",
|
||||
"_": "Missing Localizations: 180",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "水色のバルブハンドル",
|
||||
"block.create.dark_oak_window": "ダークオークの窓",
|
||||
"block.create.dark_oak_window_pane": "ダークオークの板窓",
|
||||
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||
"block.create.deepslate_pillar": "深層岩の柱",
|
||||
"block.create.deepslate_zinc_ore": "深層亜鉛鉱石",
|
||||
"block.create.deployer": "デプロイヤー",
|
||||
"block.create.depot": "デポ",
|
||||
"block.create.diorite_pillar": "閃緑岩の柱",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "鍾乳石の柱",
|
||||
"block.create.encased_chain_drive": "ケース入りチェーンドライブ",
|
||||
"block.create.encased_fan": "ケース入りファン",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "これはオーバーレイのサンプルです",
|
||||
"create.gui.config.overlay3": "マウスでクリックまたはドラッグしてください",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 116",
|
||||
"_": "Missing Localizations: 180",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "청록색 밸브 손잡이",
|
||||
"block.create.dark_oak_window": "짙은 참나무 유리창",
|
||||
"block.create.dark_oak_window_pane": "짙은 참나무 유리판",
|
||||
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||
"block.create.deepslate_pillar": "심층암 기둥",
|
||||
"block.create.deepslate_zinc_ore": "심층암 아연 광석",
|
||||
"block.create.deployer": "기계 손",
|
||||
"block.create.depot": "아이템 거치대",
|
||||
"block.create.diorite_pillar": "섬록암 기둥",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "점적석 기둥",
|
||||
"block.create.encased_chain_drive": "체인 드라이브",
|
||||
"block.create.encased_fan": "선풍기",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "This is a sample overlay",
|
||||
"create.gui.config.overlay3": "Click or drag with your mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 2054",
|
||||
"_": "Missing Localizations: 2118",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "UNLOCALIZED: Cyan Valve Handle",
|
||||
"block.create.dark_oak_window": "UNLOCALIZED: Dark Oak Window",
|
||||
"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_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||
"block.create.deployer": "UNLOCALIZED: Deployer",
|
||||
"block.create.depot": "UNLOCALIZED: Depot",
|
||||
"block.create.diorite_pillar": "UNLOCALIZED: Diorite Pillar",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||
"block.create.encased_chain_drive": "UNLOCALIZED: Encased Chain Drive",
|
||||
"block.create.encased_fan": "Omhulsde Ventilator",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "UNLOCALIZED: This is a sample overlay",
|
||||
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 489",
|
||||
"_": "Missing Localizations: 553",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "Błękitne pokrętło",
|
||||
"block.create.dark_oak_window": "Ciemnodębowe okno",
|
||||
"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_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||
"block.create.deployer": "Aplikator",
|
||||
"block.create.depot": "Składnica",
|
||||
"block.create.diorite_pillar": "Diorytowy filar",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||
"block.create.encased_chain_drive": "Izolowany przekaźnik łańcuchowy",
|
||||
"block.create.encased_fan": "Izolowany wiatrak",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "To jest przykładowa nakładka",
|
||||
"create.gui.config.overlay3": "Kliknij lub przeciągnij myszką",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1301",
|
||||
"_": "Missing Localizations: 1365",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "Válvula ciano",
|
||||
"block.create.dark_oak_window": "Janela 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_zinc_ore": "Minério de zinco de ardósia",
|
||||
"block.create.deployer": "Implantador",
|
||||
"block.create.depot": "Depósito",
|
||||
"block.create.diorite_pillar": "Pilar de diorito",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "Pilar de espeleotema",
|
||||
"block.create.encased_chain_drive": "Correia Revestida",
|
||||
"block.create.encased_fan": "Ventilador Revestida",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "UNLOCALIZED: This is a sample overlay",
|
||||
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1673",
|
||||
"_": "Missing Localizations: 1737",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "Manopla de válvula ciano",
|
||||
"block.create.dark_oak_window": "UNLOCALIZED: Dark Oak Window",
|
||||
"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_zinc_ore": "Deepslate zinc ore",
|
||||
"block.create.deployer": "Implantador",
|
||||
"block.create.depot": "Depósito",
|
||||
"block.create.diorite_pillar": "UNLOCALIZED: Diorite Pillar",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||
"block.create.encased_chain_drive": "Correia Revestida",
|
||||
"block.create.encased_fan": "Ventilador Revestida",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "UNLOCALIZED: This is a sample overlay",
|
||||
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 494",
|
||||
"_": "Missing Localizations: 558",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "Бирюзовый ручной вентиль",
|
||||
"block.create.dark_oak_window": "Окно из тёмного дуба",
|
||||
"block.create.dark_oak_window_pane": "Панель из окна из тёмного дуб",
|
||||
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
||||
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||
"block.create.deployer": "Автономный активатор",
|
||||
"block.create.depot": "Депо",
|
||||
"block.create.diorite_pillar": "Диоритовая колонна",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||
"block.create.encased_chain_drive": "Цепной привод в корпусе",
|
||||
"block.create.encased_fan": "Вентилятор в корпусе",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "Это образец оверлея",
|
||||
"create.gui.config.overlay3": "Кликни и тащи с помощью мыши",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 116",
|
||||
"_": "Missing Localizations: 180",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "青色阀门手轮",
|
||||
"block.create.dark_oak_window": "深色橡木窗户",
|
||||
"block.create.dark_oak_window_pane": "深色橡木窗户板",
|
||||
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||
"block.create.deepslate_pillar": "深板岩柱",
|
||||
"block.create.deepslate_zinc_ore": "深层锌矿石",
|
||||
"block.create.deployer": "机械手",
|
||||
"block.create.depot": "置物台",
|
||||
"block.create.diorite_pillar": "闪长岩柱",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "滴水石柱",
|
||||
"block.create.encased_chain_drive": "链式传动箱",
|
||||
"block.create.encased_fan": "鼓风机",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "这是一个实例层",
|
||||
"create.gui.config.overlay3": "点击拖拽你的鼠标",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 508",
|
||||
"_": "Missing Localizations: 572",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -193,11 +193,13 @@
|
|||
"block.create.cyan_valve_handle": "藍綠色閥門開關",
|
||||
"block.create.dark_oak_window": "黑橡木窗戶",
|
||||
"block.create.dark_oak_window_pane": "黑橡木窗戶片",
|
||||
"block.create.data_gatherer": "UNLOCALIZED: Data Gatherer",
|
||||
"block.create.deepslate_pillar": "UNLOCALIZED: Deepslate Pillar",
|
||||
"block.create.deepslate_zinc_ore": "UNLOCALIZED: Deepslate Zinc Ore",
|
||||
"block.create.deployer": "機器手",
|
||||
"block.create.depot": "置物臺",
|
||||
"block.create.diorite_pillar": "豎紋閃長岩",
|
||||
"block.create.display_board": "UNLOCALIZED: Display Board",
|
||||
"block.create.dripstone_pillar": "UNLOCALIZED: Dripstone Pillar",
|
||||
"block.create.encased_chain_drive": "鏈式傳動箱",
|
||||
"block.create.encased_fan": "鼓風機",
|
||||
|
@ -1434,6 +1436,72 @@
|
|||
"create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption",
|
||||
"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.overlay2": "這是一個實例層",
|
||||
"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:stockpile_switch",
|
||||
"create:creative_crate",
|
||||
"create:display_board",
|
||||
"create:nixie_tube",
|
||||
"create:white_nixie_tube",
|
||||
"create:magenta_nixie_tube",
|
||||
|
|
|
@ -110,55 +110,40 @@ public class AllBlockPartials {
|
|||
|
||||
COPPER_BACKTANK_SHAFT = block("copper_backtank/block_shaft_input"),
|
||||
COPPER_BACKTANK_COGS = block("copper_backtank/block_cogs"),
|
||||
|
||||
TRACK_SEGMENT_LEFT = block("track/segment_left"),
|
||||
TRACK_SEGMENT_RIGHT = block("track/segment_right"),
|
||||
TRACK_TIE = block("track/tie"),
|
||||
GIRDER_SEGMENT_TOP = block("metal_girder/segment_top"),
|
||||
|
||||
TRACK_SEGMENT_LEFT = block("track/segment_left"), TRACK_SEGMENT_RIGHT = block("track/segment_right"),
|
||||
TRACK_TIE = block("track/tie"), GIRDER_SEGMENT_TOP = block("metal_girder/segment_top"),
|
||||
GIRDER_SEGMENT_MIDDLE = block("metal_girder/segment_middle"),
|
||||
GIRDER_SEGMENT_BOTTOM = block("metal_girder/segment_bottom"),
|
||||
|
||||
TRACK_STATION_OVERLAY = block("track_overlay/station"),
|
||||
TRACK_SIGNAL_OVERLAY = block("track_overlay/signal"),
|
||||
|
||||
TRACK_STATION_OVERLAY = block("track_overlay/station"), TRACK_SIGNAL_OVERLAY = block("track_overlay/signal"),
|
||||
TRACK_ASSEMBLING_OVERLAY = block("track_overlay/assembling"),
|
||||
TRACK_SIGNAL_DUAL_OVERLAY = block("track_overlay/signal_dual"),
|
||||
|
||||
BOGEY_FRAME = block("track/bogey/bogey_frame"),
|
||||
SMALL_BOGEY_WHEELS = block("track/bogey/bogey_wheel"),
|
||||
BOGEY_PIN = block("track/bogey/bogey_drive_wheel_pin"),
|
||||
BOGEY_PISTON = block("track/bogey/bogey_drive_piston"),
|
||||
BOGEY_DRIVE = block("track/bogey/bogey_drive"),
|
||||
LARGE_BOGEY_WHEELS = block("track/bogey/bogey_drive_wheel"),
|
||||
|
||||
|
||||
BOGEY_FRAME = block("track/bogey/bogey_frame"), SMALL_BOGEY_WHEELS = block("track/bogey/bogey_wheel"),
|
||||
BOGEY_PIN = block("track/bogey/bogey_drive_wheel_pin"), BOGEY_PISTON = block("track/bogey/bogey_drive_piston"),
|
||||
BOGEY_DRIVE = block("track/bogey/bogey_drive"), LARGE_BOGEY_WHEELS = block("track/bogey/bogey_drive_wheel"),
|
||||
|
||||
TRAIN_COUPLING_HEAD = block("track/bogey/coupling_head"),
|
||||
TRAIN_COUPLING_CABLE = block("track/bogey/coupling_cable"),
|
||||
|
||||
TRAIN_CONTROLS_COVER = block("controls/train/cover"),
|
||||
TRAIN_CONTROLS_LEVER = block("controls/train/lever"),
|
||||
|
||||
ENGINE_PISTON = block("steam_engine/piston"),
|
||||
ENGINE_LINKAGE = block("steam_engine/linkage"),
|
||||
ENGINE_CONNECTOR = block("steam_engine/shaft_connector"),
|
||||
BOILER_GAUGE = block("steam_engine/gauge"),
|
||||
|
||||
SIGNAL_ON = block("track_signal/indicator_on"),
|
||||
SIGNAL_OFF = block("track_signal/indicator_off"),
|
||||
|
||||
SIGNAL_PANEL = block("track_signal/panel"),
|
||||
SIGNAL_WHITE_CUBE = block("track_signal/white_cube"),
|
||||
SIGNAL_WHITE_GLOW = block("track_signal/white_glow"),
|
||||
SIGNAL_WHITE = block("track_signal/white_tube"),
|
||||
SIGNAL_RED_CUBE = block("track_signal/red_cube"),
|
||||
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"),
|
||||
|
||||
TRAIN_CONTROLS_COVER = block("controls/train/cover"), TRAIN_CONTROLS_LEVER = block("controls/train/lever"),
|
||||
|
||||
ENGINE_PISTON = block("steam_engine/piston"), ENGINE_LINKAGE = block("steam_engine/linkage"),
|
||||
ENGINE_CONNECTOR = block("steam_engine/shaft_connector"), BOILER_GAUGE = block("steam_engine/gauge"),
|
||||
|
||||
SIGNAL_ON = block("track_signal/indicator_on"), SIGNAL_OFF = block("track_signal/indicator_off"),
|
||||
|
||||
SIGNAL_PANEL = block("track_signal/panel"), SIGNAL_WHITE_CUBE = block("track_signal/white_cube"),
|
||||
SIGNAL_WHITE_GLOW = block("track_signal/white_glow"), SIGNAL_WHITE = block("track_signal/white_tube"),
|
||||
SIGNAL_RED_CUBE = block("track_signal/red_cube"), 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_2x2 = entity("crafting_blueprint_medium"),
|
||||
CRAFTING_BLUEPRINT_3x3 = entity("crafting_blueprint_large"),
|
||||
|
||||
|
||||
COUPLING_ATTACHMENT = entity("minecart_coupling/attachment"), COUPLING_RING = entity("minecart_coupling/ring"),
|
||||
COUPLING_CONNECTOR = entity("minecart_coupling/connector")
|
||||
|
||||
|
@ -169,8 +154,7 @@ public class AllBlockPartials {
|
|||
|
||||
public static final Map<BlazeBurnerBlock.HeatLevel, PartialModel> BLAZES =
|
||||
new EnumMap<>(BlazeBurnerBlock.HeatLevel.class);
|
||||
public static final Map<Direction, PartialModel> METAL_GIRDER_BRACKETS =
|
||||
new EnumMap<>(Direction.class);
|
||||
public static final Map<Direction, PartialModel> METAL_GIRDER_BRACKETS = new EnumMap<>(Direction.class);
|
||||
public static final Map<DyeColor, PartialModel> TOOLBOX_LIDS = new EnumMap<>(DyeColor.class);
|
||||
|
||||
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.tagBlockAndItem;
|
||||
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.CreateRegistrate.connectedTextures;
|
||||
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.ChuteItem;
|
||||
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.EjectorBlock;
|
||||
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.ItemVaultItem;
|
||||
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.signal.SignalBlock;
|
||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlock;
|
||||
|
@ -426,6 +440,7 @@ public class AllBlocks {
|
|||
.transform(axeOrPickaxe())
|
||||
.blockstate(new BeltGenerator()::generate)
|
||||
.transform(BlockStressDefaults.setImpact(0))
|
||||
.onRegister(assignDataBehaviour(new ItemNameDataSource(), "combine_item_names"))
|
||||
.onRegister(CreateRegistrate.blockModel(() -> BeltModel::new))
|
||||
.register();
|
||||
|
||||
|
@ -495,6 +510,8 @@ public class AllBlocks {
|
|||
REGISTRATE.block("cuckoo_clock", CuckooClockBlock::regular)
|
||||
.transform(axeOrPickaxe())
|
||||
.transform(BuilderTransformers.cuckooClock())
|
||||
.onRegister(assignDataBehaviour(new TimeOfDayDataSource(), "time_of_day"))
|
||||
.onRegister(assignDataBehaviour(new StopWatchDataSource(), "stop_watch"))
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<CuckooClockBlock> MYSTERIOUS_CUCKOO_CLOCK =
|
||||
|
@ -528,7 +545,9 @@ public class AllBlocks {
|
|||
public static final BlockEntry<CrushingWheelControllerBlock> CRUSHING_WHEEL_CONTROLLER =
|
||||
REGISTRATE.block("crushing_wheel_controller", CrushingWheelControllerBlock::new)
|
||||
.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())
|
||||
.forAllStatesExcept(state -> ConfiguredModel.builder()
|
||||
.modelFile(p.models()
|
||||
|
@ -606,6 +625,7 @@ public class AllBlocks {
|
|||
.initialProperties(SharedProperties::stone)
|
||||
.transform(axeOrPickaxe())
|
||||
.blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p)))
|
||||
.onRegister(assignDataBehaviour(new ItemNameDataSource(), "combine_item_names"))
|
||||
.item()
|
||||
.transform(customItemModel("_", "block"))
|
||||
.register();
|
||||
|
@ -617,6 +637,7 @@ public class AllBlocks {
|
|||
.transform(axeOrPickaxe())
|
||||
.blockstate((c, p) -> p.horizontalBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p), 180))
|
||||
.transform(BlockStressDefaults.setImpact(2.0))
|
||||
.onRegister(assignDataBehaviour(new ItemNameDataSource(), "combine_item_names"))
|
||||
.item(EjectorItem::new)
|
||||
.transform(customItemModel())
|
||||
.register();
|
||||
|
@ -1330,6 +1351,7 @@ public class AllBlocks {
|
|||
.blockstate((c, p) -> p.horizontalBlock(c.get(),
|
||||
s -> s.getValue(StationBlock.ASSEMBLING) ? AssetLookup.partialBaseModel(c, p, "assembling")
|
||||
: AssetLookup.partialBaseModel(c, p)))
|
||||
.onRegister(assignDataBehaviour(new StationSummaryDataSource(), "station_summary"))
|
||||
.lang("Train Station")
|
||||
.item(TrackTargetingBlockItem::new)
|
||||
.transform(customItemModel("_", "block"))
|
||||
|
@ -1430,11 +1452,13 @@ public class AllBlocks {
|
|||
public static final BlockEntry<BeltTunnelBlock> ANDESITE_TUNNEL =
|
||||
REGISTRATE.block("andesite_tunnel", BeltTunnelBlock::new)
|
||||
.transform(BuilderTransformers.beltTunnel("andesite", new ResourceLocation("block/polished_andesite")))
|
||||
.onRegister(assignDataBehaviour(new AccumulatedItemCountDataSource(), "accumulate_items"))
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<BrassTunnelBlock> BRASS_TUNNEL =
|
||||
REGISTRATE.block("brass_tunnel", BrassTunnelBlock::new)
|
||||
.transform(BuilderTransformers.beltTunnel("brass", Create.asResource("block/brass_block")))
|
||||
.onRegister(assignDataBehaviour(new ItemThoughputDataSource(), "item_throughput"))
|
||||
.onRegister(connectedTextures(BrassTunnelCTBehaviour::new))
|
||||
.register();
|
||||
|
||||
|
@ -1443,6 +1467,8 @@ public class AllBlocks {
|
|||
.initialProperties(SharedProperties::stone)
|
||||
.transform(axeOrPickaxe())
|
||||
.blockstate((c, p) -> p.horizontalBlock(c.get(), AssetLookup.forPowered(c, p)))
|
||||
.onRegister(assignDataBehaviour(new ItemCountDataSource(), "count_items"))
|
||||
.onRegister(assignDataBehaviour(new ItemListDataSource(), "list_items"))
|
||||
.item()
|
||||
.transform(customItemModel("_", "block"))
|
||||
.register();
|
||||
|
@ -1453,6 +1479,7 @@ public class AllBlocks {
|
|||
.transform(axeOrPickaxe())
|
||||
.blockstate((c, p) -> p.horizontalBlock(c.get(),
|
||||
AssetLookup.withIndicator(c, p, $ -> AssetLookup.standardModel(c, p), StockpileSwitchBlock.INDICATOR)))
|
||||
.onRegister(assignDataBehaviour(new FillLevelDataSource(), "fill_level"))
|
||||
.simpleItem()
|
||||
.register();
|
||||
|
||||
|
@ -1462,6 +1489,28 @@ public class AllBlocks {
|
|||
.tag(AllBlockTags.SAFE_NBT.tag)
|
||||
.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 =
|
||||
REGISTRATE.block("nixie_tube", p -> new NixieTubeBlock(p, DyeColor.ORANGE))
|
||||
.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)
|
||||
.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)
|
||||
.add(1, 5, 4, 15, 13, 12)
|
||||
.forHorizontalAxis(),
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
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.HalfShaftInstance;
|
||||
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.SmartChuteRenderer;
|
||||
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.DepotTileEntity;
|
||||
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.LecternControllerTileEntity;
|
||||
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.SignalTileEntity;
|
||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationRenderer;
|
||||
|
@ -287,10 +294,10 @@ public class AllTileEntities {
|
|||
.register();
|
||||
|
||||
public static final BlockEntityEntry<HandCrankTileEntity> HAND_CRANK = Create.registrate()
|
||||
.tileEntity("hand_crank", HandCrankTileEntity::new)
|
||||
.instance(() -> HandCrankInstance::new)
|
||||
.validBlocks(AllBlocks.HAND_CRANK, AllBlocks.COPPER_VALVE_HANDLE)
|
||||
.validBlocks(AllBlocks.DYED_VALVE_HANDLES.toArray())
|
||||
.tileEntity("hand_crank", HandCrankTileEntity::new)
|
||||
.instance(() -> HandCrankInstance::new)
|
||||
.validBlocks(AllBlocks.HAND_CRANK, AllBlocks.COPPER_VALVE_HANDLE)
|
||||
.validBlocks(AllBlocks.DYED_VALVE_HANDLES.toArray())
|
||||
.renderer(() -> HandCrankRenderer::new)
|
||||
.register();
|
||||
|
||||
|
@ -503,19 +510,20 @@ public class AllTileEntities {
|
|||
.renderer(() -> PortableStorageInterfaceRenderer::new)
|
||||
.register();
|
||||
|
||||
public static final BlockEntityEntry<PortableFluidInterfaceTileEntity> PORTABLE_FLUID_INTERFACE = Create.registrate()
|
||||
.tileEntity("portable_fluid_interface", PortableFluidInterfaceTileEntity::new)
|
||||
.instance(() -> PSIInstance::new)
|
||||
.validBlocks(AllBlocks.PORTABLE_FLUID_INTERFACE)
|
||||
.renderer(() -> PortableStorageInterfaceRenderer::new)
|
||||
.register();
|
||||
|
||||
public static final BlockEntityEntry<PortableFluidInterfaceTileEntity> PORTABLE_FLUID_INTERFACE =
|
||||
Create.registrate()
|
||||
.tileEntity("portable_fluid_interface", PortableFluidInterfaceTileEntity::new)
|
||||
.instance(() -> PSIInstance::new)
|
||||
.validBlocks(AllBlocks.PORTABLE_FLUID_INTERFACE)
|
||||
.renderer(() -> PortableStorageInterfaceRenderer::new)
|
||||
.register();
|
||||
|
||||
public static final BlockEntityEntry<SteamEngineTileEntity> STEAM_ENGINE = Create.registrate()
|
||||
.tileEntity("steam_engine", SteamEngineTileEntity::new)
|
||||
.validBlocks(AllBlocks.STEAM_ENGINE)
|
||||
.renderer(() -> SteamEngineRenderer::new)
|
||||
.register();
|
||||
|
||||
|
||||
public static final BlockEntityEntry<PoweredShaftTileEntity> POWERED_SHAFT = Create.registrate()
|
||||
.tileEntity("powered_shaft", PoweredShaftTileEntity::new)
|
||||
.instance(() -> SingleRotatingInstance::new, false)
|
||||
|
@ -658,6 +666,13 @@ public class AllTileEntities {
|
|||
.validBlocks(AllBlocks.ORANGE_NIXIE_TUBE)
|
||||
.validBlocks(AllBlocks.NIXIE_TUBES.toArray())
|
||||
.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();
|
||||
|
||||
public static final BlockEntityEntry<StockpileSwitchTileEntity> STOCKPILE_SWITCH = Create.registrate()
|
||||
|
@ -706,20 +721,18 @@ public class AllTileEntities {
|
|||
.renderer(() -> BrassDiodeRenderer::new)
|
||||
.register();
|
||||
|
||||
public static final BlockEntityEntry<PulseRepeaterTileEntity> PULSE_REPEATER =
|
||||
Create.registrate()
|
||||
.tileEntity("pulse_repeater", PulseRepeaterTileEntity::new)
|
||||
.instance(() -> BrassDiodeInstance::new, false)
|
||||
.validBlocks(AllBlocks.PULSE_REPEATER)
|
||||
.renderer(() -> BrassDiodeRenderer::new)
|
||||
.register();
|
||||
public static final BlockEntityEntry<PulseRepeaterTileEntity> PULSE_REPEATER = Create.registrate()
|
||||
.tileEntity("pulse_repeater", PulseRepeaterTileEntity::new)
|
||||
.instance(() -> BrassDiodeInstance::new, false)
|
||||
.validBlocks(AllBlocks.PULSE_REPEATER)
|
||||
.renderer(() -> BrassDiodeRenderer::new)
|
||||
.register();
|
||||
|
||||
public static final BlockEntityEntry<LecternControllerTileEntity> LECTERN_CONTROLLER =
|
||||
Create.registrate()
|
||||
.tileEntity("lectern_controller", LecternControllerTileEntity::new)
|
||||
.validBlocks(AllBlocks.LECTERN_CONTROLLER)
|
||||
.renderer(() -> LecternControllerRenderer::new)
|
||||
.register();
|
||||
public static final BlockEntityEntry<LecternControllerTileEntity> LECTERN_CONTROLLER = Create.registrate()
|
||||
.tileEntity("lectern_controller", LecternControllerTileEntity::new)
|
||||
.validBlocks(AllBlocks.LECTERN_CONTROLLER)
|
||||
.renderer(() -> LecternControllerRenderer::new)
|
||||
.register();
|
||||
|
||||
// Curiosities
|
||||
public static final BlockEntityEntry<CopperBacktankTileEntity> COPPER_BACKTANK = Create.registrate()
|
||||
|
@ -766,7 +779,14 @@ public class AllTileEntities {
|
|||
.renderer(() -> StationRenderer::new)
|
||||
.validBlocks(AllBlocks.TRACK_STATION)
|
||||
.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()
|
||||
.tileEntity("track_signal", SignalTileEntity::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.curiosities.weapons.BuiltinPotatoProjectileTypes;
|
||||
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.palettes.AllPaletteBlocks;
|
||||
import com.simibubi.create.content.palettes.PalettesItemGroup;
|
||||
|
@ -96,6 +97,7 @@ public class Create {
|
|||
AllEntityTypes.register();
|
||||
AllTileEntities.register();
|
||||
AllMovementBehaviours.register();
|
||||
AllDataGathererBehaviours.register();
|
||||
AllInteractionBehaviours.register();
|
||||
AllWorldFeatures.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.PASS;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity.Mode;
|
||||
import com.simibubi.create.content.contraptions.processing.InWorldProcessing;
|
||||
import com.simibubi.create.content.contraptions.components.press.PressingBehaviour.Mode;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
|
||||
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.TransportedItemStackHandlerBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult;
|
||||
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class BeltPressingCallbacks {
|
||||
|
||||
static ProcessingResult onItemReceived(TransportedItemStack transported,
|
||||
TransportedItemStackHandlerBehaviour handler, MechanicalPressTileEntity press) {
|
||||
if (press.getSpeed() == 0)
|
||||
TransportedItemStackHandlerBehaviour handler, PressingBehaviour behaviour) {
|
||||
if (behaviour.specifics.getKineticSpeed() == 0)
|
||||
return PASS;
|
||||
if (press.running)
|
||||
if (behaviour.running)
|
||||
return HOLD;
|
||||
if (!press.getRecipe(transported.stack)
|
||||
.isPresent())
|
||||
if (!behaviour.specifics.tryProcessOnBelt(transported, null, true))
|
||||
return PASS;
|
||||
|
||||
press.start(Mode.BELT);
|
||||
behaviour.start(Mode.BELT);
|
||||
return HOLD;
|
||||
}
|
||||
|
||||
static ProcessingResult whenItemHeld(TransportedItemStack transported, TransportedItemStackHandlerBehaviour handler,
|
||||
MechanicalPressTileEntity pressTe) {
|
||||
PressingBehaviour behaviour) {
|
||||
|
||||
if (pressTe.getSpeed() == 0)
|
||||
if (behaviour.specifics.getKineticSpeed() == 0)
|
||||
return PASS;
|
||||
if (!pressTe.running)
|
||||
if (!behaviour.running)
|
||||
return PASS;
|
||||
if (pressTe.runningTicks != MechanicalPressTileEntity.CYCLE / 2)
|
||||
if (behaviour.runningTicks != PressingBehaviour.CYCLE / 2)
|
||||
return HOLD;
|
||||
|
||||
Optional<PressingRecipe> recipe = pressTe.getRecipe(transported.stack);
|
||||
pressTe.pressedItems.clear();
|
||||
pressTe.pressedItems.add(transported.stack);
|
||||
|
||||
if (!recipe.isPresent())
|
||||
behaviour.particleItems.clear();
|
||||
ArrayList<ItemStack> results = new ArrayList<>();
|
||||
if (!behaviour.specifics.tryProcessOnBelt(transported, results, false))
|
||||
return PASS;
|
||||
|
||||
boolean bulk = MechanicalPressTileEntity.canProcessInBulk() || transported.stack.getCount() == 1;
|
||||
boolean bulk = behaviour.specifics.canProcessInBulk() || transported.stack.getCount() == 1;
|
||||
|
||||
List<TransportedItemStack> collect = InWorldProcessing
|
||||
.applyRecipeOn(bulk ? transported.stack : ItemHandlerHelper.copyStackWithSize(transported.stack, 1),
|
||||
recipe.get())
|
||||
.stream()
|
||||
List<TransportedItemStack> collect = results.stream()
|
||||
.map(stack -> {
|
||||
TransportedItemStack copy = transported.copy();
|
||||
boolean centered = BeltHelper.isItemUpright(stack);
|
||||
|
@ -84,8 +76,7 @@ public class BeltPressingCallbacks {
|
|||
handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(collect, left));
|
||||
}
|
||||
|
||||
AllTriggers.triggerForNearbyPlayers(AllTriggers.BONK, pressTe.getLevel(), pressTe.getBlockPos(), 4);
|
||||
pressTe.sendData();
|
||||
behaviour.tileEntity.sendData();
|
||||
return HOLD;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,18 +28,22 @@ public class MechanicalPressRenderer extends KineticTileEntityRenderer {
|
|||
|
||||
@Override
|
||||
protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer,
|
||||
int light, int overlay) {
|
||||
int light, int 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();
|
||||
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)
|
||||
.light(light)
|
||||
.renderInto(ms, buffer.getBuffer(RenderType.solid()));
|
||||
.light(light)
|
||||
.renderInto(ms, buffer.getBuffer(RenderType.solid()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,44 +1,34 @@
|
|||
package com.simibubi.create.content.contraptions.components.press;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllRecipeTypes;
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import com.simibubi.create.Create;
|
||||
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.processing.BasinOperatingTileEntity;
|
||||
import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
|
||||
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.ITriggerable;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.item.ItemHelper;
|
||||
import com.simibubi.create.foundation.item.SmartInventory;
|
||||
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.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.entity.Entity;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.CraftingRecipe;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
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.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
|
@ -47,64 +37,14 @@ import net.minecraftforge.items.ItemHandlerHelper;
|
|||
import net.minecraftforge.items.ItemStackHandler;
|
||||
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();
|
||||
public List<ItemStack> pressedItems = new ArrayList<>();
|
||||
public BeltProcessingBehaviour processingBehaviour;
|
||||
|
||||
public int prevRunningTicks;
|
||||
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 PressingBehaviour pressingBehaviour;
|
||||
|
||||
public MechanicalPressTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState 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
|
||||
|
@ -113,119 +53,21 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
|
|||
.expandTowards(0, 1, 0);
|
||||
}
|
||||
|
||||
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) * mode.headOffset;
|
||||
return Mth.clamp((CYCLE - ticks) / CYCLE * 3, 0, 1) * mode.headOffset;
|
||||
@Override
|
||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
||||
super.addBehaviours(behaviours);
|
||||
pressingBehaviour = new PressingBehaviour(this);
|
||||
behaviours.add(pressingBehaviour);
|
||||
}
|
||||
|
||||
public void start(Mode mode) {
|
||||
this.mode = mode;
|
||||
running = true;
|
||||
prevRunningTicks = 0;
|
||||
runningTicks = 0;
|
||||
pressedItems.clear();
|
||||
sendData();
|
||||
}
|
||||
|
||||
public boolean inWorld() {
|
||||
return mode == Mode.WORLD;
|
||||
}
|
||||
|
||||
public boolean onBasin() {
|
||||
return mode == Mode.BASIN;
|
||||
public PressingBehaviour getPressingBehaviour() {
|
||||
return pressingBehaviour;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
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();
|
||||
public boolean tryProcessInBasin(boolean simulate) {
|
||||
applyBasinRecipe();
|
||||
|
||||
Optional<BasinTileEntity> basin = getBasin();
|
||||
if (basin.isPresent()) {
|
||||
SmartInventory inputs = basin.get()
|
||||
|
@ -234,99 +76,63 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
|
|||
ItemStack stackInSlot = inputs.getItem(slot);
|
||||
if (stackInSlot.isEmpty())
|
||||
continue;
|
||||
pressedItems.add(stackInSlot);
|
||||
pressingBehaviour.particleItems.add(stackInSlot);
|
||||
}
|
||||
}
|
||||
sendData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void applyPressingInWorld() {
|
||||
AABB bb = new AABB(worldPosition.below(1));
|
||||
boolean bulk = canProcessInBulk();
|
||||
pressedItems.clear();
|
||||
if (level.isClientSide)
|
||||
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();
|
||||
pressedItems.add(item);
|
||||
sendData();
|
||||
Optional<PressingRecipe> recipe = getRecipe(item);
|
||||
if (!recipe.isPresent())
|
||||
continue;
|
||||
@Override
|
||||
public boolean tryProcessInWorld(ItemEntity itemEntity, boolean simulate) {
|
||||
ItemStack item = itemEntity.getItem();
|
||||
Optional<PressingRecipe> recipe = getRecipe(item);
|
||||
if (!recipe.isPresent())
|
||||
return false;
|
||||
if (simulate)
|
||||
return true;
|
||||
|
||||
if (bulk || item.getCount() == 1) {
|
||||
InWorldProcessing.applyRecipeOn(itemEntity, recipe.get());
|
||||
} else {
|
||||
for (ItemStack result : InWorldProcessing.applyRecipeOn(ItemHandlerHelper.copyStackWithSize(item, 1),
|
||||
recipe.get())) {
|
||||
ItemEntity created =
|
||||
new ItemEntity(level, itemEntity.getX(), itemEntity.getY(), itemEntity.getZ(), result);
|
||||
created.setDefaultPickUpDelay();
|
||||
created.setDeltaMovement(VecHelper.offsetRandomly(Vec3.ZERO, Create.RANDOM, .05f));
|
||||
level.addFreshEntity(created);
|
||||
}
|
||||
item.shrink(1);
|
||||
pressingBehaviour.particleItems.add(item);
|
||||
if (canProcessInBulk() || item.getCount() == 1) {
|
||||
InWorldProcessing.applyRecipeOn(itemEntity, recipe.get());
|
||||
} else {
|
||||
for (ItemStack result : InWorldProcessing.applyRecipeOn(ItemHandlerHelper.copyStackWithSize(item, 1),
|
||||
recipe.get())) {
|
||||
ItemEntity created =
|
||||
new ItemEntity(level, itemEntity.getX(), itemEntity.getY(), itemEntity.getZ(), result);
|
||||
created.setDefaultPickUpDelay();
|
||||
created.setDeltaMovement(VecHelper.offsetRandomly(Vec3.ZERO, Create.RANDOM, .05f));
|
||||
level.addFreshEntity(created);
|
||||
}
|
||||
|
||||
AllTriggers.triggerForNearbyPlayers(AllTriggers.BONK, level, worldPosition, 4);
|
||||
entityScanCooldown = 0;
|
||||
|
||||
if (!bulk)
|
||||
break;
|
||||
item.shrink(1);
|
||||
}
|
||||
|
||||
AllTriggers.triggerForNearbyPlayers(AllTriggers.BONK, level, worldPosition, 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean canProcessInBulk() {
|
||||
return AllConfigs.SERVER.recipes.bulkPressing.get();
|
||||
@Override
|
||||
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() {
|
||||
if (getSpeed() == 0)
|
||||
return 0;
|
||||
return (int) Mth.lerp(Mth.clamp(Math.abs(getSpeed()) / 512f, 0, 1), 1, 60);
|
||||
}
|
||||
|
||||
protected void spawnParticles() {
|
||||
if (pressedItems.isEmpty())
|
||||
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);
|
||||
}
|
||||
@Override
|
||||
public void onPressingCompleted() {
|
||||
if (pressingBehaviour.onBasin() && matchBasinRecipe(currentRecipe)
|
||||
&& getBasin().filter(BasinTileEntity::canContinueProcessing)
|
||||
.isPresent())
|
||||
startProcessingBasin();
|
||||
else
|
||||
basinChecker.scheduleUpdate();
|
||||
}
|
||||
|
||||
private static final RecipeWrapper pressingInv = new RecipeWrapper(new ItemStackHandler(1));
|
||||
|
@ -350,35 +156,50 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
|
|||
|
||||
@Override
|
||||
protected <C extends Container> boolean matchStaticFilters(Recipe<C> recipe) {
|
||||
return (recipe instanceof CraftingRecipe && !(recipe instanceof MechanicalCraftingRecipe)
|
||||
&& canCompress(recipe) && !AllRecipeTypes.shouldIgnoreInAutomation(recipe))
|
||||
return (recipe instanceof CraftingRecipe && !(recipe instanceof MechanicalCraftingRecipe) && canCompress(recipe)
|
||||
&& !AllRecipeTypes.shouldIgnoreInAutomation(recipe))
|
||||
|| recipe.getType() == AllRecipeTypes.COMPACTING.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getKineticSpeed() {
|
||||
return getSpeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcessInBulk() {
|
||||
return AllConfigs.SERVER.recipes.bulkPressing.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getRecipeCacheKey() {
|
||||
return compressingRecipesKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getParticleAmount() {
|
||||
return 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startProcessingBasin() {
|
||||
if (running && runningTicks <= CYCLE / 2)
|
||||
if (pressingBehaviour.running && pressingBehaviour.runningTicks <= PressingBehaviour.CYCLE / 2)
|
||||
return;
|
||||
super.startProcessingBasin();
|
||||
start(Mode.BASIN);
|
||||
pressingBehaviour.start(Mode.BASIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBasinRemoved() {
|
||||
pressedItems.clear();
|
||||
running = false;
|
||||
runningTicks = 0;
|
||||
pressingBehaviour.particleItems.clear();
|
||||
pressingBehaviour.running = false;
|
||||
pressingBehaviour.runningTicks = 0;
|
||||
sendData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRunning() {
|
||||
return running;
|
||||
return pressingBehaviour.running;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -386,16 +207,4 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,51 +13,54 @@ import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
|||
|
||||
public class PressInstance extends ShaftInstance implements DynamicInstance {
|
||||
|
||||
private final OrientedData pressHead;
|
||||
private final MechanicalPressTileEntity press;
|
||||
private final OrientedData pressHead;
|
||||
private final MechanicalPressTileEntity press;
|
||||
|
||||
public PressInstance(MaterialManager dispatcher, MechanicalPressTileEntity tile) {
|
||||
super(dispatcher, tile);
|
||||
press = tile;
|
||||
public PressInstance(MaterialManager dispatcher, MechanicalPressTileEntity tile) {
|
||||
super(dispatcher, tile);
|
||||
press = tile;
|
||||
|
||||
pressHead = dispatcher.defaultSolid()
|
||||
.material(Materials.ORIENTED)
|
||||
.getModel(AllBlockPartials.MECHANICAL_PRESS_HEAD, blockState)
|
||||
.createInstance();
|
||||
pressHead = dispatcher.defaultSolid()
|
||||
.material(Materials.ORIENTED)
|
||||
.getModel(AllBlockPartials.MECHANICAL_PRESS_HEAD, blockState)
|
||||
.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);
|
||||
|
||||
transformModels();
|
||||
}
|
||||
transformModels();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginFrame() {
|
||||
transformModels();
|
||||
}
|
||||
@Override
|
||||
public void beginFrame() {
|
||||
transformModels();
|
||||
}
|
||||
|
||||
private void transformModels() {
|
||||
float renderedHeadOffset = getRenderedHeadOffset(press);
|
||||
private void transformModels() {
|
||||
float renderedHeadOffset = getRenderedHeadOffset(press);
|
||||
|
||||
pressHead.setPosition(getInstancePosition())
|
||||
.nudge(0, -renderedHeadOffset, 0);
|
||||
}
|
||||
pressHead.setPosition(getInstancePosition())
|
||||
.nudge(0, -renderedHeadOffset, 0);
|
||||
}
|
||||
|
||||
private float getRenderedHeadOffset(MechanicalPressTileEntity press) {
|
||||
return press.getRenderedHeadOffset(AnimationTickHolder.getPartialTicks());
|
||||
}
|
||||
private float getRenderedHeadOffset(MechanicalPressTileEntity press) {
|
||||
PressingBehaviour pressingBehaviour = press.getPressingBehaviour();
|
||||
return pressingBehaviour.getRenderedHeadOffset(AnimationTickHolder.getPartialTicks())
|
||||
* pressingBehaviour.mode.headOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
super.updateLight();
|
||||
@Override
|
||||
public void updateLight() {
|
||||
super.updateLight();
|
||||
|
||||
relight(pos, pressHead);
|
||||
}
|
||||
relight(pos, pressHead);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
pressHead.delete();
|
||||
}
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
pressHead.delete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.BrassTunnelBlock;
|
||||
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.behaviour.belt.DirectBeltInputBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
@ -44,6 +46,7 @@ public class BeltTunnelInteractionHandler {
|
|||
boolean onServer = !world.isClientSide || beltInventory.belt.isVirtual();
|
||||
boolean removed = false;
|
||||
BeltTunnelTileEntity nextTunnel = getTunnelOnSegment(beltInventory, upcomingSegment);
|
||||
int transferred = current.stack.getCount();
|
||||
|
||||
if (nextTunnel instanceof BrassTunnelTileEntity) {
|
||||
BrassTunnelTileEntity brassTunnel = (BrassTunnelTileEntity) nextTunnel;
|
||||
|
@ -82,7 +85,8 @@ public class BeltTunnelInteractionHandler {
|
|||
continue;
|
||||
|
||||
ItemStack toinsert = ItemHandlerHelper.copyStackWithSize(current.stack, 1);
|
||||
if (!behaviour.handleInsertion(toinsert, d, false).isEmpty())
|
||||
if (!behaviour.handleInsertion(toinsert, d, false)
|
||||
.isEmpty())
|
||||
return true;
|
||||
if (onServer)
|
||||
flapTunnel(beltInventory, upcomingSegment, d, false);
|
||||
|
@ -98,6 +102,10 @@ public class BeltTunnelInteractionHandler {
|
|||
if (onServer) {
|
||||
flapTunnel(beltInventory, currentSegment, movementFacing, false);
|
||||
flapTunnel(beltInventory, upcomingSegment, movementFacing.getOpposite(), true);
|
||||
|
||||
if (nextTunnel != null)
|
||||
DataGathererBlock.sendToGatherers(world, nextTunnel.getBlockPos(),
|
||||
(dgte, b) -> b.itemReceived(dgte, transferred), AccumulatedItemCountDataSource.class);
|
||||
}
|
||||
|
||||
if (removed)
|
||||
|
@ -140,7 +148,8 @@ public class BeltTunnelInteractionHandler {
|
|||
|
||||
public static BeltTunnelTileEntity getTunnelOnPosition(Level world, BlockPos pos) {
|
||||
pos = pos.above();
|
||||
if (!(world.getBlockState(pos).getBlock() instanceof BeltTunnelBlock))
|
||||
if (!(world.getBlockState(pos)
|
||||
.getBlock() instanceof BeltTunnelBlock))
|
||||
return null;
|
||||
BlockEntity te = world.getBlockEntity(pos);
|
||||
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.logistics.block.chute.AbstractChuteBlock;
|
||||
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.TrackShape;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
|
@ -203,6 +204,8 @@ public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenc
|
|||
state = state.setValue(updateProperty, true);
|
||||
else if (sideState.getBlock() instanceof NixieTubeBlock && NixieTubeBlock.getFacing(sideState) == d)
|
||||
state = state.setValue(updateProperty, true);
|
||||
else if (sideState.getBlock() instanceof FlapDisplayBlock)
|
||||
state = state.setValue(updateProperty, true);
|
||||
else if (isFacingBracket(level, pos, d))
|
||||
state = state.setValue(updateProperty, true);
|
||||
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);
|
||||
}
|
||||
|
||||
private static void drawOutline(BlockPos selection) {
|
||||
public static void drawOutline(BlockPos selection) {
|
||||
Level world = Minecraft.getInstance().level;
|
||||
if (currentSelection == null)
|
||||
if (selection == null)
|
||||
return;
|
||||
|
||||
BlockPos pos = currentSelection;
|
||||
BlockPos pos = selection;
|
||||
BlockState state = world.getBlockState(pos);
|
||||
VoxelShape shape = state.getShape(world, pos);
|
||||
AABB boundingBox = shape.isEmpty() ? new AABB(BlockPos.ZERO) : shape.bounds();
|
||||
|
|
|
@ -1,37 +1,64 @@
|
|||
package com.simibubi.create.content.logistics.block.diodes;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.foundation.block.ITE;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
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.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
|
||||
public class BrassDiodeBlock extends AbstractDiodeBlock implements ITE<BrassDiodeTileEntity> {
|
||||
|
||||
public static final BooleanProperty POWERING = BooleanProperty.create("powering");
|
||||
public static final BooleanProperty INVERTED = BooleanProperty.create("inverted");
|
||||
|
||||
public BrassDiodeBlock(Properties properties) {
|
||||
super(properties);
|
||||
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
|
||||
protected void createBlockStateDefinition(Builder<Block, BlockState> builder) {
|
||||
builder.add(POWERED, POWERING, FACING);
|
||||
builder.add(POWERED, POWERING, FACING, INVERTED);
|
||||
super.createBlockStateDefinition(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
|
|
|
@ -33,7 +33,7 @@ public class BrassDiodeGenerator extends AbstractDiodeGenerator {
|
|||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.simibubi.create.content.logistics.block.redstone;
|
|||
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
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.Direction;
|
||||
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;
|
||||
|
@ -78,7 +81,28 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock
|
|||
|
||||
if (!display && dye == null)
|
||||
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)
|
||||
.getOpposite();
|
||||
|
||||
|
@ -89,10 +113,6 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock
|
|||
|
||||
Direction right = left.getOpposite();
|
||||
|
||||
if (world.isClientSide)
|
||||
return InteractionResult.SUCCESS;
|
||||
|
||||
BlockPos currentPos = pos;
|
||||
while (true) {
|
||||
BlockPos nextPos = currentPos.relative(left);
|
||||
if (!areNixieBlocksEqual(world.getBlockState(nextPos), state))
|
||||
|
@ -104,20 +124,13 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock
|
|||
|
||||
while (true) {
|
||||
final int rowPosition = index;
|
||||
|
||||
if (display)
|
||||
withTileEntityDo(world, currentPos, te -> te.displayCustomNameOf(heldItem, rowPosition));
|
||||
if (dye != null)
|
||||
world.setBlockAndUpdate(currentPos, withColor(state, dye));
|
||||
|
||||
callback.accept(currentPos, rowPosition);
|
||||
BlockPos nextPos = currentPos.relative(right);
|
||||
if (!areNixieBlocksEqual(world.getBlockState(nextPos), state))
|
||||
break;
|
||||
currentPos = nextPos;
|
||||
index++;
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package com.simibubi.create.content.logistics.block.redstone;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
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.Color;
|
||||
import com.simibubi.create.foundation.utility.Couple;
|
||||
import com.simibubi.create.foundation.utility.DyeHelper;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -33,32 +32,7 @@ import net.minecraft.world.phys.Vec3;
|
|||
|
||||
public class NixieTubeRenderer extends SafeTileEntityRenderer<NixieTubeTileEntity> {
|
||||
|
||||
private 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();
|
||||
private static Random r = new Random();
|
||||
|
||||
public NixieTubeRenderer(BlockEntityRendererProvider.Context context) {}
|
||||
|
||||
|
@ -107,12 +81,12 @@ public class NixieTubeRenderer extends SafeTileEntityRenderer<NixieTubeTileEntit
|
|||
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;
|
||||
float charWidth = fontRenderer.width(c);
|
||||
float shadowOffset = .5f;
|
||||
float flicker = r.nextFloat();
|
||||
Couple<Integer> couple = DYE_TABLE.get(color);
|
||||
Couple<Integer> couple = DyeHelper.DYE_TABLE.get(color);
|
||||
int brightColor = couple.getFirst();
|
||||
int darkColor = couple.getSecond();
|
||||
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.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
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.block.data.DataGathererBlock;
|
||||
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.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
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.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.ComponentUtils;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
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.BlockEntityType;
|
||||
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 {
|
||||
|
||||
private static final Couple<String> EMPTY = Couple.create("", "");
|
||||
|
||||
private boolean hasCustomText;
|
||||
private int redstoneStrength;
|
||||
private JsonElement rawCustomText;
|
||||
private int customTextIndex;
|
||||
private Component parsedCustomText;
|
||||
private Optional<DynamicComponent> customText;
|
||||
private int nixieIndex;
|
||||
private Couple<String> displayedStrings;
|
||||
|
||||
private WeakReference<SignalTileEntity> cachedSignalTE;
|
||||
|
@ -49,7 +35,7 @@ public class NixieTubeTileEntity extends SmartTileEntity {
|
|||
|
||||
public NixieTubeTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
hasCustomText = false;
|
||||
customText = Optional.empty();
|
||||
redstoneStrength = 0;
|
||||
cachedSignalTE = new WeakReference<>(null);
|
||||
}
|
||||
|
@ -57,32 +43,23 @@ public class NixieTubeTileEntity extends SmartTileEntity {
|
|||
@Override
|
||||
public void 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();
|
||||
}
|
||||
signalState = null;
|
||||
SignalTileEntity signalTileEntity = cachedSignalTE.get();
|
||||
|
||||
if (level.isClientSide) {
|
||||
signalState = null;
|
||||
SignalTileEntity signalTileEntity = cachedSignalTE.get();
|
||||
|
||||
if (signalTileEntity == null || signalTileEntity.isRemoved()) {
|
||||
Direction facing = NixieTubeBlock.getFacing(getBlockState());
|
||||
BlockEntity blockEntity = level.getBlockEntity(worldPosition.relative(facing.getOpposite()));
|
||||
if (blockEntity instanceof SignalTileEntity signal) {
|
||||
signalState = signal.getState();
|
||||
cachedSignalTE = new WeakReference<>(signal);
|
||||
}
|
||||
return;
|
||||
if (signalTileEntity == null || signalTileEntity.isRemoved()) {
|
||||
Direction facing = NixieTubeBlock.getFacing(getBlockState());
|
||||
BlockEntity blockEntity = level.getBlockEntity(worldPosition.relative(facing.getOpposite()));
|
||||
if (blockEntity instanceof SignalTileEntity signal) {
|
||||
signalState = signal.getState();
|
||||
cachedSignalTE = new WeakReference<>(signal);
|
||||
}
|
||||
|
||||
signalState = signalTileEntity.getState();
|
||||
return;
|
||||
}
|
||||
|
||||
signalState = signalTileEntity.getState();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -94,7 +71,7 @@ public class NixieTubeTileEntity extends SmartTileEntity {
|
|||
//
|
||||
|
||||
public boolean reactsToRedstone() {
|
||||
return !hasCustomText;
|
||||
return customText.isEmpty();
|
||||
}
|
||||
|
||||
public Couple<String> getDisplayedStrings() {
|
||||
|
@ -103,40 +80,47 @@ public class NixieTubeTileEntity extends SmartTileEntity {
|
|||
return displayedStrings;
|
||||
}
|
||||
|
||||
public MutableComponent getFullText() {
|
||||
return customText.map(DynamicComponent::get)
|
||||
.orElse(new TextComponent("" + redstoneStrength));
|
||||
}
|
||||
|
||||
public void updateRedstoneStrength(int signalStrength) {
|
||||
clearCustomText();
|
||||
redstoneStrength = signalStrength;
|
||||
DataGathererBlock.notifyGatherers(level, worldPosition);
|
||||
notifyUpdate();
|
||||
}
|
||||
|
||||
public void displayCustomNameOf(ItemStack stack, int nixiePositionInRow) {
|
||||
CompoundTag compoundnbt = stack.getTagElement("display");
|
||||
if (compoundnbt != null && compoundnbt.contains("Name", Tag.TAG_STRING)) {
|
||||
hasCustomText = true;
|
||||
rawCustomText = getJsonFromString(compoundnbt.getString("Name"));
|
||||
customTextIndex = nixiePositionInRow;
|
||||
parsedCustomText = parseCustomText();
|
||||
notifyUpdate();
|
||||
}
|
||||
public void displayCustomText(String tagElement, int nixiePositionInRow) {
|
||||
if (tagElement == null)
|
||||
return;
|
||||
if (customText.filter(d -> d.sameAs(tagElement))
|
||||
.isPresent())
|
||||
return;
|
||||
|
||||
DynamicComponent component = customText.orElseGet(DynamicComponent::new);
|
||||
component.displayCustomText(level, worldPosition, tagElement);
|
||||
customText = Optional.of(component);
|
||||
nixieIndex = nixiePositionInRow;
|
||||
DataGathererBlock.notifyGatherers(level, worldPosition);
|
||||
notifyUpdate();
|
||||
}
|
||||
|
||||
public void updateDisplayedStrings() {
|
||||
if (signalState != null)
|
||||
return;
|
||||
if (!hasCustomText) {
|
||||
displayedStrings = Couple.create(redstoneStrength < 10 ? "0" : "1", String.valueOf(redstoneStrength % 10));
|
||||
} else {
|
||||
String fullText = parsedCustomText.getString();
|
||||
int index = customTextIndex * 2;
|
||||
displayedStrings = Couple.create(charOrEmpty(fullText, index), charOrEmpty(fullText, index + 1));
|
||||
}
|
||||
customText.map(DynamicComponent::resolve)
|
||||
.ifPresentOrElse(
|
||||
fullText -> displayedStrings =
|
||||
Couple.create(charOrEmpty(fullText, nixieIndex * 2), charOrEmpty(fullText, nixieIndex * 2 + 1)),
|
||||
() -> displayedStrings =
|
||||
Couple.create(redstoneStrength < 10 ? "0" : "1", String.valueOf(redstoneStrength % 10)));
|
||||
}
|
||||
|
||||
public void clearCustomText() {
|
||||
hasCustomText = false;
|
||||
rawCustomText = null;
|
||||
customTextIndex = 0;
|
||||
parsedCustomText = null;
|
||||
nixieIndex = 0;
|
||||
customText = Optional.empty();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -145,34 +129,21 @@ public class NixieTubeTileEntity extends SmartTileEntity {
|
|||
protected void read(CompoundTag nbt, boolean clientPacket) {
|
||||
super.read(nbt, clientPacket);
|
||||
|
||||
if (nbt.contains("RawCustomText", Tag.TAG_STRING)) {
|
||||
rawCustomText = getJsonFromString(nbt.getString("RawCustomText"));
|
||||
// Check if string forms valid JSON
|
||||
if (rawCustomText != null && !rawCustomText.isJsonNull()) {
|
||||
Component deserializedComponent = parseCustomText();
|
||||
// Check if JSON forms valid component
|
||||
if (deserializedComponent != null) {
|
||||
try {
|
||||
// Try to deserialize previously parsed component
|
||||
parsedCustomText = Component.Serializer.fromJson(nbt.getString("CustomText"));
|
||||
} catch (JsonParseException e) {
|
||||
//
|
||||
}
|
||||
if (parsedCustomText == null) {
|
||||
// Use test component to ensure field isn't null
|
||||
parsedCustomText = deserializedComponent;
|
||||
}
|
||||
hasCustomText = true;
|
||||
customTextIndex = nbt.getInt("CustomTextIndex");
|
||||
}
|
||||
if (nbt.contains("CustomText")) {
|
||||
DynamicComponent component = customText.orElseGet(DynamicComponent::new);
|
||||
component.read(level, worldPosition, nbt);
|
||||
|
||||
if (component.isValid()) {
|
||||
customText = Optional.of(component);
|
||||
nixieIndex = nbt.getInt("CustomTextIndex");
|
||||
} else {
|
||||
customText = Optional.empty();
|
||||
nixieIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasCustomText) {
|
||||
clearCustomText();
|
||||
if (customText.isEmpty())
|
||||
redstoneStrength = nbt.getInt("RedstoneStrength");
|
||||
}
|
||||
|
||||
if (clientPacket)
|
||||
updateDisplayedStrings();
|
||||
}
|
||||
|
@ -181,57 +152,18 @@ public class NixieTubeTileEntity extends SmartTileEntity {
|
|||
protected void write(CompoundTag nbt, boolean clientPacket) {
|
||||
super.write(nbt, clientPacket);
|
||||
|
||||
if (hasCustomText) {
|
||||
nbt.putString("RawCustomText", rawCustomText.toString());
|
||||
nbt.putInt("CustomTextIndex", customTextIndex);
|
||||
nbt.putString("CustomText", Component.Serializer.toJson(parsedCustomText));
|
||||
} else {
|
||||
if (customText.isPresent()) {
|
||||
nbt.putInt("CustomTextIndex", nixieIndex);
|
||||
customText.get()
|
||||
.write(nbt);
|
||||
} else
|
||||
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) {
|
||||
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
|
||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.simibubi.create.content.logistics.block.redstone;
|
|||
|
||||
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.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
||||
|
@ -145,8 +146,10 @@ public class StockpileSwitchTileEntity extends SmartTileEntity {
|
|||
if (update)
|
||||
scheduleBlockTick();
|
||||
|
||||
if (changed || update)
|
||||
sendData();
|
||||
if (changed || update) {
|
||||
DataGathererBlock.notifyGatherers(level, worldPosition);
|
||||
notifyUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
protected void scheduleBlockTick() {
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.simibubi.create.AllKeys;
|
|||
import com.simibubi.create.CreateClient;
|
||||
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.management.display.GlobalTrainDisplayData;
|
||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
|
||||
|
@ -91,6 +92,7 @@ public class GlobalRailwayManager {
|
|||
sync = new TrackGraphSync();
|
||||
movingTrains = new LinkedList<>();
|
||||
waitingTrains = new LinkedList<>();
|
||||
GlobalTrainDisplayData.statusByDestination.clear();
|
||||
}
|
||||
|
||||
public void markTracksDirty() {
|
||||
|
@ -167,15 +169,19 @@ public class GlobalRailwayManager {
|
|||
group.trains.clear();
|
||||
group.reserved = null;
|
||||
}
|
||||
|
||||
|
||||
for (TrackGraph graph : trackNetworks.values())
|
||||
graph.tickPoints(true);
|
||||
|
||||
tickTrains(level);
|
||||
|
||||
|
||||
for (TrackGraph graph : trackNetworks.values())
|
||||
graph.tickPoints(false);
|
||||
|
||||
GlobalTrainDisplayData.updateTick = level.getGameTime() % 100 == 0;
|
||||
if (GlobalTrainDisplayData.updateTick)
|
||||
GlobalTrainDisplayData.refresh();
|
||||
|
||||
// if (AllKeys.isKeyDown(GLFW.GLFW_KEY_K))
|
||||
// trackNetworks.values()
|
||||
// .forEach(TrackGraph::debugViewReserved);
|
||||
|
|
|
@ -50,6 +50,7 @@ public class Navigation {
|
|||
|
||||
public GlobalStation destination;
|
||||
public double distanceToDestination;
|
||||
public double distanceStartedAt;
|
||||
public boolean destinationBehindTrain;
|
||||
List<Couple<TrackNode>> currentPath;
|
||||
|
||||
|
@ -135,7 +136,8 @@ public class Navigation {
|
|||
MutableObject<Pair<UUID, Boolean>> trackingCrossSignal = new MutableObject<>(null);
|
||||
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(),
|
||||
(distance, couple) -> {
|
||||
// > scanDistance and not following down a cross signal
|
||||
|
@ -358,7 +360,7 @@ public class Navigation {
|
|||
distanceToDestination = distance;
|
||||
|
||||
if (noneFound) {
|
||||
distanceToDestination = 0;
|
||||
distanceToDestination = distanceStartedAt = 0;
|
||||
currentPath = new ArrayList<>();
|
||||
if (this.destination != null)
|
||||
cancelNavigation();
|
||||
|
@ -370,6 +372,9 @@ public class Navigation {
|
|||
train.reservedSignalBlocks.clear();
|
||||
train.navigation.waitingForSignal = null;
|
||||
|
||||
if (this.destination == null && !simulate)
|
||||
distanceStartedAt = distance;
|
||||
|
||||
if (this.destination == destination)
|
||||
return 0;
|
||||
|
||||
|
@ -677,6 +682,7 @@ public class Navigation {
|
|||
return tag;
|
||||
tag.putUUID("Destination", destination.id);
|
||||
tag.putDouble("DistanceToDestination", distanceToDestination);
|
||||
tag.putDouble("DistanceStartedAt", distanceStartedAt);
|
||||
tag.putBoolean("BehindTrain", destinationBehindTrain);
|
||||
tag.put("Path", NBTHelper.writeCompoundList(currentPath, c -> {
|
||||
CompoundTag nbt = new CompoundTag();
|
||||
|
@ -700,6 +706,7 @@ public class Navigation {
|
|||
if (destination == null)
|
||||
return;
|
||||
distanceToDestination = tag.getDouble("DistanceToDestination");
|
||||
distanceStartedAt = tag.getDouble("DistanceStartedAt");
|
||||
destinationBehindTrain = tag.getBoolean("BehindTrain");
|
||||
currentPath.clear();
|
||||
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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
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.station.GlobalStation;
|
||||
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.ScheduleDestination;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.config.CTrains;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
public class ScheduleRuntime {
|
||||
|
@ -34,6 +41,9 @@ public class ScheduleRuntime {
|
|||
List<Integer> conditionProgress;
|
||||
List<CompoundTag> conditionContext;
|
||||
|
||||
int ticksInTransit;
|
||||
List<Integer> predictionTicks;
|
||||
|
||||
public ScheduleRuntime(Train train) {
|
||||
this.train = train;
|
||||
reset();
|
||||
|
@ -44,6 +54,14 @@ public class ScheduleRuntime {
|
|||
return;
|
||||
state = State.POST_TRANSIT;
|
||||
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())
|
||||
return;
|
||||
List<List<ScheduleWaitCondition>> conditions = schedule.entries.get(currentEntry).conditions;
|
||||
|
@ -67,8 +85,10 @@ public class ScheduleRuntime {
|
|||
return;
|
||||
if (train.derailed)
|
||||
return;
|
||||
if (train.navigation.destination != null)
|
||||
if (train.navigation.destination != null) {
|
||||
ticksInTransit++;
|
||||
return;
|
||||
}
|
||||
if (currentEntry >= schedule.entries.size()) {
|
||||
currentEntry = 0;
|
||||
if (!schedule.cyclic)
|
||||
|
@ -97,8 +117,10 @@ public class ScheduleRuntime {
|
|||
destinationReached();
|
||||
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;
|
||||
ticksInTransit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void tickConditions(Level level) {
|
||||
|
@ -155,6 +177,8 @@ public class ScheduleRuntime {
|
|||
paused = false;
|
||||
isAutoSchedule = auto;
|
||||
train.status.newSchedule();
|
||||
predictionTicks = new ArrayList<>();
|
||||
schedule.entries.forEach($ -> predictionTicks.add(-1));
|
||||
}
|
||||
|
||||
public Schedule getSchedule() {
|
||||
|
@ -173,6 +197,121 @@ public class ScheduleRuntime {
|
|||
state = State.PRE_TRANSIT;
|
||||
conditionProgress = 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() {
|
||||
|
@ -185,6 +324,7 @@ public class ScheduleRuntime {
|
|||
NBTHelper.writeEnum(tag, "State", state);
|
||||
tag.putIntArray("ConditionProgress", conditionProgress);
|
||||
tag.put("ConditionContext", NBTHelper.writeCompoundList(conditionContext, CompoundTag::copy));
|
||||
tag.putIntArray("TransitTimes", predictionTicks);
|
||||
return tag;
|
||||
}
|
||||
|
||||
|
@ -199,6 +339,14 @@ public class ScheduleRuntime {
|
|||
for (int i : tag.getIntArray("ConditionProgress"))
|
||||
conditionProgress.add(i);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ public class ConnectedPillarBlock extends LayeredBlock {
|
|||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPlace(BlockState pState, Level pLevel, BlockPos pPos, BlockState pOldState, boolean pIsMoving) {
|
||||
if (pOldState.getBlock() == this)
|
||||
|
@ -87,14 +87,15 @@ public class ConnectedPillarBlock extends LayeredBlock {
|
|||
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(pState.getValue(AXIS), AxisDirection.NEGATIVE));
|
||||
BlockPos belowPos =
|
||||
pPos.relative(Direction.fromAxisAndDirection(pState.getValue(AXIS), AxisDirection.NEGATIVE));
|
||||
BlockState belowState = pLevel.getBlockState(belowPos);
|
||||
if (!canConnect(pState, belowState))
|
||||
if (!canConnect(pState, belowState))
|
||||
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.zapper.ZapperItem;
|
||||
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.mechanicalArm.ArmInteractionPointHandler;
|
||||
import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler;
|
||||
|
@ -156,6 +157,7 @@ public class ClientEvents {
|
|||
TrackPlacement.clientTick();
|
||||
TrackRemoval.clientTick();
|
||||
TrainRelocator.clientTick();
|
||||
DataGathererBlockItem.clientTick();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
|
@ -2,11 +2,13 @@ package com.simibubi.create.foundation.config;
|
|||
|
||||
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 psiTimeout = i(20, 1, "psiTimeout", Comments.psiTimeout);
|
||||
public final ConfigInt mechanicalArmRange = i(5, 1, "mechanicalArmRange", Comments.mechanicalArmRange);
|
||||
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);
|
||||
|
||||
@Override
|
||||
|
@ -20,6 +22,8 @@ public class CLogistics extends ConfigBase {
|
|||
static String defaultExtractionTimer =
|
||||
"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 dataGathererRange =
|
||||
"Maximum possible distance in blocks between data gatherers and their target.";
|
||||
static String psiTimeout =
|
||||
"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.";
|
||||
|
|
|
@ -59,7 +59,7 @@ public enum AllGuiTextures implements ScreenElement {
|
|||
TOOLBELT_MAIN_SLOT("widgets", 0, 97, 24, 24),
|
||||
TOOLBELT_EMPTY_SLOT("widgets", 27, 98, 22, 22),
|
||||
TOOLBELT_INACTIVE_SLOT("widgets", 52, 98, 22, 22),
|
||||
|
||||
|
||||
TOOLBELT_HOTBAR_OFF("widgets", 0, 130, 20, 24),
|
||||
TOOLBELT_HOTBAR_ON("widgets", 20, 130, 20, 24),
|
||||
TOOLBELT_SELECTED_OFF("widgets", 0, 155, 22, 22),
|
||||
|
@ -80,7 +80,12 @@ public enum AllGuiTextures implements ScreenElement {
|
|||
PROJECTOR_FILTER("projector", 0, 36, 162, 22),
|
||||
PROJECTOR_END("projector", 0, 58, 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_CARD_DARK("schedule", 5, 233, 1, 1),
|
||||
SCHEDULE_CARD_MEDIUM("schedule", 6, 233, 1, 1),
|
||||
|
@ -109,7 +114,7 @@ public enum AllGuiTextures implements ScreenElement {
|
|||
SCHEDULE_EDITOR_INACTIVE_SLOT("schedule_2", 0, 91, 18, 18),
|
||||
SCHEDULE_EDITOR_SECOND_LINE("schedule_2", 20, 91, 124, 18),
|
||||
SCHEDULE_EDITOR_DIVIDER("schedule_2", 145, 91, 4, 18),
|
||||
|
||||
|
||||
STATION("schedule_2", 0, 111, 200, 127),
|
||||
STATION_ASSEMBLING("assemble", 200, 178),
|
||||
STATION_TEXTBOX_TOP("assemble", 1, 179, 150, 18),
|
||||
|
|
|
@ -16,6 +16,8 @@ import net.minecraft.network.chat.TextComponent;
|
|||
|
||||
public abstract class AbstractSimiWidget extends AbstractWidget implements TickableGuiEventListener {
|
||||
|
||||
public static final int HEADER_RGB = 0x5391E1;
|
||||
|
||||
protected float z;
|
||||
protected boolean wasHovered = false;
|
||||
protected List<Component> toolTip = new LinkedList<>();
|
||||
|
|
|
@ -5,7 +5,6 @@ import javax.annotation.Nonnull;
|
|||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
import com.simibubi.create.foundation.gui.element.ScreenElement;
|
||||
|
||||
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 shiftScrollsFaster = Lang.translate("gui.scrollInput.shiftScrollsFaster");
|
||||
protected Label displayLabel;
|
||||
protected boolean inverted;
|
||||
|
||||
protected int min, max;
|
||||
protected int shiftStep;
|
||||
|
@ -37,6 +38,11 @@ public class ScrollInput extends AbstractSimiWidget {
|
|||
public Function<StepContext, Integer> standardStep() {
|
||||
return c -> c.shift ? shiftStep : 1;
|
||||
}
|
||||
|
||||
public ScrollInput inverted() {
|
||||
inverted = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScrollInput withRange(int min, int max) {
|
||||
this.min = min;
|
||||
|
@ -91,6 +97,9 @@ public class ScrollInput extends AbstractSimiWidget {
|
|||
|
||||
@Override
|
||||
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
|
||||
if (inverted)
|
||||
delta *= -1;
|
||||
|
||||
StepContext context = new StepContext();
|
||||
context.control = AllKeys.ctrlDown();
|
||||
context.shift = AllKeys.shiftDown();
|
||||
|
@ -134,7 +143,7 @@ public class ScrollInput extends AbstractSimiWidget {
|
|||
|
||||
protected void updateTooltip() {
|
||||
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(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) {
|
||||
super(xIn, yIn, widthIn, heightIn);
|
||||
options = new ArrayList<>();
|
||||
inverted();
|
||||
}
|
||||
|
||||
public ScrollInput forOptions(List<? extends Component> options) {
|
||||
|
@ -32,15 +33,11 @@ public class SelectionScrollInput extends ScrollInput {
|
|||
displayLabel.text = options.get(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
|
||||
return super.mouseScrolled(mouseX, mouseY, -delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateTooltip() {
|
||||
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 max = Math.max(this.min + 16, state + 8);
|
||||
min = Math.max(min, this.min);
|
||||
|
@ -53,14 +50,21 @@ public class SelectionScrollInput extends ScrollInput {
|
|||
max++;
|
||||
for (int i = min; i < max; i++) {
|
||||
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
|
||||
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)
|
||||
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.zapper.ZapperBeamPacket;
|
||||
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.EjectorPlacementPacket;
|
||||
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),
|
||||
CONTROLS_INPUT(ControlsInputPacket.class, ControlsInputPacket::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
|
||||
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.AllItems;
|
||||
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.relays.belt.BeltBlock;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
|
||||
|
@ -79,7 +79,8 @@ public class BeltScenes {
|
|||
scene.idle(7);
|
||||
|
||||
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.world.moveSection(shafts, util.vector.of(0, -2, 0), 0);
|
||||
|
@ -534,8 +535,9 @@ public class BeltScenes {
|
|||
scene.world.removeItemsFromBelt(depotPos);
|
||||
scene.world.hideSection(util.select.position(depotPos.above(2)), Direction.SOUTH);
|
||||
scene.idle(20);
|
||||
ElementLink<WorldSectionElement> spout = scene.world.showIndependentSection(util.select.position(depotPos.above(2)
|
||||
.west()), Direction.SOUTH);
|
||||
ElementLink<WorldSectionElement> spout =
|
||||
scene.world.showIndependentSection(util.select.position(depotPos.above(2)
|
||||
.west()), Direction.SOUTH);
|
||||
scene.world.moveSection(spout, util.vector.of(1, 0, 0), 0);
|
||||
|
||||
BlockPos pressPos = depotPos.above(2)
|
||||
|
@ -546,10 +548,11 @@ public class BeltScenes {
|
|||
scene.idle(10);
|
||||
|
||||
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.world.modifyTileEntity(pressPos, type,
|
||||
pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||
.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
||||
scene.world.removeItemsFromBelt(depotPos);
|
||||
ItemStack sheet = AllItems.COPPER_SHEET.asStack();
|
||||
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.mixer.MechanicalMixerTileEntity;
|
||||
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.BasinTileEntity;
|
||||
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
|
||||
|
@ -314,10 +314,11 @@ public class ProcessingScenes {
|
|||
scene.idle(10);
|
||||
|
||||
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.world.modifyTileEntity(pressPos, type,
|
||||
pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||
.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
||||
scene.world.removeItemsFromBelt(depotPos);
|
||||
ItemStack sheet = AllItems.COPPER_SHEET.asStack();
|
||||
scene.world.createItemOnBeltLike(depotPos, Direction.UP, sheet);
|
||||
|
@ -344,7 +345,8 @@ public class ProcessingScenes {
|
|||
ElementLink<BeltItemElement> ingot2 = scene.world.createItemOnBelt(beltPos, Direction.SOUTH, copper);
|
||||
scene.idle(15);
|
||||
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)
|
||||
.pointAt(pressSide)
|
||||
|
@ -353,8 +355,8 @@ public class ProcessingScenes {
|
|||
.text("The Press will hold and process them automatically");
|
||||
|
||||
scene.idle(30);
|
||||
scene.world.modifyTileEntity(pressPos, type,
|
||||
pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||
.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
||||
scene.world.removeItemsFromBelt(pressPos.below(2));
|
||||
ingot = scene.world.createItemOnBelt(pressPos.below(2), Direction.UP, sheet);
|
||||
scene.world.stallBeltItem(ingot, true);
|
||||
|
@ -362,10 +364,11 @@ public class ProcessingScenes {
|
|||
scene.world.stallBeltItem(ingot, false);
|
||||
scene.idle(15);
|
||||
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.world.modifyTileEntity(pressPos, type,
|
||||
pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||
.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper));
|
||||
scene.world.removeItemsFromBelt(pressPos.below(2));
|
||||
ingot2 = scene.world.createItemOnBelt(pressPos.below(2), Direction.UP, sheet);
|
||||
scene.world.stallBeltItem(ingot2, true);
|
||||
|
@ -492,10 +495,11 @@ public class ProcessingScenes {
|
|||
30);
|
||||
scene.idle(30);
|
||||
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.world.modifyTileEntity(pressPos, type,
|
||||
pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basin), copper));
|
||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||
.makeCompactingParticleEffect(util.vector.centerOf(basin), copper));
|
||||
scene.world.modifyTileNBT(util.select.position(basin), BasinTileEntity.class, nbt -> {
|
||||
nbt.put("VisualizedItems",
|
||||
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.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.world.modifyTileEntity(pressPos, type,
|
||||
pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basin), log));
|
||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||
.makeCompactingParticleEffect(util.vector.centerOf(basin), log));
|
||||
scene.world.modifyTileNBT(util.select.position(basin), BasinTileEntity.class, nbt -> {
|
||||
nbt.put("VisualizedItems",
|
||||
NBTHelper.writeCompoundList(ImmutableList.of(IntAttached.with(1, bark)), ia -> ia.getValue()
|
||||
|
@ -632,8 +637,8 @@ public class ProcessingScenes {
|
|||
.withItem(new ItemStack(Items.SOUL_SAND)),
|
||||
40);
|
||||
scene.idle(7);
|
||||
scene.world.modifyBlock(util.grid.at(3, 1, 2), s -> s.setValue(LitBlazeBurnerBlock.FLAME_TYPE, LitBlazeBurnerBlock.FlameType.SOUL),
|
||||
false);
|
||||
scene.world.modifyBlock(util.grid.at(3, 1, 2),
|
||||
s -> s.setValue(LitBlazeBurnerBlock.FLAME_TYPE, LitBlazeBurnerBlock.FlameType.SOUL), false);
|
||||
scene.overlay.showText(60)
|
||||
.text("The flame can be transformed using a soul-infused item")
|
||||
.pointAt(util.vector.blockSurface(center.east()
|
||||
|
@ -821,10 +826,11 @@ public class ProcessingScenes {
|
|||
scene.idle(10);
|
||||
|
||||
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.world.modifyTileEntity(pressPos, type,
|
||||
pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basinPos), stack));
|
||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||
.makeCompactingParticleEffect(util.vector.centerOf(basinPos), stack));
|
||||
scene.world.modifyTileNBT(util.select.position(basinPos), BasinTileEntity.class, nbt -> {
|
||||
nbt.put("VisualizedItems",
|
||||
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),
|
||||
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.world.modifyTileEntity(pressPos, type,
|
||||
pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basinPos), nugget));
|
||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||
.makeCompactingParticleEffect(util.vector.centerOf(basinPos), nugget));
|
||||
|
||||
ItemStack ingot = new ItemStack(Items.COPPER_INGOT);
|
||||
scene.idle(30);
|
||||
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basinPos), Pointing.RIGHT).withItem(ingot),
|
||||
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.world.modifyTileEntity(pressPos, type,
|
||||
pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basinPos), ingot));
|
||||
scene.world.modifyTileEntity(pressPos, type, pte -> pte.getPressingBehaviour()
|
||||
.makeCompactingParticleEffect(util.vector.centerOf(basinPos), ingot));
|
||||
|
||||
ItemStack block = new ItemStack(Items.COPPER_BLOCK);
|
||||
scene.idle(30);
|
||||
|
|
|
@ -28,8 +28,8 @@ public abstract class SmartTileEntity extends CachedRenderBBTileEntity implement
|
|||
private final Map<BehaviourType<?>, TileEntityBehaviour> behaviours = new HashMap<>();
|
||||
private boolean initialized = false;
|
||||
private boolean firstNbtRead = true;
|
||||
private int lazyTickRate;
|
||||
private int lazyTickCounter;
|
||||
protected int lazyTickRate;
|
||||
protected int lazyTickCounter;
|
||||
|
||||
// Used for simulating this TE in a client-only setting
|
||||
private boolean virtualMode;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue