Choo Choo, Part IV
- Trains now play a sound sequence based on attached blocks when arriving at a station after travelling for some time - Trains can now be stalled by movement behaviours of mounted blocks - Fixed bells constantly activating when mounted to a train - Max train length is now configurable and substantially longer
This commit is contained in:
parent
520983d5d0
commit
e281512787
38 changed files with 443 additions and 86 deletions
|
@ -544,22 +544,22 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
|
|||
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
|
||||
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
|
||||
875f9aff979888b9d63d6a425cbf544431f1af5a assets/create/lang/en_ud.json
|
||||
c8e4df6292133a1873e4dccb34c00b1e52afcd92 assets/create/lang/en_us.json
|
||||
3ca43c518fc5c0120b5cf2aaf37cc78f51625fd4 assets/create/lang/unfinished/de_de.json
|
||||
128d3e35cf2d41dacdb54abd8562091f15323a8c assets/create/lang/unfinished/es_cl.json
|
||||
f02d6b15275a22ac665303e6d7181998f408e1a7 assets/create/lang/unfinished/es_es.json
|
||||
02e43d3f9d2527c2cd72f1a5bfe76397b6cfa32f assets/create/lang/unfinished/fr_fr.json
|
||||
9f0982f15705f8c3f675f9dfac5b68a753ddf97a assets/create/lang/unfinished/it_it.json
|
||||
84d0f74256115e505a239ed826b28002fbc67f86 assets/create/lang/unfinished/ja_jp.json
|
||||
96dfb6f44098b2a44c4ba6c53ed6f42a4d7811f5 assets/create/lang/unfinished/ko_kr.json
|
||||
5ea64ddc9613b72376220353819a477bf4c6d64d assets/create/lang/unfinished/nl_nl.json
|
||||
dd81cd81f426833b627831530c77ab3f3655bb39 assets/create/lang/unfinished/pl_pl.json
|
||||
7cdff911043ccc6232932f85825090305ce92426 assets/create/lang/unfinished/pt_br.json
|
||||
ba139e8ea012ed05598ea5bb57ee6ac95693efdd assets/create/lang/unfinished/pt_pt.json
|
||||
86ac8dc000591768856bbaa873f9d101faddc1cd assets/create/lang/unfinished/ro_ro.json
|
||||
14988b8d3a0b97a7c6b49f392d5088fd59a3aaaa assets/create/lang/unfinished/ru_ru.json
|
||||
99ffa28fe67913dda825628947e5763f0a21ee8a assets/create/lang/unfinished/zh_cn.json
|
||||
01da3a96eb7aeea75afed38dd1a83321959fcf0a assets/create/lang/unfinished/zh_tw.json
|
||||
0a0155981901a175ef3d80376bd12bf6ed87fc40 assets/create/lang/en_us.json
|
||||
2441d72bd7c3f9bd175a3b7ad6dfd08650244333 assets/create/lang/unfinished/de_de.json
|
||||
c78d38ed11410f3749b0531faddb47bc864c602e assets/create/lang/unfinished/es_cl.json
|
||||
3f324c1793d15fc4efee2496ded04ef40a149eef assets/create/lang/unfinished/es_es.json
|
||||
a75c200cad527244a00e9c8d8044b99ebcb4f434 assets/create/lang/unfinished/fr_fr.json
|
||||
f8498450f21370fc25144fb02d7f3de644302eae assets/create/lang/unfinished/it_it.json
|
||||
fb99ffda9c4f753478d69d4a7e672d2934e4eefe assets/create/lang/unfinished/ja_jp.json
|
||||
c5b3a59940d9d1f31bd333acb05e77a07833f8f7 assets/create/lang/unfinished/ko_kr.json
|
||||
1a8e15b473cc565d4a0ce6a077ebb21b04436caa assets/create/lang/unfinished/nl_nl.json
|
||||
a4c4763232172a82d131bdcf9418e8944faa4767 assets/create/lang/unfinished/pl_pl.json
|
||||
4293a80519e12fe25df446daf66a2c93abde0c29 assets/create/lang/unfinished/pt_br.json
|
||||
40b6e4ba6fbdc90902288bbf0be9fd65a08d0bce assets/create/lang/unfinished/pt_pt.json
|
||||
e4a748bfbb60cb7b597921115ce69b45bbfb3d79 assets/create/lang/unfinished/ro_ro.json
|
||||
5539e89820b997b42e5605202e5c8ba508e80b77 assets/create/lang/unfinished/ru_ru.json
|
||||
b3f274b8dc40d041733ba10cab527c5130f68bcf assets/create/lang/unfinished/zh_cn.json
|
||||
5309ae6bd90efd2cf5e8adb730c2d2f4818edf7d 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
|
||||
|
@ -2155,7 +2155,7 @@ d080b1b25e5bc8baf5aee68691b08c7f12ece3b0 assets/create/models/item/windmill_bear
|
|||
866fbb0ce2878a73e0440d1caf6534c8bd7c384f assets/create/models/item/zinc_ingot.json
|
||||
a80fb25a0b655e76be986b5b49fcb0f03461a1ab assets/create/models/item/zinc_nugget.json
|
||||
b1689617190c05ef34bd18456b0c7ae09bb3210f assets/create/models/item/zinc_ore.json
|
||||
92c34840e05861f7f98aa2f942f9a90370f82cd6 assets/create/sounds.json
|
||||
56f5b100aa98b37efb44b85856ff4bfeaa7a89ec assets/create/sounds.json
|
||||
0f1b4b980afba9bf2caf583b88e261bba8b10313 data/create/advancements/aesthetics.json
|
||||
613e64b44bed959da899fdd54c1cacb227fb33f2 data/create/advancements/andesite_alloy.json
|
||||
81885c6bfb85792c88aaa7c9b70f58832945d31f data/create/advancements/andesite_casing.json
|
||||
|
|
|
@ -1591,7 +1591,10 @@
|
|||
"create.subtitle.potato_hit": "Vegetable impacts",
|
||||
"create.subtitle.saw_activate_wood": "Mechanical Saw activates",
|
||||
"create.subtitle.whistle_high": "High whistling",
|
||||
"create.subtitle.whistle_train": "Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "Haunted Bell awakens",
|
||||
"create.subtitle.whistle_train_high": "High whistling",
|
||||
"create.subtitle.whistle_train_low": "Low whistling",
|
||||
"create.subtitle.deny": "Declining boop",
|
||||
"create.subtitle.controller_click": "Controller clicks",
|
||||
"create.subtitle.whistle_low": "Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1534",
|
||||
"_": "Missing Localizations: 1537",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "UNLOCALIZED: Vegetable impacts",
|
||||
"create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "UNLOCALIZED: Haunted Bell awakens",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "UNLOCALIZED: Declining boop",
|
||||
"create.subtitle.controller_click": "UNLOCALIZED: Controller clicks",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 556",
|
||||
"_": "Missing Localizations: 559",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "Impactos vegetales",
|
||||
"create.subtitle.saw_activate_wood": "Sierra Mecánica se activa",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "Campana Embrujada despierta",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "Boop denegante",
|
||||
"create.subtitle.controller_click": "Controlador cliquea",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 227",
|
||||
"_": "Missing Localizations: 230",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "Impacto de vegetal",
|
||||
"create.subtitle.saw_activate_wood": "Sierra mecánica activada",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "Campana maldita se despierta",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "Pitido denegante",
|
||||
"create.subtitle.controller_click": "",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1796",
|
||||
"_": "Missing Localizations: 1799",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "UNLOCALIZED: Vegetable impacts",
|
||||
"create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "UNLOCALIZED: Haunted Bell awakens",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "UNLOCALIZED: Declining boop",
|
||||
"create.subtitle.controller_click": "UNLOCALIZED: Controller clicks",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1485",
|
||||
"_": "Missing Localizations: 1488",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "UNLOCALIZED: Vegetable impacts",
|
||||
"create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "UNLOCALIZED: Haunted Bell awakens",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "UNLOCALIZED: Declining boop",
|
||||
"create.subtitle.controller_click": "UNLOCALIZED: Controller clicks",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 222",
|
||||
"_": "Missing Localizations: 225",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "野菜の衝撃",
|
||||
"create.subtitle.saw_activate_wood": "メカニカルソーが動作する",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "憑りつかれた鐘が目覚める",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "失敗音",
|
||||
"create.subtitle.controller_click": "コントローラーのカチカチ音",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 222",
|
||||
"_": "Missing Localizations: 225",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "채소가 부딫힘",
|
||||
"create.subtitle.saw_activate_wood": "톱이 작동함",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "종에 귀신이 들림",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "취소음",
|
||||
"create.subtitle.controller_click": "조작기를 누름",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 2148",
|
||||
"_": "Missing Localizations: 2151",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "UNLOCALIZED: Vegetable impacts",
|
||||
"create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "UNLOCALIZED: Haunted Bell awakens",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "UNLOCALIZED: Declining boop",
|
||||
"create.subtitle.controller_click": "UNLOCALIZED: Controller clicks",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 595",
|
||||
"_": "Missing Localizations: 598",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "Warzywo ląduje",
|
||||
"create.subtitle.saw_activate_wood": "Mechaniczna piła aktywuje się",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "Nawiedzony dzwon budzi się",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "Dźwięk odmowy",
|
||||
"create.subtitle.controller_click": "Sterownik klika",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1396",
|
||||
"_": "Missing Localizations: 1399",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "UNLOCALIZED: Vegetable impacts",
|
||||
"create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "UNLOCALIZED: Haunted Bell awakens",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "UNLOCALIZED: Declining boop",
|
||||
"create.subtitle.controller_click": "UNLOCALIZED: Controller clicks",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1768",
|
||||
"_": "Missing Localizations: 1771",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "UNLOCALIZED: Vegetable impacts",
|
||||
"create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "UNLOCALIZED: Haunted Bell awakens",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "UNLOCALIZED: Declining boop",
|
||||
"create.subtitle.controller_click": "UNLOCALIZED: Controller clicks",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 223",
|
||||
"_": "Missing Localizations: 226",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "Impact de legumă",
|
||||
"create.subtitle.saw_activate_wood": "Ferăstrău Mecanic se activează",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "Clopot Bântuit se trezețte",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "Boop de refuz",
|
||||
"create.subtitle.controller_click": "Controlor clickuiește",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 600",
|
||||
"_": "Missing Localizations: 603",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "Овощ врезается",
|
||||
"create.subtitle.saw_activate_wood": "Активируется механическая пила",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "Призрачный колокол пробуждается",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "Отрицательный «Буп»",
|
||||
"create.subtitle.controller_click": "Клики контроллера",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 222",
|
||||
"_": "Missing Localizations: 225",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "土豆:击中",
|
||||
"create.subtitle.saw_activate_wood": "动力锯:切割",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "奇异钟:转化",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "提示声:出错",
|
||||
"create.subtitle.controller_click": "遥控器:按下按钮",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 614",
|
||||
"_": "Missing Localizations: 617",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -1592,7 +1592,10 @@
|
|||
"create.subtitle.potato_hit": "食物撞擊聲",
|
||||
"create.subtitle.saw_activate_wood": "機械鋸子運作聲",
|
||||
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
|
||||
"create.subtitle.haunted_bell_convert": "靈魂鐘轉化聲",
|
||||
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
|
||||
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
|
||||
"create.subtitle.deny": "UNLOCALIZED: Declining boop",
|
||||
"create.subtitle.controller_click": "遙控器按鍵聲",
|
||||
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
|
||||
|
|
|
@ -419,6 +419,33 @@
|
|||
],
|
||||
"subtitle": "create.subtitle.whistle_low"
|
||||
},
|
||||
"whistle_train": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "create:whistle_train",
|
||||
"type": "file"
|
||||
}
|
||||
],
|
||||
"subtitle": "create.subtitle.whistle_train"
|
||||
},
|
||||
"whistle_train_high": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "create:whistle_train_high",
|
||||
"type": "file"
|
||||
}
|
||||
],
|
||||
"subtitle": "create.subtitle.whistle_train_high"
|
||||
},
|
||||
"whistle_train_low": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "create:whistle_train_low",
|
||||
"type": "file"
|
||||
}
|
||||
],
|
||||
"subtitle": "create.subtitle.whistle_train_low"
|
||||
},
|
||||
"worldshaper_place": {
|
||||
"sounds": [
|
||||
{
|
||||
|
|
|
@ -228,7 +228,7 @@ public class AllSoundEvents {
|
|||
.attenuationDistance(64)
|
||||
.build(),
|
||||
|
||||
WHISTLE = create("whistle").subtitle("Whistling")
|
||||
WHISTLE_MEDIUM = create("whistle").subtitle("Whistling")
|
||||
.category(SoundSource.RECORDS)
|
||||
.attenuationDistance(64)
|
||||
.build(),
|
||||
|
@ -238,6 +238,18 @@ public class AllSoundEvents {
|
|||
.attenuationDistance(64)
|
||||
.build(),
|
||||
|
||||
WHISTLE_TRAIN_HIGH = create("whistle_train_high").subtitle("High whistling")
|
||||
.category(SoundSource.RECORDS)
|
||||
.build(),
|
||||
|
||||
WHISTLE_TRAIN_MEDIUM = create("whistle_train").subtitle("Whistling")
|
||||
.category(SoundSource.RECORDS)
|
||||
.build(),
|
||||
|
||||
WHISTLE_TRAIN_LOW = create("whistle_train_low").subtitle("Low whistling")
|
||||
.category(SoundSource.RECORDS)
|
||||
.build(),
|
||||
|
||||
WHISTLE_CHIFF = create("chiff").noSubtitle()
|
||||
.category(SoundSource.RECORDS)
|
||||
.build(),
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.components.actors;
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import com.simibubi.create.content.curiosities.bell.AbstractBellBlock;
|
||||
import com.simibubi.create.content.logistics.trains.entity.CarriageContraption;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
|
@ -17,6 +18,11 @@ public class BellMovementBehaviour implements MovementBehaviour {
|
|||
public boolean renderAsNormalTileEntity() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive(MovementContext context) {
|
||||
return !(context.contraption instanceof CarriageContraption);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSpeedChanged(MovementContext context, Vec3 oldMotion, Vec3 motion) {
|
||||
|
@ -28,7 +34,7 @@ public class BellMovementBehaviour implements MovementBehaviour {
|
|||
|
||||
@Override
|
||||
public void stopMoving(MovementContext context) {
|
||||
if (context.position != null)
|
||||
if (context.position != null && isActive(context))
|
||||
playSound(context);
|
||||
}
|
||||
|
||||
|
|
|
@ -83,8 +83,13 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
|
|||
.getNormal());
|
||||
facingVec = context.rotation.apply(facingVec);
|
||||
Vec3 vec = context.position.subtract(facingVec.scale(2));
|
||||
|
||||
float xRot = AbstractContraptionEntity.pitchFromVector(facingVec) - 90;
|
||||
if (Math.abs(xRot) > 89)
|
||||
facingVec = context.rotation.apply(new Vec3(0, 0, 1));
|
||||
|
||||
player.setYRot(AbstractContraptionEntity.yawFromVector(facingVec));
|
||||
player.setXRot(AbstractContraptionEntity.pitchFromVector(facingVec) - 90);
|
||||
player.setXRot(xRot);
|
||||
|
||||
DeployerHandler.activate(player, vec, pos, facingVec, mode);
|
||||
}
|
||||
|
@ -105,7 +110,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
|
|||
if (schematicWorld == null)
|
||||
return;
|
||||
if (!schematicWorld.getBounds()
|
||||
.isInside(pos.subtract(schematicWorld.anchor)))
|
||||
.isInside(pos.subtract(schematicWorld.anchor)))
|
||||
return;
|
||||
BlockState blockState = schematicWorld.getBlockState(pos);
|
||||
ItemRequirement requirement = ItemRequirement.of(blockState, schematicWorld.getBlockEntity(pos));
|
||||
|
@ -121,15 +126,15 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
|
|||
IItemHandler iItemHandler = context.contraption.inventory;
|
||||
for (ItemRequirement.StackRequirement required : requiredItems) {
|
||||
int amountFound = ItemHelper
|
||||
.extract(iItemHandler, s -> ItemRequirement.validate(required.item, s), ExtractionCountMode.UPTO,
|
||||
required.item.getCount(), true)
|
||||
.getCount();
|
||||
.extract(iItemHandler, s -> ItemRequirement.validate(required.item, s), ExtractionCountMode.UPTO,
|
||||
required.item.getCount(), true)
|
||||
.getCount();
|
||||
if (amountFound < required.item.getCount())
|
||||
return;
|
||||
}
|
||||
for (ItemRequirement.StackRequirement required : requiredItems)
|
||||
ItemHelper.extract(iItemHandler, s -> ItemRequirement.validate(required.item, s), ExtractionCountMode.UPTO,
|
||||
required.item.getCount(), false);
|
||||
ItemHelper.extract(iItemHandler, s -> ItemRequirement.validate(required.item, s),
|
||||
ExtractionCountMode.UPTO, required.item.getCount(), false);
|
||||
}
|
||||
|
||||
CompoundTag data = null;
|
||||
|
@ -183,7 +188,8 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
|
|||
if (player == null)
|
||||
return;
|
||||
|
||||
context.tileData.put("Inventory", player.getInventory().save(new ListTag()));
|
||||
context.tileData.put("Inventory", player.getInventory()
|
||||
.save(new ListTag()));
|
||||
player.discard();
|
||||
}
|
||||
|
||||
|
@ -215,8 +221,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
|
|||
if (itemstack.isEmpty())
|
||||
continue;
|
||||
|
||||
if (list == inv.items && i == inv.selected
|
||||
&& FilterItem.test(context.world, itemstack, filter))
|
||||
if (list == inv.items && i == inv.selected && FilterItem.test(context.world, itemstack, filter))
|
||||
continue;
|
||||
|
||||
dropItem(context, itemstack);
|
||||
|
@ -237,9 +242,11 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
|
|||
private DeployerFakePlayer getPlayer(MovementContext context) {
|
||||
if (!(context.temporaryData instanceof DeployerFakePlayer) && context.world instanceof ServerLevel) {
|
||||
DeployerFakePlayer deployerFakePlayer = new DeployerFakePlayer((ServerLevel) context.world);
|
||||
deployerFakePlayer.getInventory().load(context.tileData.getList("Inventory", Tag.TAG_COMPOUND));
|
||||
deployerFakePlayer.getInventory()
|
||||
.load(context.tileData.getList("Inventory", Tag.TAG_COMPOUND));
|
||||
if (context.data.contains("HeldItem"))
|
||||
deployerFakePlayer.setItemInHand(InteractionHand.MAIN_HAND, ItemStack.of(context.data.getCompound("HeldItem")));
|
||||
deployerFakePlayer.setItemInHand(InteractionHand.MAIN_HAND,
|
||||
ItemStack.of(context.data.getCompound("HeldItem")));
|
||||
context.tileData.remove("Inventory");
|
||||
context.temporaryData = deployerFakePlayer;
|
||||
}
|
||||
|
@ -257,7 +264,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
|
|||
@Override
|
||||
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
|
||||
ContraptionMatrices matrices, MultiBufferSource buffers) {
|
||||
if (!Backend.isOn())
|
||||
if (!Backend.isOn())
|
||||
DeployerRenderer.renderInContraption(context, renderWorld, matrices, buffers);
|
||||
}
|
||||
|
||||
|
@ -268,7 +275,8 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
|
|||
|
||||
@Nullable
|
||||
@Override
|
||||
public ActorInstance createInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld, MovementContext context) {
|
||||
public ActorInstance createInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld,
|
||||
MovementContext context) {
|
||||
return new DeployerActorInstance(materialManager, simulationWorld, context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.simibubi.create.content.contraptions.components.steam.whistle;
|
||||
|
||||
import static com.simibubi.create.AllSoundEvents.WHISTLE;
|
||||
import static com.simibubi.create.AllSoundEvents.WHISTLE_MEDIUM;
|
||||
import static com.simibubi.create.AllSoundEvents.WHISTLE_HIGH;
|
||||
import static com.simibubi.create.AllSoundEvents.WHISTLE_LOW;
|
||||
|
||||
|
@ -18,7 +18,7 @@ public class WhistleSoundInstance extends AbstractTickableSoundInstance {
|
|||
private WhistleSize size;
|
||||
|
||||
public WhistleSoundInstance(WhistleSize size, BlockPos worldPosition) {
|
||||
super((size == WhistleSize.SMALL ? WHISTLE_HIGH : size == WhistleSize.MEDIUM ? WHISTLE : WHISTLE_LOW)
|
||||
super((size == WhistleSize.SMALL ? WHISTLE_HIGH : size == WhistleSize.MEDIUM ? WHISTLE_MEDIUM : WHISTLE_LOW)
|
||||
.getMainEvent(), SoundSource.RECORDS);
|
||||
this.size = size;
|
||||
looping = true;
|
||||
|
|
|
@ -11,6 +11,8 @@ import com.simibubi.create.content.contraptions.components.actors.PloughBlock;
|
|||
import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceBlock;
|
||||
import com.simibubi.create.content.contraptions.components.crank.HandCrankBlock;
|
||||
import com.simibubi.create.content.contraptions.components.fan.NozzleBlock;
|
||||
import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock;
|
||||
import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleExtenderBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingTileEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock;
|
||||
|
@ -146,8 +148,7 @@ public class BlockMovementChecks {
|
|||
/**
|
||||
* Attached blocks will move if blocks they are attached to are moved
|
||||
*/
|
||||
public static boolean isBlockAttachedTowards(BlockState state, Level world, BlockPos pos,
|
||||
Direction direction) {
|
||||
public static boolean isBlockAttachedTowards(BlockState state, Level world, BlockPos pos, Direction direction) {
|
||||
for (AttachedCheck check : ATTACHED_CHECKS) {
|
||||
CheckResult result = check.isBlockAttachedTowards(state, world, pos, direction);
|
||||
if (result != CheckResult.PASS) {
|
||||
|
@ -179,10 +180,10 @@ public class BlockMovementChecks {
|
|||
if (state.getBlock() instanceof FenceGateBlock)
|
||||
return true;
|
||||
if (state.getMaterial()
|
||||
.isReplaceable())
|
||||
.isReplaceable())
|
||||
return false;
|
||||
if (state.getCollisionShape(world, pos)
|
||||
.isEmpty())
|
||||
.isEmpty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -258,11 +259,15 @@ public class BlockMovementChecks {
|
|||
return true;
|
||||
if (block instanceof WoolCarpetBlock)
|
||||
return true;
|
||||
if (block instanceof WhistleBlock)
|
||||
return true;
|
||||
if (block instanceof WhistleExtenderBlock)
|
||||
return true;
|
||||
return AllBlockTags.BRITTLE.matches(state);
|
||||
}
|
||||
|
||||
private static boolean isBlockAttachedTowardsFallback(BlockState state, Level world, BlockPos pos,
|
||||
Direction direction) {
|
||||
Direction direction) {
|
||||
Block block = state.getBlock();
|
||||
if (block instanceof LadderBlock)
|
||||
return state.getValue(LadderBlock.FACING) == direction.getOpposite();
|
||||
|
@ -331,18 +336,23 @@ public class BlockMovementChecks {
|
|||
}
|
||||
if (state.getBlock() instanceof SailBlock)
|
||||
return direction.getAxis() != state.getValue(SailBlock.FACING)
|
||||
.getAxis();
|
||||
.getAxis();
|
||||
if (state.getBlock() instanceof FluidTankBlock)
|
||||
return FluidTankConnectivityHandler.isConnected(world, pos, pos.relative(direction));
|
||||
if (state.getBlock() instanceof ItemVaultBlock)
|
||||
return ItemVaultConnectivityHandler.isConnected(world, pos, pos.relative(direction));
|
||||
if (AllBlocks.STICKER.has(state) && state.getValue(StickerBlock.EXTENDED)) {
|
||||
return direction == state.getValue(StickerBlock.FACING)
|
||||
&& !isNotSupportive(world.getBlockState(pos.relative(direction)), direction.getOpposite());
|
||||
&& !isNotSupportive(world.getBlockState(pos.relative(direction)), direction.getOpposite());
|
||||
}
|
||||
if (block instanceof IBogeyBlock bogey)
|
||||
return bogey.getStickySurfaces(world, pos, state)
|
||||
.contains(direction);
|
||||
if (block instanceof WhistleBlock)
|
||||
return direction == (state.getValue(WhistleBlock.WALL) ? state.getValue(WhistleBlock.FACING)
|
||||
: Direction.DOWN);
|
||||
if (block instanceof WhistleExtenderBlock)
|
||||
return direction == Direction.DOWN;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -355,7 +365,7 @@ public class BlockMovementChecks {
|
|||
return state.getValue(HarvesterBlock.FACING) == facing;
|
||||
if (AllBlocks.MECHANICAL_PLOUGH.has(state))
|
||||
return state.getValue(PloughBlock.FACING) == facing;
|
||||
|
||||
|
||||
if (AllBlocks.CART_ASSEMBLER.has(state))
|
||||
return Direction.DOWN == facing;
|
||||
if (AllBlocks.MECHANICAL_SAW.has(state))
|
||||
|
@ -373,10 +383,10 @@ public class BlockMovementChecks {
|
|||
.getAxis();
|
||||
if (AllBlocks.PISTON_EXTENSION_POLE.has(state))
|
||||
return facing.getAxis() != state.getValue(BlockStateProperties.FACING)
|
||||
.getAxis();
|
||||
.getAxis();
|
||||
if (AllBlocks.MECHANICAL_PISTON_HEAD.has(state))
|
||||
return facing.getAxis() != state.getValue(BlockStateProperties.FACING)
|
||||
.getAxis();
|
||||
.getAxis();
|
||||
if (AllBlocks.STICKER.has(state) && !state.getValue(StickerBlock.EXTENDED))
|
||||
return facing == state.getValue(StickerBlock.FACING);
|
||||
return isBrittle(state);
|
||||
|
@ -415,13 +425,12 @@ public class BlockMovementChecks {
|
|||
public CheckResult isNotSupportive(BlockState state, Direction direction);
|
||||
}
|
||||
|
||||
public static interface AllChecks extends MovementNecessaryCheck, MovementAllowedCheck, BrittleCheck, AttachedCheck, NotSupportiveCheck {
|
||||
public static interface AllChecks
|
||||
extends MovementNecessaryCheck, MovementAllowedCheck, BrittleCheck, AttachedCheck, NotSupportiveCheck {
|
||||
}
|
||||
|
||||
public static enum CheckResult {
|
||||
SUCCESS,
|
||||
FAIL,
|
||||
PASS;
|
||||
SUCCESS, FAIL, PASS;
|
||||
|
||||
public Boolean toBoolean() {
|
||||
return this == PASS ? null : (this == SUCCESS ? true : false);
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
package com.simibubi.create.content.logistics.trains.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock;
|
||||
import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock.WhistleSize;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.level.block.BellBlock;
|
||||
import net.minecraft.world.level.block.NoteBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
||||
|
||||
public class ArrivalSoundQueue {
|
||||
|
||||
public int offset;
|
||||
int min, max;
|
||||
Multimap<Integer, BlockPos> sources;
|
||||
|
||||
public ArrivalSoundQueue() {
|
||||
sources = Multimaps.newMultimap(new HashMap<>(), ArrayList::new);
|
||||
min = Integer.MAX_VALUE;
|
||||
max = Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer firstTick() {
|
||||
return sources.isEmpty() ? null : min + offset;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer lastTick() {
|
||||
return sources.isEmpty() ? null : max + offset;
|
||||
}
|
||||
|
||||
public boolean tick(CarriageContraptionEntity entity, int tick, boolean backwards) {
|
||||
tick = tick - offset;
|
||||
if (!sources.containsKey(tick))
|
||||
return backwards ? tick > min : tick < max;
|
||||
Contraption contraption = entity.getContraption();
|
||||
for (BlockPos blockPos : sources.get(tick))
|
||||
play(entity, contraption.getBlocks()
|
||||
.get(blockPos));
|
||||
return backwards ? tick > min : tick < max;
|
||||
}
|
||||
|
||||
public void serialize(CompoundTag tagIn) {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putInt("Offset", offset);
|
||||
tag.put("Sources", NBTHelper.writeCompoundList(sources.entries(), e -> {
|
||||
CompoundTag c = new CompoundTag();
|
||||
c.putInt("Tick", e.getKey());
|
||||
c.put("Pos", NbtUtils.writeBlockPos(e.getValue()));
|
||||
return c;
|
||||
}));
|
||||
tagIn.put("SoundQueue", tag);
|
||||
}
|
||||
|
||||
public void deserialize(CompoundTag tagIn) {
|
||||
CompoundTag tag = tagIn.getCompound("SoundQueue");
|
||||
offset = tag.getInt("Offset");
|
||||
NBTHelper.iterateCompoundList(tag.getList("Sources", Tag.TAG_COMPOUND),
|
||||
c -> add(c.getInt("Tick"), NbtUtils.readBlockPos(c.getCompound("Pos"))));
|
||||
}
|
||||
|
||||
public void add(int offset, BlockPos localPos) {
|
||||
sources.put(offset, localPos);
|
||||
min = Math.min(offset, min);
|
||||
max = Math.max(offset, max);
|
||||
}
|
||||
|
||||
public static boolean isPlayable(BlockState state) {
|
||||
if (state.getBlock() instanceof BellBlock)
|
||||
return true;
|
||||
if (state.getBlock() instanceof NoteBlock)
|
||||
return true;
|
||||
if (state.getBlock() instanceof WhistleBlock)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void play(CarriageContraptionEntity entity, StructureBlockInfo info) {
|
||||
if (info == null)
|
||||
return;
|
||||
BlockState state = info.state;
|
||||
|
||||
if (state.getBlock() instanceof BellBlock) {
|
||||
if (AllBlocks.HAUNTED_BELL.has(state))
|
||||
playSimple(entity, AllSoundEvents.HAUNTED_BELL_USE.getMainEvent(), 1, 1);
|
||||
else
|
||||
playSimple(entity, SoundEvents.BELL_BLOCK, 1, 1);
|
||||
}
|
||||
|
||||
if (state.getBlock()instanceof NoteBlock nb) {
|
||||
float f = (float) Math.pow(2, (state.getValue(NoteBlock.NOTE) - 12) / 12.0);
|
||||
playSimple(entity, state.getValue(NoteBlock.INSTRUMENT)
|
||||
.getSoundEvent(), 1, f);
|
||||
}
|
||||
|
||||
if (state.getBlock() instanceof WhistleBlock && info.nbt != null) {
|
||||
int pitch = info.nbt.getInt("Pitch");
|
||||
float f = (float) Math.pow(2, (pitch - 12) / 12.0);
|
||||
WhistleSize size = state.getValue(WhistleBlock.SIZE);
|
||||
playSimple(entity, (size == WhistleSize.LARGE ? AllSoundEvents.WHISTLE_TRAIN_LOW
|
||||
: size == WhistleSize.MEDIUM ? AllSoundEvents.WHISTLE_TRAIN_MEDIUM : AllSoundEvents.WHISTLE_TRAIN_HIGH)
|
||||
.getMainEvent(),
|
||||
1, f);
|
||||
playSimple(entity, AllSoundEvents.WHISTLE_CHIFF.getMainEvent(), .75f,
|
||||
size == WhistleSize.SMALL ? f + .75f : f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void playSimple(CarriageContraptionEntity entity, SoundEvent event, float volume, float pitch) {
|
||||
entity.level.playSound(null, entity, event, SoundSource.NEUTRAL, 5 * volume, pitch);
|
||||
}
|
||||
|
||||
}
|
|
@ -36,6 +36,7 @@ public class Carriage {
|
|||
public Train train;
|
||||
public int id;
|
||||
public boolean blocked;
|
||||
public boolean stalled;
|
||||
public Couple<Boolean> presentConductors;
|
||||
|
||||
public int bogeySpacing;
|
||||
|
@ -50,6 +51,7 @@ public class Carriage {
|
|||
// client
|
||||
public boolean pointsInitialised;
|
||||
|
||||
|
||||
static final int FIRST = 0, MIDDLE = 1, LAST = 2, BOTH = 3;
|
||||
|
||||
public Carriage(CarriageBogey bogey1, @Nullable CarriageBogey bogey2, int bogeySpacing) {
|
||||
|
@ -284,6 +286,7 @@ public class Carriage {
|
|||
tag.putInt("Spacing", bogeySpacing);
|
||||
tag.putBoolean("FrontConductor", presentConductors.getFirst());
|
||||
tag.putBoolean("BackConductor", presentConductors.getSecond());
|
||||
tag.putBoolean("Stalled", stalled);
|
||||
|
||||
CarriageContraptionEntity entity = this.entity.get();
|
||||
if (entity != null)
|
||||
|
@ -303,6 +306,7 @@ public class Carriage {
|
|||
|
||||
Carriage carriage = new Carriage(bogey1, bogey2, tag.getInt("Spacing"));
|
||||
|
||||
carriage.stalled = tag.getBoolean("Stalled");
|
||||
carriage.presentConductors = Couple.create(tag.getBoolean("FrontConductor"), tag.getBoolean("BackConductor"));
|
||||
carriage.serialisedEntity = tag.getCompound("Entity")
|
||||
.copy();
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.simibubi.create.foundation.utility.Couple;
|
|||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
|
@ -42,6 +43,7 @@ public class CarriageContraption extends Contraption {
|
|||
private boolean backwardControls;
|
||||
public Couple<Boolean> blazeBurnerConductors;
|
||||
public Map<BlockPos, Couple<Boolean>> conductorSeats;
|
||||
public ArrivalSoundQueue soundQueue;
|
||||
|
||||
// during assembly only
|
||||
private int bogeys;
|
||||
|
@ -53,6 +55,11 @@ public class CarriageContraption extends Contraption {
|
|||
conductorSeats = new HashMap<>();
|
||||
assembledBlazeBurners = new ArrayList<>();
|
||||
blazeBurnerConductors = Couple.create(false, false);
|
||||
soundQueue = new ArrivalSoundQueue();
|
||||
}
|
||||
|
||||
public void setSoundQueueOffset(int offset) {
|
||||
soundQueue.offset = offset;
|
||||
}
|
||||
|
||||
public CarriageContraption(Direction assemblyDirection) {
|
||||
|
@ -106,6 +113,13 @@ public class CarriageContraption extends Contraption {
|
|||
protected Pair<StructureBlockInfo, BlockEntity> capture(Level world, BlockPos pos) {
|
||||
BlockState blockState = world.getBlockState(pos);
|
||||
|
||||
if (ArrivalSoundQueue.isPlayable(blockState)) {
|
||||
int anchorCoord = VecHelper.getCoordinate(anchor, assemblyDirection.getAxis());
|
||||
int posCoord = VecHelper.getCoordinate(pos, assemblyDirection.getAxis());
|
||||
soundQueue.add((posCoord - anchorCoord) * assemblyDirection.getAxisDirection()
|
||||
.getStep(), toLocalPos(pos));
|
||||
}
|
||||
|
||||
if (blockState.getBlock() instanceof IBogeyBlock) {
|
||||
bogeys++;
|
||||
if (bogeys == 2)
|
||||
|
@ -151,6 +165,7 @@ public class CarriageContraption extends Contraption {
|
|||
return compoundTag;
|
||||
});
|
||||
tag.put("ConductorSeats", list);
|
||||
soundQueue.serialize(tag);
|
||||
return tag;
|
||||
}
|
||||
|
||||
|
@ -165,6 +180,7 @@ public class CarriageContraption extends Contraption {
|
|||
NBTHelper.iterateCompoundList(nbt.getList("ConductorSeats", Tag.TAG_COMPOUND),
|
||||
c -> conductorSeats.put(NbtUtils.readBlockPos(c.getCompound("Pos")),
|
||||
Couple.create(c.getBoolean("Forward"), c.getBoolean("Backward"))));
|
||||
soundQueue.deserialize(nbt);
|
||||
super.readNBT(world, nbt, spawnData);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,19 +2,18 @@ package com.simibubi.create.content.logistics.trains.entity;
|
|||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.jozufozu.flywheel.repack.joml.Math;
|
||||
import com.simibubi.create.AllEntityDataSerializers;
|
||||
import com.simibubi.create.AllEntityTypes;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock;
|
||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||
|
@ -65,10 +64,15 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
public boolean leftTickingChunks;
|
||||
public boolean firstPositionUpdate;
|
||||
|
||||
private boolean arrivalSoundPlaying;
|
||||
private boolean arrivalSoundReversed;
|
||||
private int arrivalSoundTicks;
|
||||
|
||||
public CarriageContraptionEntity(EntityType<?> type, Level world) {
|
||||
super(type, world);
|
||||
validForRender = false;
|
||||
firstPositionUpdate = true;
|
||||
arrivalSoundTicks = Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -167,15 +171,13 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
}
|
||||
|
||||
tickActors();
|
||||
contraption.stalled = false;
|
||||
for (MutablePair<StructureBlockInfo, MovementContext> pair : contraption.getActors()) {
|
||||
MovementContext context = pair.right;
|
||||
context.stall = false;
|
||||
}
|
||||
boolean isStalled = isStalled();
|
||||
carriage.stalled = isStalled;
|
||||
|
||||
CarriageSyncData carriageData = getCarriageData();
|
||||
|
||||
if (!level.isClientSide) {
|
||||
|
||||
entityData.set(SCHEDULED, carriage.train.runtime.getSchedule() != null);
|
||||
boolean shouldCarriageSyncThisTick =
|
||||
carriage.train.shouldCarriageSyncThisTick(level.getGameTime(), getType().updateInterval());
|
||||
|
@ -184,6 +186,18 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
entityData.set(CARRIAGE_DATA, carriageData);
|
||||
carriageData.setDirty(false);
|
||||
}
|
||||
|
||||
Navigation navigation = carriage.train.navigation;
|
||||
if (navigation.announceArrival && Math.abs(navigation.distanceToDestination) < 60
|
||||
&& carriageIndex == (carriage.train.speed < 0 ? carriage.train.carriages.size() - 1 : 0)) {
|
||||
navigation.announceArrival = false;
|
||||
arrivalSoundPlaying = true;
|
||||
arrivalSoundReversed = carriage.train.speed < 0;
|
||||
arrivalSoundTicks = Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
if (arrivalSoundPlaying)
|
||||
tickArrivalSound(cc);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -223,6 +237,59 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
validForRender = true;
|
||||
}
|
||||
|
||||
private void tickArrivalSound(CarriageContraption cc) {
|
||||
List<Carriage> carriages = carriage.train.carriages;
|
||||
|
||||
if (arrivalSoundTicks == Integer.MIN_VALUE) {
|
||||
int carriageCount = carriages.size();
|
||||
Integer tick = null;
|
||||
|
||||
for (int index = 0; index < carriageCount; index++) {
|
||||
int i = arrivalSoundReversed ? carriageCount - 1 - index : index;
|
||||
Carriage carriage = carriages.get(i);
|
||||
CarriageContraptionEntity entity = carriage.entity.get();
|
||||
if (entity == null || !(entity.contraption instanceof CarriageContraption otherCC))
|
||||
break;
|
||||
tick = arrivalSoundReversed ? otherCC.soundQueue.lastTick() : otherCC.soundQueue.firstTick();
|
||||
if (tick != null)
|
||||
break;
|
||||
}
|
||||
|
||||
if (tick == null) {
|
||||
arrivalSoundPlaying = false;
|
||||
return;
|
||||
}
|
||||
|
||||
arrivalSoundTicks = tick;
|
||||
}
|
||||
|
||||
if (tickCount % 2 == 0)
|
||||
return;
|
||||
|
||||
boolean keepTicking = false;
|
||||
for (Carriage c : carriages) {
|
||||
CarriageContraptionEntity entity = c.entity.get();
|
||||
if (entity == null || !(entity.contraption instanceof CarriageContraption otherCC))
|
||||
continue;
|
||||
keepTicking |= otherCC.soundQueue.tick(entity, arrivalSoundTicks, arrivalSoundReversed);
|
||||
}
|
||||
|
||||
if (!keepTicking) {
|
||||
arrivalSoundPlaying = false;
|
||||
return;
|
||||
}
|
||||
|
||||
arrivalSoundTicks += arrivalSoundReversed ? -1 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tickActors() {
|
||||
super.tickActors();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleStallInformation(float x, float y, float z, float angle) {}
|
||||
|
||||
Vec3 derailParticleOffset = VecHelper.offsetRandomly(Vec3.ZERO, Create.RANDOM, 1.5f)
|
||||
.multiply(1, .25f, 1);
|
||||
|
||||
|
@ -308,7 +375,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
train.navigation.waitingForSignal = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
if (carriage == null)
|
||||
|
|
|
@ -17,6 +17,7 @@ import javax.annotation.Nullable;
|
|||
import org.apache.commons.lang3.mutable.MutableDouble;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
|
||||
import com.jozufozu.flywheel.repack.joml.Math;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.logistics.trains.TrackEdge;
|
||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||
|
@ -52,6 +53,7 @@ public class Navigation {
|
|||
public double distanceToDestination;
|
||||
public double distanceStartedAt;
|
||||
public boolean destinationBehindTrain;
|
||||
public boolean announceArrival;
|
||||
List<Couple<TrackNode>> currentPath;
|
||||
|
||||
private TravellingPoint signalScout;
|
||||
|
@ -366,6 +368,9 @@ public class Navigation {
|
|||
cancelNavigation();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (Math.abs(distanceToDestination) > 100)
|
||||
announceArrival = true;
|
||||
|
||||
currentPath = pathTo.path;
|
||||
destinationBehindTrain = pathTo.distance < 0;
|
||||
|
@ -676,6 +681,7 @@ public class Navigation {
|
|||
tag.putDouble("DistanceToDestination", distanceToDestination);
|
||||
tag.putDouble("DistanceStartedAt", distanceStartedAt);
|
||||
tag.putBoolean("BehindTrain", destinationBehindTrain);
|
||||
tag.putBoolean("AnnounceArrival", announceArrival);
|
||||
tag.put("Path", NBTHelper.writeCompoundList(currentPath, c -> {
|
||||
CompoundTag nbt = new CompoundTag();
|
||||
nbt.put("Nodes", c.map(TrackNode::getLocation)
|
||||
|
@ -703,6 +709,7 @@ public class Navigation {
|
|||
distanceToDestination = tag.getDouble("DistanceToDestination");
|
||||
distanceStartedAt = tag.getDouble("DistanceStartedAt");
|
||||
destinationBehindTrain = tag.getBoolean("BehindTrain");
|
||||
announceArrival = tag.getBoolean("AnnounceArrival");
|
||||
currentPath.clear();
|
||||
NBTHelper.iterateCompoundList(tag.getList("Path", Tag.TAG_COMPOUND),
|
||||
c -> currentPath.add(Couple
|
||||
|
|
|
@ -181,6 +181,10 @@ public class Train {
|
|||
stress[i - 1] = target - actual;
|
||||
}
|
||||
previousCarriage = carriage;
|
||||
if (carriage.stalled) {
|
||||
distance = 0;
|
||||
speed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// positive stress: carriages should move apart
|
||||
|
@ -532,7 +536,6 @@ public class Train {
|
|||
navigation.cancelNavigation();
|
||||
forEachTravellingPoint(tp -> migratingPoints.add(new TrainMigration(tp)));
|
||||
graph = null;
|
||||
syncTrackGraphChanges();
|
||||
}
|
||||
|
||||
public void forEachTravellingPoint(Consumer<TravellingPoint> callback) {
|
||||
|
@ -613,14 +616,13 @@ public class Train {
|
|||
if (derailed)
|
||||
status.successfulMigration();
|
||||
derailed = false;
|
||||
if (runtime.getSchedule() != null) {
|
||||
if (runtime.state == State.IN_TRANSIT)
|
||||
runtime.state = State.PRE_TRANSIT;
|
||||
}
|
||||
if (runtime.getSchedule() != null && runtime.state == State.IN_TRANSIT)
|
||||
runtime.state = State.PRE_TRANSIT;
|
||||
GlobalStation currentStation = getCurrentStation();
|
||||
if (currentStation != null)
|
||||
currentStation.reserveFor(this);
|
||||
updateSignalBlocks = true;
|
||||
migrationCooldown = 0;
|
||||
syncTrackGraphChanges();
|
||||
return;
|
||||
}
|
||||
|
@ -722,7 +724,7 @@ public class Train {
|
|||
while (current != null) {
|
||||
prev = current;
|
||||
d = current.getLocationOn(edge);
|
||||
current = signalData.next(EdgePointType.SIGNAL, d);
|
||||
current = signalData.next(EdgePointType.SIGNAL, d);
|
||||
}
|
||||
if (prev != null) {
|
||||
UUID group = prev.getGroup(node2);
|
||||
|
|
|
@ -65,6 +65,7 @@ public abstract class AbstractStationScreen extends AbstractSimiScreen {
|
|||
Carriage carriage = carriages.get(i);
|
||||
w += icon.getIconWidth(carriage.bogeySpacing) + 1;
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
|
|
|
@ -153,7 +153,10 @@ public class AssemblyScreen extends AbstractStationScreen {
|
|||
|
||||
TrainIconType icon = train.icon;
|
||||
int offset = 0;
|
||||
int position = background.width / 2 - getTrainIconWidth(train) / 2;
|
||||
int trainIconWidth = getTrainIconWidth(train);
|
||||
int position = background.width / 2 - trainIconWidth / 2;
|
||||
if (trainIconWidth > 130)
|
||||
position -= trainIconWidth - 130;
|
||||
boolean frontConductor = false;
|
||||
boolean backConductor = false;
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ public class StationScreen extends AbstractStationScreen {
|
|||
.length());
|
||||
trainNameBox.setHighlightPos(trainNameBox.getCursorPosition());
|
||||
}
|
||||
|
||||
|
||||
super.tick();
|
||||
|
||||
updateAssemblyTooltip(te.edgePoint.isOnCurve() ? "no_assembly_curve"
|
||||
|
@ -154,6 +154,8 @@ public class StationScreen extends AbstractStationScreen {
|
|||
|
||||
int trainIconWidth = getTrainIconWidth(imminentTrain);
|
||||
int targetPos = background.width / 2 - trainIconWidth / 2;
|
||||
if (trainIconWidth > 130)
|
||||
targetPos -= trainIconWidth - 130;
|
||||
float f = (float) (imminentTrain.navigation.distanceToDestination / 15f);
|
||||
if (trainPresent())
|
||||
f = 0;
|
||||
|
@ -164,6 +166,8 @@ public class StationScreen extends AbstractStationScreen {
|
|||
|
||||
int trainIconWidth = getTrainIconWidth(train);
|
||||
int targetPos = background.width / 2 - trainIconWidth / 2;
|
||||
if (trainIconWidth > 130)
|
||||
targetPos -= trainIconWidth - 130;
|
||||
|
||||
if (leavingAnimation > 0) {
|
||||
disassembleTrainButton.active = false;
|
||||
|
|
|
@ -33,6 +33,7 @@ import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePoi
|
|||
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleItem;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
|
@ -311,8 +312,8 @@ public class StationTileEntity extends SmartTileEntity {
|
|||
|
||||
BlockPos bogeyOffset = new BlockPos(track.getUpNormal(level, targetPosition, trackState));
|
||||
|
||||
int MAX_LENGTH = 48;
|
||||
int MAX_BOGEY_COUNT = 20;
|
||||
int MAX_LENGTH = AllConfigs.SERVER.trains.maxAssemblyLength.get();
|
||||
int MAX_BOGEY_COUNT = AllConfigs.SERVER.trains.maxBogeyCount.get();
|
||||
|
||||
int bogeyIndex = 0;
|
||||
int maxBogeyCount = MAX_BOGEY_COUNT;
|
||||
|
@ -324,10 +325,14 @@ public class StationTileEntity extends SmartTileEntity {
|
|||
Arrays.fill(bogeyTypes, null);
|
||||
|
||||
for (int i = 0; i < MAX_LENGTH; i++) {
|
||||
if (i == MAX_LENGTH - 1 || !track.trackEquals(trackState, level.getBlockState(currentPos))) {
|
||||
if (i == MAX_LENGTH - 1) {
|
||||
assemblyLength = i;
|
||||
break;
|
||||
}
|
||||
if (!track.trackEquals(trackState, level.getBlockState(currentPos))) {
|
||||
assemblyLength = Math.max(0, i - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
BlockState potentialBogeyState = level.getBlockState(bogeyOffset.offset(currentPos));
|
||||
if (potentialBogeyState.getBlock()instanceof IBogeyBlock bogey && bogeyIndex < bogeyLocations.length) {
|
||||
|
@ -510,9 +515,10 @@ public class StationTileEntity extends SmartTileEntity {
|
|||
BlockPos bogeyPosOffset = trackPosition.offset(bogeyOffset);
|
||||
|
||||
try {
|
||||
boolean success = contraption.assemble(level,
|
||||
bogeyPosOffset.relative(assemblyDirection, bogeyLocations[bogeyIndex] + 1));
|
||||
int offset = bogeyLocations[bogeyIndex] + 1;
|
||||
boolean success = contraption.assemble(level, bogeyPosOffset.relative(assemblyDirection, offset));
|
||||
atLeastOneForwardControls |= contraption.hasForwardControls();
|
||||
contraption.setSoundQueueOffset(offset);
|
||||
if (!success) {
|
||||
exception(new AssemblyException(Lang.translate("train_assembly.nothing_attached", bogeyIndex + 1)),
|
||||
-1);
|
||||
|
|
|
@ -7,6 +7,8 @@ public class CTrains extends ConfigBase {
|
|||
public final ConfigFloat trainTurningTopSpeed =
|
||||
f(18, 0, "trainTurningTopSpeed", Comments.mps, Comments.trainTurningTopSpeed);
|
||||
public final ConfigFloat trainAcceleration = f(4, 0, "trainAcceleration", Comments.acc, Comments.trainAcceleration);
|
||||
public final ConfigInt maxAssemblyLength = i(128, 5, "maxAssemblyLength", Comments.maxAssemblyLength);
|
||||
public final ConfigInt maxBogeyCount = i(20, 1, "maxBogeyCount", Comments.maxBogeyCount);
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
|
@ -32,6 +34,8 @@ public class CTrains extends ConfigBase {
|
|||
static String trainTurningTopSpeed = "The top speed of Trains during a turn.";
|
||||
static String trainAcceleration = "The acceleration of any assembled Train.";
|
||||
static String trainsCauseDamage = "Whether moving Trains can hurt colliding mobs and players.";
|
||||
static String maxAssemblyLength = "Maximum length of a Train Stations' assembly track.";
|
||||
static String maxBogeyCount = "Maximum amount of bogeys assembled as a single Train.";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Binary file not shown.
BIN
src/main/resources/assets/create/sounds/whistle_train.ogg
Normal file
BIN
src/main/resources/assets/create/sounds/whistle_train.ogg
Normal file
Binary file not shown.
BIN
src/main/resources/assets/create/sounds/whistle_train_high.ogg
Normal file
BIN
src/main/resources/assets/create/sounds/whistle_train_high.ogg
Normal file
Binary file not shown.
BIN
src/main/resources/assets/create/sounds/whistle_train_low.ogg
Normal file
BIN
src/main/resources/assets/create/sounds/whistle_train_low.ogg
Normal file
Binary file not shown.
Loading…
Reference in a new issue