From 367296e6c1ba673deb06339fe80bc6b4e7c6d816 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Fri, 10 Jul 2020 19:48:04 +0200 Subject: [PATCH] Logistical enhancements and fixes - Arms can no longer insert into powered brass funnels - Slight ArmInteractionPoint refactor - Arms can now interact with Millstones, Basins, Jukeboxes, Crushing Wheels and the Mechanical Saw - Fixed crash when logging into a world with a running mixer - Arms now start to dance when one of their in or outputs is a running jukebox - Arms can now be mounted on the ceiling - Arms now always prefer the interaction points that were selected first - Fixed belt funnels not updating their blockstate properly when transitioning from other funnel types - Vertical funnels next to the end of a belt will now stall the belt when unable to collect incoming items - Minor model & texture touch ups - Arm no longer cancels player interaction when its empty handed - Fixed chutes not vertically interacting with andesite funnels --- src/generated/resources/.cache/cache | 24 +-- .../create/blockstates/mechanical_arm.json | 6 +- .../resources/assets/create/lang/en_us.json | 4 + .../assets/create/lang/unfinished/de_de.json | 6 +- .../assets/create/lang/unfinished/fr_fr.json | 6 +- .../assets/create/lang/unfinished/it_it.json | 6 +- .../assets/create/lang/unfinished/ja_jp.json | 6 +- .../assets/create/lang/unfinished/ko_kr.json | 6 +- .../assets/create/lang/unfinished/nl_nl.json | 6 +- .../assets/create/lang/unfinished/pt_br.json | 6 +- .../assets/create/lang/unfinished/ru_ru.json | 6 +- .../assets/create/lang/unfinished/zh_cn.json | 6 +- .../create/advancements/mechanical_arm.json | 46 +++++ .../data/create/advancements/musical_arm.json | 46 +++++ .../java/com/simibubi/create/AllBlocks.java | 6 +- .../java/com/simibubi/create/AllShapes.java | 2 + .../mixer/MechanicalMixerTileEntity.java | 11 +- .../fluids/CombinedFluidHandler.java | 12 +- .../block/chute/ChuteTileEntity.java | 10 +- .../block/funnel/AndesiteFunnelBlock.java | 8 +- .../block/funnel/BeltFunnelBlock.java | 15 +- .../block/funnel/BrassFunnelBlock.java | 5 +- .../logistics/block/funnel/FunnelBlock.java | 16 +- .../logistics/block/funnel/FunnelItem.java | 8 +- .../block/funnel/FunnelTileEntity.java | 19 ++ .../HorizontalInteractionFunnelBlock.java | 9 +- .../inventories/CreativeCrateInventory.java | 2 +- .../block/mechanicalArm/ArmAngleTarget.java | 19 +- .../block/mechanicalArm/ArmBlock.java | 33 +++- .../mechanicalArm/ArmInteractionPoint.java | 173 +++++++++++++++--- .../ArmInteractionPointHandler.java | 59 ++++-- .../block/mechanicalArm/ArmItem.java | 9 +- .../block/mechanicalArm/ArmRenderer.java | 30 ++- .../block/mechanicalArm/ArmTileEntity.java | 52 +++++- .../advancement/AllAdvancements.java | 25 ++- .../foundation/advancement/AllTriggers.java | 2 + .../create/lang/default/advancements.json | 4 + .../create/models/block/funnel/block.json | 4 +- .../textures/block/andesite_funnel_back.png | Bin 978 -> 984 bytes .../block/andesite_funnel_plating.png | Bin 1403 -> 1432 bytes .../create/textures/block/andesite_tunnel.png | Bin 2571 -> 2567 bytes .../textures/block/andesite_tunnel_top.png | Bin 297 -> 297 bytes .../textures/block/brass_funnel_back.png | Bin 948 -> 952 bytes .../textures/block/brass_funnel_plating.png | Bin 1580 -> 1564 bytes 44 files changed, 574 insertions(+), 139 deletions(-) create mode 100644 src/generated/resources/data/create/advancements/mechanical_arm.json create mode 100644 src/generated/resources/data/create/advancements/musical_arm.json diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 91511dbdb..9b2149026 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -179,7 +179,7 @@ b7506b862d13b3f915c60d38bb7a20afc935f70a assets\create\blockstates\limestone_pil 69790737767e06f000c7824749c46664a123160e assets\create\blockstates\linear_chassis.json c793ab3aa6cf09d8d6d4136757629689f0365771 assets\create\blockstates\linked_extractor.json c5422866667331f1d5cf6753c0889747ee02762b assets\create\blockstates\linked_transposer.json -e82e69ae4c7a784ef89fc5d954b2b01946746d48 assets\create\blockstates\mechanical_arm.json +3b3250d6e209403a93d025604a8081087965016e assets\create\blockstates\mechanical_arm.json ddcf4bb281e046fbb1026b8f46a2cf12448598df assets\create\blockstates\mechanical_bearing.json 5586beef2d9183dc34d8e8d2723620c0569592ae assets\create\blockstates\mechanical_crafter.json 044db7d50e19008bae8bf3325eac2ed0eb1ea6d2 assets\create\blockstates\mechanical_drill.json @@ -338,16 +338,16 @@ c77b46d8b459e5c7cc495393546f3fcca8a1fa1d assets\create\blockstates\weathered_lim 7f39521b211441f5c3e06d60c5978cebe16cacfb assets\create\blockstates\zinc_block.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets\create\blockstates\zinc_ore.json 541831ab0cf2f0222f0b7e42ec6c4b0ae636168d assets\create\lang\en_ud.json -fe44adfde38a1084754fe46b632811f90dcfcd7f assets\create\lang\en_us.json -143b76ed828949330ef0e338fb6709c28561ac2d assets\create\lang\unfinished\de_de.json -95bf7693b162141c2c76617ed4e04bec474e2def assets\create\lang\unfinished\fr_fr.json -b3bf60afc7d0dea72a9d7d01df36d34affd6a296 assets\create\lang\unfinished\it_it.json -ef336e01a8e3ed3f8c2713c66476bcc708e3e3b0 assets\create\lang\unfinished\ja_jp.json -66c84c388e552ee8259eca2ab1009493456fc4d3 assets\create\lang\unfinished\ko_kr.json -66b3140ef158b51208a191e6a90473fba5bb1749 assets\create\lang\unfinished\nl_nl.json -775702e0f3fbdab7ef8b1714e3cff69da56bd500 assets\create\lang\unfinished\pt_br.json -7c4c4e7a00456f893538a6baa35d726a8786bf93 assets\create\lang\unfinished\ru_ru.json -ce16074d9dc5d504f2a91b164258f0059163260b assets\create\lang\unfinished\zh_cn.json +fd57d2d8144286e26033a087a501f45f2df9ea34 assets\create\lang\en_us.json +87c28254c2acb462fe6a994f688a19e31a4c7a9d assets\create\lang\unfinished\de_de.json +6cd93a72126063c634f49db190d4da545e5a6c43 assets\create\lang\unfinished\fr_fr.json +401d0b295988cfa31af1a94f8c50d86eb54cad0d assets\create\lang\unfinished\it_it.json +30f1189e1963d0a87a9505bfdac9b663ff9d09d1 assets\create\lang\unfinished\ja_jp.json +a56d5b51d410821b7993bdbfd1b141e51be11b54 assets\create\lang\unfinished\ko_kr.json +e8a39cb4afc7668f2690bcacda1f06afd9c82579 assets\create\lang\unfinished\nl_nl.json +3876e40fbc9c6e8561cc761949a6fb9565a03fce assets\create\lang\unfinished\pt_br.json +cc2c01ee69a5a394c9d6dc87f77e08f05adf38a7 assets\create\lang\unfinished\ru_ru.json +7a8b2739021d2e1d2b563f2bed3a201bd3f1b00f assets\create\lang\unfinished\zh_cn.json 846200eb548d3bfa2e77b41039de159b4b6cfb45 assets\create\models\block\acacia_window.json 1930fa3a3c98d53dd19e4ee7f55bc27fd47aa281 assets\create\models\block\acacia_window_pane_noside.json 1763ea2c9b981d187f5031ba608f3d5d3be3986a assets\create\models\block\acacia_window_pane_noside_alt.json @@ -1365,10 +1365,12 @@ e4e3c1bd7ecf501b40cffc26d8ad145ab4e89118 data\create\advancements\deployer.json 62f3610188f7dbd3900ab305edc2d06282705a38 data\create\advancements\goggles.json 7e12b7ccb198ef0db7964b8cbef152d8347e333c data\create\advancements\its_alive.json 3d0fc63191ef507a018ef996ebf9406a523f3976 data\create\advancements\lava_wheel.json +90393cdb6b699c9c0fd4dd9400159c3aa6911a6b data\create\advancements\mechanical_arm.json 786c2058805ceca3cd3970cc6e918560b54747f5 data\create\advancements\mechanical_drill.json 41444ae151ce90d2d68dcda0ed3565f98509c594 data\create\advancements\mechanical_saw.json 9c7f0c2484a84ccf42166704475fafcb1f232ce6 data\create\advancements\millstone.json 704c7fc0ed357b1a116ffdc0b6c64fe64e337a5a data\create\advancements\mixer.json +8085b46ca0dd8c511841cabd88e51bff4baceefd data\create\advancements\musical_arm.json a135eec618e448f440d9f42cc7a3e6c63fc45a71 data\create\advancements\overstressed.json 72025d8bf73ab8096c29f12d0c8d9a346f09cd64 data\create\advancements\polished_rose_quartz.json 1e3cd82e36fd4bcd053d652a0eead4458ed7f315 data\create\advancements\press.json diff --git a/src/generated/resources/assets/create/blockstates/mechanical_arm.json b/src/generated/resources/assets/create/blockstates/mechanical_arm.json index c4754cb1a..b283c0432 100644 --- a/src/generated/resources/assets/create/blockstates/mechanical_arm.json +++ b/src/generated/resources/assets/create/blockstates/mechanical_arm.json @@ -1,7 +1,11 @@ { "variants": { - "": { + "ceiling=false": { "model": "create:block/mechanical_arm/block" + }, + "ceiling=true": { + "model": "create:block/mechanical_arm/block", + "x": 180 } } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 5e18d7883..5b5379ff7 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -457,6 +457,10 @@ "advancement.create.crafter.desc": "Place and power some Mechanical Crafters", "advancement.create.deployer": "Poke, Place, and Attack", "advancement.create.deployer.desc": "Place and power a Deployer, the perfect reflection of yourself.", + "advancement.create.mechanical_arm": "Mechanical Grab'n'Drop", + "advancement.create.mechanical_arm.desc": "Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch it do all the work for you.", + "advancement.create.musical_arm": "Play me my Theme Tune!", + "advancement.create.musical_arm.desc": "Watch a Mechanical Arm operate your Jukebox.", "advancement.create.fist_bump": "Pound It, Bro!", "advancement.create.fist_bump.desc": "Make two Deployers fist-bump.", "advancement.create.crushing_wheel": "A Pair of Giants", diff --git a/src/generated/resources/assets/create/lang/unfinished/de_de.json b/src/generated/resources/assets/create/lang/unfinished/de_de.json index 0b7f7b251..9a8c82e36 100644 --- a/src/generated/resources/assets/create/lang/unfinished/de_de.json +++ b/src/generated/resources/assets/create/lang/unfinished/de_de.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 777", + "_": "Missing Localizations: 781", "_": "->------------------------] Game Elements [------------------------<-", @@ -458,6 +458,10 @@ "advancement.create.crafter.desc": "UNLOCALIZED: Place and power some Mechanical Crafters", "advancement.create.deployer": "UNLOCALIZED: Poke, Place, and Attack", "advancement.create.deployer.desc": "UNLOCALIZED: Place and power a Deployer, the perfect reflection of yourself.", + "advancement.create.mechanical_arm": "UNLOCALIZED: Mechanical Grab'n'Drop", + "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch it do all the work for you.", + "advancement.create.musical_arm": "UNLOCALIZED: Play me my Theme Tune!", + "advancement.create.musical_arm.desc": "UNLOCALIZED: Watch a Mechanical Arm operate your Jukebox.", "advancement.create.fist_bump": "UNLOCALIZED: Pound It, Bro!", "advancement.create.fist_bump.desc": "UNLOCALIZED: Make two Deployers fist-bump.", "advancement.create.crushing_wheel": "UNLOCALIZED: A Pair of Giants", diff --git a/src/generated/resources/assets/create/lang/unfinished/fr_fr.json b/src/generated/resources/assets/create/lang/unfinished/fr_fr.json index 21baa7d50..4f2fc8b3d 100644 --- a/src/generated/resources/assets/create/lang/unfinished/fr_fr.json +++ b/src/generated/resources/assets/create/lang/unfinished/fr_fr.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 380", + "_": "Missing Localizations: 384", "_": "->------------------------] Game Elements [------------------------<-", @@ -458,6 +458,10 @@ "advancement.create.crafter.desc": "UNLOCALIZED: Place and power some Mechanical Crafters", "advancement.create.deployer": "UNLOCALIZED: Poke, Place, and Attack", "advancement.create.deployer.desc": "UNLOCALIZED: Place and power a Deployer, the perfect reflection of yourself.", + "advancement.create.mechanical_arm": "UNLOCALIZED: Mechanical Grab'n'Drop", + "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch it do all the work for you.", + "advancement.create.musical_arm": "UNLOCALIZED: Play me my Theme Tune!", + "advancement.create.musical_arm.desc": "UNLOCALIZED: Watch a Mechanical Arm operate your Jukebox.", "advancement.create.fist_bump": "UNLOCALIZED: Pound It, Bro!", "advancement.create.fist_bump.desc": "UNLOCALIZED: Make two Deployers fist-bump.", "advancement.create.crushing_wheel": "UNLOCALIZED: A Pair of Giants", diff --git a/src/generated/resources/assets/create/lang/unfinished/it_it.json b/src/generated/resources/assets/create/lang/unfinished/it_it.json index cd54613f7..b91adee26 100644 --- a/src/generated/resources/assets/create/lang/unfinished/it_it.json +++ b/src/generated/resources/assets/create/lang/unfinished/it_it.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 364", + "_": "Missing Localizations: 368", "_": "->------------------------] Game Elements [------------------------<-", @@ -458,6 +458,10 @@ "advancement.create.crafter.desc": "UNLOCALIZED: Place and power some Mechanical Crafters", "advancement.create.deployer": "UNLOCALIZED: Poke, Place, and Attack", "advancement.create.deployer.desc": "UNLOCALIZED: Place and power a Deployer, the perfect reflection of yourself.", + "advancement.create.mechanical_arm": "UNLOCALIZED: Mechanical Grab'n'Drop", + "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch it do all the work for you.", + "advancement.create.musical_arm": "UNLOCALIZED: Play me my Theme Tune!", + "advancement.create.musical_arm.desc": "UNLOCALIZED: Watch a Mechanical Arm operate your Jukebox.", "advancement.create.fist_bump": "UNLOCALIZED: Pound It, Bro!", "advancement.create.fist_bump.desc": "UNLOCALIZED: Make two Deployers fist-bump.", "advancement.create.crushing_wheel": "UNLOCALIZED: A Pair of Giants", diff --git a/src/generated/resources/assets/create/lang/unfinished/ja_jp.json b/src/generated/resources/assets/create/lang/unfinished/ja_jp.json index 4bc000f9d..16000f239 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ja_jp.json +++ b/src/generated/resources/assets/create/lang/unfinished/ja_jp.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 359", + "_": "Missing Localizations: 363", "_": "->------------------------] Game Elements [------------------------<-", @@ -458,6 +458,10 @@ "advancement.create.crafter.desc": "UNLOCALIZED: Place and power some Mechanical Crafters", "advancement.create.deployer": "UNLOCALIZED: Poke, Place, and Attack", "advancement.create.deployer.desc": "UNLOCALIZED: Place and power a Deployer, the perfect reflection of yourself.", + "advancement.create.mechanical_arm": "UNLOCALIZED: Mechanical Grab'n'Drop", + "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch it do all the work for you.", + "advancement.create.musical_arm": "UNLOCALIZED: Play me my Theme Tune!", + "advancement.create.musical_arm.desc": "UNLOCALIZED: Watch a Mechanical Arm operate your Jukebox.", "advancement.create.fist_bump": "UNLOCALIZED: Pound It, Bro!", "advancement.create.fist_bump.desc": "UNLOCALIZED: Make two Deployers fist-bump.", "advancement.create.crushing_wheel": "UNLOCALIZED: A Pair of Giants", diff --git a/src/generated/resources/assets/create/lang/unfinished/ko_kr.json b/src/generated/resources/assets/create/lang/unfinished/ko_kr.json index 92d51ddfc..ac39c9e93 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ko_kr.json +++ b/src/generated/resources/assets/create/lang/unfinished/ko_kr.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 364", + "_": "Missing Localizations: 368", "_": "->------------------------] Game Elements [------------------------<-", @@ -458,6 +458,10 @@ "advancement.create.crafter.desc": "UNLOCALIZED: Place and power some Mechanical Crafters", "advancement.create.deployer": "UNLOCALIZED: Poke, Place, and Attack", "advancement.create.deployer.desc": "UNLOCALIZED: Place and power a Deployer, the perfect reflection of yourself.", + "advancement.create.mechanical_arm": "UNLOCALIZED: Mechanical Grab'n'Drop", + "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch it do all the work for you.", + "advancement.create.musical_arm": "UNLOCALIZED: Play me my Theme Tune!", + "advancement.create.musical_arm.desc": "UNLOCALIZED: Watch a Mechanical Arm operate your Jukebox.", "advancement.create.fist_bump": "UNLOCALIZED: Pound It, Bro!", "advancement.create.fist_bump.desc": "UNLOCALIZED: Make two Deployers fist-bump.", "advancement.create.crushing_wheel": "UNLOCALIZED: A Pair of Giants", diff --git a/src/generated/resources/assets/create/lang/unfinished/nl_nl.json b/src/generated/resources/assets/create/lang/unfinished/nl_nl.json index 82e15be94..6bbaa48c1 100644 --- a/src/generated/resources/assets/create/lang/unfinished/nl_nl.json +++ b/src/generated/resources/assets/create/lang/unfinished/nl_nl.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 714", + "_": "Missing Localizations: 718", "_": "->------------------------] Game Elements [------------------------<-", @@ -458,6 +458,10 @@ "advancement.create.crafter.desc": "UNLOCALIZED: Place and power some Mechanical Crafters", "advancement.create.deployer": "UNLOCALIZED: Poke, Place, and Attack", "advancement.create.deployer.desc": "UNLOCALIZED: Place and power a Deployer, the perfect reflection of yourself.", + "advancement.create.mechanical_arm": "UNLOCALIZED: Mechanical Grab'n'Drop", + "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch it do all the work for you.", + "advancement.create.musical_arm": "UNLOCALIZED: Play me my Theme Tune!", + "advancement.create.musical_arm.desc": "UNLOCALIZED: Watch a Mechanical Arm operate your Jukebox.", "advancement.create.fist_bump": "UNLOCALIZED: Pound It, Bro!", "advancement.create.fist_bump.desc": "UNLOCALIZED: Make two Deployers fist-bump.", "advancement.create.crushing_wheel": "UNLOCALIZED: A Pair of Giants", diff --git a/src/generated/resources/assets/create/lang/unfinished/pt_br.json b/src/generated/resources/assets/create/lang/unfinished/pt_br.json index 134623835..d49c96b2a 100644 --- a/src/generated/resources/assets/create/lang/unfinished/pt_br.json +++ b/src/generated/resources/assets/create/lang/unfinished/pt_br.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 784", + "_": "Missing Localizations: 788", "_": "->------------------------] Game Elements [------------------------<-", @@ -458,6 +458,10 @@ "advancement.create.crafter.desc": "UNLOCALIZED: Place and power some Mechanical Crafters", "advancement.create.deployer": "UNLOCALIZED: Poke, Place, and Attack", "advancement.create.deployer.desc": "UNLOCALIZED: Place and power a Deployer, the perfect reflection of yourself.", + "advancement.create.mechanical_arm": "UNLOCALIZED: Mechanical Grab'n'Drop", + "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch it do all the work for you.", + "advancement.create.musical_arm": "UNLOCALIZED: Play me my Theme Tune!", + "advancement.create.musical_arm.desc": "UNLOCALIZED: Watch a Mechanical Arm operate your Jukebox.", "advancement.create.fist_bump": "UNLOCALIZED: Pound It, Bro!", "advancement.create.fist_bump.desc": "UNLOCALIZED: Make two Deployers fist-bump.", "advancement.create.crushing_wheel": "UNLOCALIZED: A Pair of Giants", diff --git a/src/generated/resources/assets/create/lang/unfinished/ru_ru.json b/src/generated/resources/assets/create/lang/unfinished/ru_ru.json index b3f27dba3..cf9239c4f 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ru_ru.json +++ b/src/generated/resources/assets/create/lang/unfinished/ru_ru.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 778", + "_": "Missing Localizations: 782", "_": "->------------------------] Game Elements [------------------------<-", @@ -458,6 +458,10 @@ "advancement.create.crafter.desc": "UNLOCALIZED: Place and power some Mechanical Crafters", "advancement.create.deployer": "UNLOCALIZED: Poke, Place, and Attack", "advancement.create.deployer.desc": "UNLOCALIZED: Place and power a Deployer, the perfect reflection of yourself.", + "advancement.create.mechanical_arm": "UNLOCALIZED: Mechanical Grab'n'Drop", + "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch it do all the work for you.", + "advancement.create.musical_arm": "UNLOCALIZED: Play me my Theme Tune!", + "advancement.create.musical_arm.desc": "UNLOCALIZED: Watch a Mechanical Arm operate your Jukebox.", "advancement.create.fist_bump": "UNLOCALIZED: Pound It, Bro!", "advancement.create.fist_bump.desc": "UNLOCALIZED: Make two Deployers fist-bump.", "advancement.create.crushing_wheel": "UNLOCALIZED: A Pair of Giants", diff --git a/src/generated/resources/assets/create/lang/unfinished/zh_cn.json b/src/generated/resources/assets/create/lang/unfinished/zh_cn.json index 0f1a8b8b8..b691687f8 100644 --- a/src/generated/resources/assets/create/lang/unfinished/zh_cn.json +++ b/src/generated/resources/assets/create/lang/unfinished/zh_cn.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 40", + "_": "Missing Localizations: 44", "_": "->------------------------] Game Elements [------------------------<-", @@ -458,6 +458,10 @@ "advancement.create.crafter.desc": "放置一些机械合成台并且为其供能", "advancement.create.deployer": "我就指着你了咋地?", "advancement.create.deployer.desc": "放置并且功能一个机械手。这可是你右手的完美复制品", + "advancement.create.mechanical_arm": "UNLOCALIZED: Mechanical Grab'n'Drop", + "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch it do all the work for you.", + "advancement.create.musical_arm": "UNLOCALIZED: Play me my Theme Tune!", + "advancement.create.musical_arm.desc": "UNLOCALIZED: Watch a Mechanical Arm operate your Jukebox.", "advancement.create.fist_bump": "来碰个拳,哥们~", "advancement.create.fist_bump.desc": "使两个机械臂互相碰拳", "advancement.create.crushing_wheel": "一对大家伙", diff --git a/src/generated/resources/data/create/advancements/mechanical_arm.json b/src/generated/resources/data/create/advancements/mechanical_arm.json new file mode 100644 index 000000000..81ca30467 --- /dev/null +++ b/src/generated/resources/data/create/advancements/mechanical_arm.json @@ -0,0 +1,46 @@ +{ + "parent": "create:brass_casing", + "display": { + "icon": { + "item": "create:mechanical_arm" + }, + "title": { + "translate": "advancement.create.mechanical_arm" + }, + "description": { + "translate": "advancement.create.mechanical_arm.desc" + }, + "frame": "goal", + "show_toast": true, + "announce_to_chat": true, + "hidden": false + }, + "criteria": { + "0": { + "trigger": "minecraft:placed_block", + "conditions": { + "block": "create:mechanical_arm" + } + }, + "1": { + "trigger": "create:kinetic_block", + "conditions": { + "block": "create:mechanical_arm" + } + }, + "2": { + "trigger": "create:mechanical_arm" + } + }, + "requirements": [ + [ + "0" + ], + [ + "1" + ], + [ + "2" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/musical_arm.json b/src/generated/resources/data/create/advancements/musical_arm.json new file mode 100644 index 000000000..05b68bce2 --- /dev/null +++ b/src/generated/resources/data/create/advancements/musical_arm.json @@ -0,0 +1,46 @@ +{ + "parent": "create:mechanical_arm", + "display": { + "icon": { + "item": "minecraft:music_disc_13" + }, + "title": { + "translate": "advancement.create.musical_arm" + }, + "description": { + "translate": "advancement.create.musical_arm.desc" + }, + "frame": "task", + "show_toast": true, + "announce_to_chat": true, + "hidden": false + }, + "criteria": { + "0": { + "trigger": "minecraft:placed_block", + "conditions": { + "block": "create:mechanical_arm" + } + }, + "1": { + "trigger": "create:kinetic_block", + "conditions": { + "block": "create:mechanical_arm" + } + }, + "2": { + "trigger": "create:musical_arm" + } + }, + "requirements": [ + [ + "0" + ], + [ + "1" + ], + [ + "2" + ] + ] +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 564009be0..d8a8d0e7a 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -700,7 +700,11 @@ public class AllBlocks { public static final BlockEntry MECHANICAL_ARM = REGISTRATE.block("mechanical_arm", ArmBlock::new) .initialProperties(SharedProperties::softMetal) - .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) + .blockstate((c, p) -> p.getVariantBuilder(c.get()) + .forAllStates(s -> ConfiguredModel.builder() + .modelFile(AssetLookup.partialBaseModel(c, p)) + .rotationX(s.get(ArmBlock.CEILING) ? 180 : 0) + .build())) .transform(StressConfigDefaults.setImpact(8.0)) .item(ArmItem::new) .transform(customItemModel()) diff --git a/src/main/java/com/simibubi/create/AllShapes.java b/src/main/java/com/simibubi/create/AllShapes.java index 71626ae70..bb5329f4d 100644 --- a/src/main/java/com/simibubi/create/AllShapes.java +++ b/src/main/java/com/simibubi/create/AllShapes.java @@ -135,6 +135,8 @@ public class AllShapes { .build(), MECHANICAL_ARM = shape(2, 0, 2, 14, 10, 14).add(3, 0, 3, 13, 14, 13) .build(), + MECHANICAL_ARM_CEILING = shape(2, 6, 2, 14, 16, 14).add(3, 2, 3, 13, 16, 13) + .build(), CHUTE = shape(1, 8, 1, 15, 16, 15).add(2, 0, 2, 14, 8, 14) .build(), TANK = shape(1, 0, 1, 15, 16, 15).build(), TANK_TOP = shape(TANK_TOP_LID).add(TANK) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java index 76cf705ef..9d89b97d3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java @@ -118,10 +118,17 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { return super.write(compound); } + @Override + public void lazyTick() { + super.lazyTick(); + if (world.isRemote && running && !basinItemInv.isPresent()) + updateBasin(); + } + @Override public void tick() { super.tick(); - + if (runningTicks >= 40) { running = false; runningTicks = 0; @@ -156,6 +163,8 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { public void renderParticles() { IItemHandler itemHandler = basinItemInv.orElse(null); BasinInventory inv = (BasinInventory) itemHandler; + if (inv == null) + return; for (int slot = 0; slot < inv.getInputHandler() .getSlots(); slot++) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/CombinedFluidHandler.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/CombinedFluidHandler.java index 8d62457ea..d7ae0d73b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/CombinedFluidHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/CombinedFluidHandler.java @@ -1,6 +1,11 @@ package com.simibubi.create.content.contraptions.fluids; -import net.minecraft.fluid.Fluid; +import java.util.Arrays; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import javax.annotation.Nonnull; + import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.util.math.MathHelper; @@ -8,11 +13,6 @@ import net.minecraftforge.common.util.NonNullConsumer; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; -import javax.annotation.Nonnull; -import java.util.Arrays; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - public class CombinedFluidHandler implements IFluidHandler { private final int capacity; private final FluidStack[] tanks; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java index d8ed5b570..0e65b0f99 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java @@ -147,8 +147,8 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor return false; BlockState stateBelow = world.getBlockState(pos.down()); - if (AllBlocks.BRASS_FUNNEL.has(stateBelow)) { - if (stateBelow.get(BrassFunnelBlock.POWERED)) + if (stateBelow.getBlock() instanceof FunnelBlock) { + if (stateBelow.has(BrassFunnelBlock.POWERED) && stateBelow.get(BrassFunnelBlock.POWERED)) return false; if (stateBelow.get(BrassFunnelBlock.FACING) != Direction.UP) return false; @@ -187,9 +187,9 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor private boolean handleUpwardOutput(boolean simulate) { BlockState stateAbove = world.getBlockState(pos.up()); - if (AllBlocks.BRASS_FUNNEL.has(stateAbove)) { - if (!stateAbove.get(BrassFunnelBlock.POWERED) - && stateAbove.get(BrassFunnelBlock.FACING) == Direction.DOWN) { + if (stateAbove.getBlock() instanceof FunnelBlock) { + boolean powered = stateAbove.has(BrassFunnelBlock.POWERED) && stateAbove.get(BrassFunnelBlock.POWERED); + if (!powered && stateAbove.get(BrassFunnelBlock.FACING) == Direction.DOWN) { ItemStack remainder = FunnelBlock.tryInsert(world, pos.up(), item, simulate); if (remainder.isEmpty()) { if (!simulate) diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/AndesiteFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/AndesiteFunnelBlock.java index 6a128adc6..87a3c1705 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/AndesiteFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/AndesiteFunnelBlock.java @@ -4,6 +4,8 @@ import com.simibubi.create.AllBlocks; import net.minecraft.block.BlockState; import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockReader; public class AndesiteFunnelBlock extends FunnelBlock { @@ -12,14 +14,14 @@ public class AndesiteFunnelBlock extends FunnelBlock { } @Override - public BlockState getEquivalentBeltFunnel(BlockState state) { + public BlockState getEquivalentBeltFunnel(IBlockReader world, BlockPos pos, BlockState state) { Direction facing = state.get(FACING); return AllBlocks.ANDESITE_BELT_FUNNEL.getDefaultState() .with(BeltFunnelBlock.HORIZONTAL_FACING, facing); } - + @Override - public BlockState getEquivalentChuteFunnel(BlockState state) { + public BlockState getEquivalentChuteFunnel(IBlockReader world, BlockPos pos, BlockState state) { Direction facing = state.get(FACING); return AllBlocks.ANDESITE_CHUTE_FUNNEL.getDefaultState() .with(ChuteFunnelBlock.HORIZONTAL_FACING, facing); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelBlock.java index 52cdc6e72..c0b721908 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelBlock.java @@ -23,7 +23,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; -import net.minecraft.world.ILightReader; import net.minecraft.world.IWorld; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; @@ -55,9 +54,12 @@ public abstract class BeltFunnelBlock extends HorizontalInteractionFunnelBlock { @Override public BlockState getStateForPlacement(BlockItemUseContext ctx) { BlockState state = super.getStateForPlacement(ctx); - World world = ctx.getWorld(); - BlockPos posBelow = ctx.getPos() - .down(); + return getStateForPosition(ctx.getWorld(), ctx.getPos(), state, ctx.getFace()); + } + + public BlockState getStateForPosition(World world, BlockPos pos, BlockState defaultState, Direction facing) { + BlockState state = defaultState.with(HORIZONTAL_FACING, facing); + BlockPos posBelow = pos.down(); BlockState stateBelow = world.getBlockState(posBelow); if (!AllBlocks.BELT.has(stateBelow)) return state; @@ -68,8 +70,7 @@ public abstract class BeltFunnelBlock extends HorizontalInteractionFunnelBlock { if (beltTileEntity.getSpeed() == 0) return state; Direction movementFacing = beltTileEntity.getMovementFacing(); - Direction funnelFacing = ctx.getFace(); - return state.with(PUSHING, movementFacing == funnelFacing); + return state.with(PUSHING, movementFacing == facing); } @Override @@ -107,7 +108,7 @@ public abstract class BeltFunnelBlock extends HorizontalInteractionFunnelBlock { return true; } - public static BlockState updateShape(BlockState state, ILightReader world, BlockPos pos) { + public static BlockState updateShape(BlockState state, IBlockReader world, BlockPos pos) { state = state.with(SHAPE, Shape.RETRACTED); BlockState neighbour = world.getBlockState(pos.offset(state.get(HORIZONTAL_FACING))); if (canConnectTo(state, neighbour)) diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/BrassFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/BrassFunnelBlock.java index 42eb7bdd3..96d4bce9c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/BrassFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/BrassFunnelBlock.java @@ -10,6 +10,7 @@ import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockReader; import net.minecraft.world.World; public class BrassFunnelBlock extends FunnelBlock { @@ -48,7 +49,7 @@ public class BrassFunnelBlock extends FunnelBlock { } @Override - public BlockState getEquivalentBeltFunnel(BlockState state) { + public BlockState getEquivalentBeltFunnel(IBlockReader world, BlockPos pos, BlockState state) { Direction facing = state.get(FACING); return AllBlocks.BRASS_BELT_FUNNEL.getDefaultState() .with(BeltFunnelBlock.HORIZONTAL_FACING, facing) @@ -56,7 +57,7 @@ public class BrassFunnelBlock extends FunnelBlock { } @Override - public BlockState getEquivalentChuteFunnel(BlockState state) { + public BlockState getEquivalentChuteFunnel(IBlockReader world, BlockPos pos, BlockState state) { Direction facing = state.get(FACING); return AllBlocks.BRASS_CHUTE_FUNNEL.getDefaultState() .with(ChuteFunnelBlock.HORIZONTAL_FACING, facing) diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelBlock.java index f9df8a5c0..aa414f12a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelBlock.java @@ -61,8 +61,8 @@ public abstract class FunnelBlock extends ProperDirectionalBlock implements ITE< BlockRayTraceResult hit) { ItemStack heldItem = player.getHeldItem(handIn); - boolean shouldntInsertItem = AllBlocks.MECHANICAL_ARM.isIn(heldItem); - + boolean shouldntInsertItem = AllBlocks.MECHANICAL_ARM.isIn(heldItem) || !canInsertIntoFunnel(state); + if (hit.getFace() == getFunnelFacing(state) && !shouldntInsertItem) { if (!worldIn.isRemote) withTileEntityDo(worldIn, pos, te -> { @@ -144,17 +144,17 @@ public abstract class FunnelBlock extends ProperDirectionalBlock implements ITE< if (facing.getAxis() .isHorizontal()) { if (direction == Direction.DOWN) { - BlockState equivalentFunnel = getEquivalentBeltFunnel(state); + BlockState equivalentFunnel = getEquivalentBeltFunnel(null, null, state); if (BeltFunnelBlock.isOnValidBelt(equivalentFunnel, world, pos)) - return equivalentFunnel; + return BeltFunnelBlock.updateShape(equivalentFunnel, world, pos); } if (direction == facing) { - BlockState equivalentFunnel = getEquivalentChuteFunnel(state); + BlockState equivalentFunnel = getEquivalentChuteFunnel(null, null, state); if (ChuteFunnelBlock.isOnValidChute(equivalentFunnel, world, pos)) return equivalentFunnel; } if (direction == facing.getOpposite()) { - BlockState equivalentFunnel = getEquivalentChuteFunnel(state); + BlockState equivalentFunnel = getEquivalentChuteFunnel(null, null, state); if (ChuteFunnelBlock.isOnValidChute(equivalentFunnel, world, pos)) return equivalentFunnel; } @@ -162,9 +162,9 @@ public abstract class FunnelBlock extends ProperDirectionalBlock implements ITE< return state; } - public abstract BlockState getEquivalentChuteFunnel(BlockState state); + public abstract BlockState getEquivalentChuteFunnel(IBlockReader world, BlockPos pos, BlockState state); - public abstract BlockState getEquivalentBeltFunnel(BlockState state); + public abstract BlockState getEquivalentBeltFunnel(IBlockReader world, BlockPos pos, BlockState state); @Override public boolean isValidPosition(BlockState state, IWorldReader world, BlockPos pos) { diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelItem.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelItem.java index adb57c068..9167aa479 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelItem.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelItem.java @@ -29,6 +29,8 @@ public class FunnelItem extends BlockItem { @Override protected BlockState getStateForPlacement(BlockItemUseContext ctx) { + World world = ctx.getWorld(); + BlockPos pos = ctx.getPos(); BlockState state = super.getStateForPlacement(ctx); if (state == null) return state; @@ -40,9 +42,9 @@ public class FunnelItem extends BlockItem { return state; FunnelBlock block = (FunnelBlock) getBlock(); - Block beltFunnelBlock = block.getEquivalentBeltFunnel(state) + Block beltFunnelBlock = block.getEquivalentBeltFunnel(world, pos, state) .getBlock(); - Block chuteFunnelBlock = block.getEquivalentChuteFunnel(state) + Block chuteFunnelBlock = block.getEquivalentChuteFunnel(world, pos, state) .getBlock(); BlockState equivalentBeltFunnel = beltFunnelBlock.getStateForPlacement(ctx) @@ -52,8 +54,6 @@ public class FunnelItem extends BlockItem { BlockState reversedChuteFunnel = equivalentChuteFunnel.rotate(Rotation.CLOCKWISE_180) .cycle(ChuteFunnelBlock.PUSHING); - World world = ctx.getWorld(); - BlockPos pos = ctx.getPos(); if (BeltFunnelBlock.isOnValidBelt(equivalentBeltFunnel, world, pos)) return BeltFunnelBlock.updateShape(equivalentBeltFunnel, world, pos); if (ChuteFunnelBlock.isOnValidChute(equivalentChuteFunnel, world, pos)) diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java index 522f94db9..007898fe3 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java @@ -34,6 +34,7 @@ public class FunnelTileEntity extends SmartTileEntity { private FilteringBehaviour filtering; private InsertingBehaviour inserting; private ExtractingBehaviour extracting; + private DirectBeltInputBehaviour beltInputBehaviour; int sendFlap; InterpolatedChasingValue flap; @@ -183,6 +184,15 @@ public class FunnelTileEntity extends SmartTileEntity { filtering.onlyActiveWhen(this::supportsFiltering); behaviours.add(filtering); + beltInputBehaviour = new DirectBeltInputBehaviour(this).onlyInsertWhen(this::supportsDirectBeltInput) + .setInsertionHandler(this::handleDirectBeltInput); + behaviours.add(beltInputBehaviour); + } + + private boolean supportsDirectBeltInput(Direction side) { + BlockState blockState = getBlockState(); + return blockState != null && blockState.getBlock() instanceof FunnelBlock + && blockState.get(FunnelBlock.FACING) == Direction.UP; } private boolean supportsFiltering() { @@ -190,6 +200,15 @@ public class FunnelTileEntity extends SmartTileEntity { return blockState != null && blockState.has(BlockStateProperties.POWERED); } + private ItemStack handleDirectBeltInput(TransportedItemStack stack, Direction side, boolean simulate) { + ItemStack inserted = stack.stack; + if (!filtering.test(inserted)) + return inserted; + if (determineCurrentMode() == Mode.PAUSED) + return inserted; + return inserting.insert(inserted, simulate); + } + public void flap(boolean inward) { sendFlap = inward ? 1 : -1; sendData(); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/HorizontalInteractionFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/HorizontalInteractionFunnelBlock.java index 276a04ee5..3216e1d8a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/HorizontalInteractionFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/HorizontalInteractionFunnelBlock.java @@ -86,9 +86,12 @@ public abstract class HorizontalInteractionFunnelBlock extends HorizontalBlock i @Override public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbour, IWorld world, BlockPos pos, BlockPos p_196271_6_) { - if (!canStillInteract(state, world, pos)) - return parent.getDefaultState() - .with(FunnelBlock.FACING, state.get(HORIZONTAL_FACING)); + if (!canStillInteract(state, world, pos)) { + BlockState parentState = parent.getDefaultState(); + if (state.has(POWERED) && state.get(POWERED)) + parentState = parentState.with(POWERED, true); + return parentState.with(FunnelBlock.FACING, state.get(HORIZONTAL_FACING)); + } return state; } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateInventory.java b/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateInventory.java index ec1b4efca..e8da1b86d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateInventory.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateInventory.java @@ -35,7 +35,7 @@ public class CreativeCrateInventory implements IItemHandler { public ItemStack extractItem(int slot, int amount, boolean simulate) { ItemStack filter = te.filter.getFilter().copy(); if (!filter.isEmpty()) - filter.setCount(amount); + filter.setCount(Math.min(filter.getMaxStackSize(), amount)); return filter; } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmAngleTarget.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmAngleTarget.java index fd1b94216..696b987f0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmAngleTarget.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmAngleTarget.java @@ -12,7 +12,7 @@ import net.minecraft.util.math.Vec3d; public class ArmAngleTarget { static ArmAngleTarget NO_TARGET = new ArmAngleTarget(); - + float baseAngle; float lowerArmAngle; float upperArmAngle; @@ -24,10 +24,13 @@ public class ArmAngleTarget { headAngle = -15; } - public ArmAngleTarget(BlockPos armPos, Vec3d pointTarget, Direction clawFacing) { + public ArmAngleTarget(BlockPos armPos, Vec3d pointTarget, Direction clawFacing, boolean ceiling) { +// if (ceiling) +// clawFacing = clawFacing.getOpposite(); + Vec3d target = pointTarget; Vec3d origin = VecHelper.getCenterOf(armPos) - .add(0, 4 / 16f, 0); + .add(0, ceiling ? -4 / 16f : 4 / 16f, 0); Vec3d clawTarget = target; target = target.add(new Vec3d(clawFacing.getOpposite() .getDirectionVec()).scale(.5f)); @@ -37,6 +40,11 @@ public class ArmAngleTarget { .length(); float baseAngle = AngleHelper.deg(MathHelper.atan2(diff.x, diff.z)) + 180; + if (ceiling) { + diff = diff.mul(1, -1, 1); + baseAngle = 180 - baseAngle; + } + float alphaOffset = AngleHelper.deg(MathHelper.atan2(diff.y, horizontalDistance)); float a = 18 / 16f; // lower arm length @@ -61,8 +69,13 @@ public class ArmAngleTarget { headPos = VecHelper.rotate(headPos.add(0, b, 0), beta + 180, Axis.X); headPos = VecHelper.rotate(headPos.add(0, a, 0), alpha - 90, Axis.X); headPos = VecHelper.rotate(headPos, baseAngle, Axis.Y); + headPos = VecHelper.rotate(headPos, ceiling ? 180 : 0, Axis.X); headPos = headPos.add(origin); Vec3d headDiff = clawTarget.subtract(headPos); + + if (ceiling) + headDiff = headDiff.mul(1, -1, 1); + float horizontalHeadDistance = (float) headDiff.mul(1, 0, 1) .length(); float headAngle = diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmBlock.java index e5f1518d5..7265722c8 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmBlock.java @@ -1,17 +1,24 @@ package com.simibubi.create.content.logistics.block.mechanicalArm; +import org.apache.commons.lang3.mutable.MutableBoolean; + import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.base.KineticBlock; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity.Phase; import com.simibubi.create.foundation.block.ITE; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.InventoryHelper; +import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.ItemStack; +import net.minecraft.state.BooleanProperty; +import net.minecraft.state.StateContainer.Builder; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ActionResultType; +import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -24,8 +31,21 @@ import net.minecraft.world.World; public class ArmBlock extends KineticBlock implements ITE { + public static final BooleanProperty CEILING = BooleanProperty.create("ceiling"); + public ArmBlock(Properties properties) { super(properties); + setDefaultState(getDefaultState().with(CEILING, false)); + } + + @Override + protected void fillStateContainer(Builder p_206840_1_) { + super.fillStateContainer(p_206840_1_.add(CEILING)); + } + + @Override + public BlockState getStateForPlacement(BlockItemUseContext ctx) { + return getDefaultState().with(CEILING, ctx.getFace() == Direction.DOWN); } @Override @@ -34,9 +54,9 @@ public class ArmBlock extends KineticBlock implements ITE { } @Override - public VoxelShape getShape(BlockState p_220053_1_, IBlockReader p_220053_2_, BlockPos p_220053_3_, + public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_, ISelectionContext p_220053_4_) { - return AllShapes.MECHANICAL_ARM; + return state.get(CEILING) ? AllShapes.MECHANICAL_ARM_CEILING : AllShapes.MECHANICAL_ARM; } @Override @@ -70,18 +90,21 @@ public class ArmBlock extends KineticBlock implements ITE { @Override public ActionResultType onUse(BlockState p_225533_1_, World world, BlockPos pos, PlayerEntity player, Hand p_225533_5_, BlockRayTraceResult p_225533_6_) { - if (world.isRemote) - return ActionResultType.SUCCESS; + MutableBoolean success = new MutableBoolean(false); withTileEntityDo(world, pos, te -> { if (te.heldItem.isEmpty()) return; + success.setTrue(); + if (world.isRemote) + return; player.inventory.placeItemBackInInventory(world, te.heldItem); te.heldItem = ItemStack.EMPTY; te.phase = Phase.SEARCH_INPUTS; te.markDirty(); te.sendData(); }); - return ActionResultType.SUCCESS; + + return success.booleanValue() ? ActionResultType.SUCCESS : ActionResultType.PASS; } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java index 980057350..7923b5adf 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java @@ -1,12 +1,17 @@ package com.simibubi.create.content.logistics.block.mechanicalArm; +import java.util.function.Supplier; + import javax.annotation.Nullable; +import com.google.common.collect.ImmutableMap; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.components.saw.SawBlock; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock; import com.simibubi.create.content.logistics.block.funnel.FunnelBlock; +import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InsertingBehaviour; @@ -14,9 +19,14 @@ import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; +import net.minecraft.block.JukeboxBlock; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.NBTUtil; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.tileentity.JukeboxTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -43,6 +53,19 @@ public abstract class ArmInteractionPoint { private LazyOptional cachedHandler; private ArmAngleTarget cachedAngles; + private static ImmutableMap> POINTS = + ImmutableMap.>builder() + .put(new Belt(), Belt::new) + .put(new Depot(), Depot::new) + .put(new Saw(), Saw::new) + .put(new Chute(), Chute::new) + .put(new Jukebox(), Jukebox::new) + .put(new Basin(), Basin::new) + .put(new Millstone(), Millstone::new) + .put(new Funnel(), Funnel::new) + .put(new CrushingWheels(), CrushingWheels::new) + .build(); + public ArmInteractionPoint() { cachedHandler = LazyOptional.empty(); } @@ -66,16 +89,19 @@ public abstract class ArmInteractionPoint { return Direction.DOWN; } - abstract boolean isValid(BlockState state); + abstract boolean isValid(IBlockReader reader, BlockPos pos, BlockState state); - static boolean isInteractable(BlockState state) { - return AllBlocks.DEPOT.has(state) || AllBlocks.BELT.has(state) || AllBlocks.CHUTE.has(state) - || state.getBlock() instanceof FunnelBlock; + static boolean isInteractable(IBlockReader reader, BlockPos pos, BlockState state) { + for (ArmInteractionPoint armInteractionPoint : POINTS.keySet()) + if (armInteractionPoint.isValid(reader, pos, state)) + return true; + return false; } - ArmAngleTarget getTargetAngles(BlockPos armPos) { + ArmAngleTarget getTargetAngles(BlockPos armPos, boolean ceiling) { if (cachedAngles == null) - cachedAngles = new ArmAngleTarget(armPos, getInteractionPositionVector(), getInteractionDirection()); + cachedAngles = + new ArmAngleTarget(armPos, getInteractionPositionVector(), getInteractionDirection(), ceiling); return cachedAngles; } @@ -120,15 +146,10 @@ public abstract class ArmInteractionPoint { BlockState state = world.getBlockState(pos); ArmInteractionPoint point = null; - if (AllBlocks.DEPOT.has(state)) - point = new Depot(); - if (AllBlocks.BELT.has(state) && !(world.getBlockState(pos.up()) - .getBlock() instanceof BeltTunnelBlock)) - point = new Belt(); - if (AllBlocks.CHUTE.has(state)) - point = new Chute(); - if (state.getBlock() instanceof FunnelBlock) - point = new Funnel(); + for (ArmInteractionPoint armInteractionPoint : POINTS.keySet()) + if (armInteractionPoint.isValid(world, pos, state)) + point = POINTS.get(armInteractionPoint) + .get(); if (point != null) { point.state = state; @@ -155,6 +176,15 @@ public abstract class ArmInteractionPoint { return interactionPoint; } + static abstract class TopFaceArmInteractionPoint extends ArmInteractionPoint { + + @Override + Vec3d getInteractionPositionVector() { + return new Vec3d(pos).add(.5f, 1, .5f); + } + + } + static class Depot extends ArmInteractionPoint { @Override @@ -163,29 +193,117 @@ public abstract class ArmInteractionPoint { } @Override - boolean isValid(BlockState state) { + boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { return AllBlocks.DEPOT.has(state); } } + static class Saw extends Depot { + + @Override + boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { + return AllBlocks.MECHANICAL_SAW.has(state) && state.get(SawBlock.RUNNING) + && state.get(SawBlock.FACING) == Direction.UP; + } + + } + + static class Millstone extends ArmInteractionPoint { + + @Override + boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { + return AllBlocks.MILLSTONE.has(state); + } + + } + + static class CrushingWheels extends TopFaceArmInteractionPoint { + + @Override + boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { + return AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(state); + } + + } + + static class Basin extends ArmInteractionPoint { + + @Override + boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { + return AllBlocks.BASIN.has(state); + } + + } + + static class Jukebox extends TopFaceArmInteractionPoint { + + @Override + boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { + return state.getBlock() instanceof JukeboxBlock; + } + + @Override + int getSlotCount(World world) { + return 1; + } + + @Override + ItemStack insert(World world, ItemStack stack, boolean simulate) { + TileEntity tileEntity = world.getTileEntity(pos); + if (!(tileEntity instanceof JukeboxTileEntity)) + return stack; + if (!(state.getBlock() instanceof JukeboxBlock)) + return stack; + JukeboxBlock jukeboxBlock = (JukeboxBlock) state.getBlock(); + JukeboxTileEntity jukeboxTE = (JukeboxTileEntity) tileEntity; + if (!jukeboxTE.getRecord() + .isEmpty()) + return stack; + ItemStack remainder = stack.copy(); + ItemStack toInsert = remainder.split(1); + if (!simulate && !world.isRemote) { + jukeboxBlock.insertRecord(world, pos, state, toInsert); + world.playEvent((PlayerEntity) null, 1010, pos, Item.getIdFromItem(toInsert.getItem())); + AllTriggers.triggerForNearbyPlayers(AllTriggers.MUSICAL_ARM, world, pos, 10); + } + return remainder; + } + + @Override + ItemStack extract(World world, int slot, int amount, boolean simulate) { + TileEntity tileEntity = world.getTileEntity(pos); + if (!(tileEntity instanceof JukeboxTileEntity)) + return ItemStack.EMPTY; + if (!(state.getBlock() instanceof JukeboxBlock)) + return ItemStack.EMPTY; + JukeboxTileEntity jukeboxTE = (JukeboxTileEntity) tileEntity; + ItemStack itemstack = jukeboxTE.getRecord(); + if (itemstack.isEmpty()) + return ItemStack.EMPTY; + if (!simulate && !world.isRemote) { + world.playEvent(1010, pos, 0); + jukeboxTE.clear(); + world.setBlockState(pos, state.with(JukeboxBlock.HAS_RECORD, false), 2); + } + return itemstack; + } + + } + static class Belt extends Depot { @Override - boolean isValid(BlockState state) { - return AllBlocks.BELT.has(state); + boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { + return AllBlocks.BELT.has(state) && !(reader.getBlockState(pos.up()) + .getBlock() instanceof BeltTunnelBlock); } } - static class Chute extends ArmInteractionPoint { + static class Chute extends TopFaceArmInteractionPoint { @Override - Vec3d getInteractionPositionVector() { - return new Vec3d(pos).add(.5f, 1, .5f); - } - - @Override - boolean isValid(BlockState state) { + boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { return AllBlocks.CHUTE.has(state); } } @@ -219,6 +337,9 @@ public abstract class ArmInteractionPoint { ItemStack insert(World world, ItemStack stack, boolean simulate) { FilteringBehaviour filtering = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE); InsertingBehaviour inserter = TileEntityBehaviour.get(world, pos, InsertingBehaviour.TYPE); + BlockState state = world.getBlockState(pos); + if (state.has(BlockStateProperties.POWERED) && state.get(BlockStateProperties.POWERED)) + return stack; if (inserter == null) return stack; if (filtering != null && !filtering.test(stack)) @@ -227,7 +348,7 @@ public abstract class ArmInteractionPoint { } @Override - boolean isValid(BlockState state) { + boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { return state.getBlock() instanceof FunnelBlock; } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java index 12f61cf53..7a5a181cc 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java @@ -1,9 +1,9 @@ package com.simibubi.create.content.logistics.block.mechanicalArm; -import java.util.HashMap; +import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; +import java.util.List; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; @@ -30,7 +30,7 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @EventBusSubscriber(value = Dist.CLIENT) public class ArmInteractionPointHandler { - static Map currentSelection = new HashMap<>(); + static List currentSelection = new ArrayList<>(); static ItemStack currentItem; static long lastBlockPos = -1; @@ -44,15 +44,17 @@ public class ArmInteractionPointHandler { if (!world.isRemote) return; - if (!currentSelection.containsKey(pos)) { + ArmInteractionPoint selected = getSelected(pos); + + if (selected == null) { ArmInteractionPoint point = ArmInteractionPoint.createAt(world, pos); if (point == null) return; - currentSelection.put(pos, point); + selected = point; + put(point); } - currentSelection.get(pos) - .cycleMode(); + selected.cycleMode(); event.setCanceled(true); event.setCancellationResult(ActionResultType.SUCCESS); } @@ -64,7 +66,7 @@ public class ArmInteractionPointHandler { if (!event.getWorld().isRemote) return; BlockPos pos = event.getPos(); - if (currentSelection.remove(pos) != null) { + if (remove(pos) != null) { event.setCanceled(true); event.setCancellationResult(ActionResultType.SUCCESS); } @@ -73,7 +75,7 @@ public class ArmInteractionPointHandler { public static void flushSettings(BlockPos pos) { if (currentItem == null) return; - AllPackets.channel.sendToServer(new ArmPlacementPacket(currentSelection.values(), pos)); + AllPackets.channel.sendToServer(new ArmPlacementPacket(currentSelection, pos)); currentSelection.clear(); currentItem = null; } @@ -100,7 +102,7 @@ public class ArmInteractionPointHandler { } private static void checkForWrench(ItemStack heldItem) { - if(!AllItems.WRENCH.isIn(heldItem)) { + if (!AllItems.WRENCH.isIn(heldItem)) { return; } @@ -122,8 +124,8 @@ public class ArmInteractionPointHandler { if (lastBlockPos == -1 || lastBlockPos != pos.toLong()) { currentSelection.clear(); ArmTileEntity arm = (ArmTileEntity) te; - arm.inputs.forEach(point -> currentSelection.put(point.pos, point)); - arm.outputs.forEach(point -> currentSelection.put(point.pos, point)); + arm.inputs.forEach(ArmInteractionPointHandler::put); + arm.outputs.forEach(ArmInteractionPointHandler::put); lastBlockPos = pos.toLong(); } @@ -132,16 +134,14 @@ public class ArmInteractionPointHandler { } } - private static void drawOutlines(Map selection) { + private static void drawOutlines(Collection selection) { World world = Minecraft.getInstance().world; - for (Iterator> iterator = selection.entrySet() - .iterator(); iterator.hasNext();) { - Entry entry = iterator.next(); - BlockPos pos = entry.getKey(); + for (Iterator iterator = selection.iterator(); iterator.hasNext();) { + ArmInteractionPoint point = iterator.next(); + BlockPos pos = point.pos; BlockState state = world.getBlockState(pos); - ArmInteractionPoint point = entry.getValue(); - if (!point.isValid(state)) { + if (!point.isValid(world, pos, state)) { iterator.remove(); continue; } @@ -158,4 +158,23 @@ public class ArmInteractionPointHandler { } } + private static void put(ArmInteractionPoint point) { + currentSelection.add(point); + } + + private static ArmInteractionPoint remove(BlockPos pos) { + ArmInteractionPoint result = getSelected(pos); + if (result != null) + currentSelection.remove(result); + return result; + } + + private static ArmInteractionPoint getSelected(BlockPos pos) { + for (ArmInteractionPoint point : currentSelection) { + if (point.pos.equals(pos)) + return point; + } + return null; + } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmItem.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmItem.java index a459fea8c..eff83fadb 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmItem.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmItem.java @@ -22,8 +22,9 @@ public class ArmItem extends BlockItem { @Override public ActionResultType onItemUse(ItemUseContext ctx) { - if (ArmInteractionPoint.isInteractable(ctx.getWorld() - .getBlockState(ctx.getPos()))) + World world = ctx.getWorld(); + BlockPos pos = ctx.getPos(); + if (ArmInteractionPoint.isInteractable(world, pos, world.getBlockState(pos))) return ActionResultType.SUCCESS; return super.onItemUse(ctx); } @@ -37,9 +38,9 @@ public class ArmItem extends BlockItem { } @Override - public boolean canPlayerBreakBlockWhileHolding(BlockState state, World p_195938_2_, BlockPos p_195938_3_, + public boolean canPlayerBreakBlockWhileHolding(BlockState state, World world, BlockPos pos, PlayerEntity p_195938_4_) { - return !ArmInteractionPoint.isInteractable(state); + return !ArmInteractionPoint.isInteractable(world, pos, state); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java index c7e03a2cf..ba13e7bff 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java @@ -5,6 +5,9 @@ import com.mojang.blaze3d.vertex.IVertexBuilder; 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.content.logistics.block.mechanicalArm.ArmTileEntity.Phase; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.SuperByteBuffer; @@ -18,6 +21,7 @@ import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.item.BlockItem; import net.minecraft.item.ItemStack; +import net.minecraft.util.math.MathHelper; public class ArmRenderer extends KineticTileEntityRenderer { @@ -35,6 +39,21 @@ public class ArmRenderer extends KineticTileEntityRenderer { MatrixStacker msr = MatrixStacker.of(ms); int color = 0xFFFFFF; + float baseAngle = arm.baseAngle.get(pt); + float lowerArmAngle = arm.lowerArmAngle.get(pt) - 135; + float upperArmAngle = arm.upperArmAngle.get(pt) - 90; + float headAngle = arm.headAngle.get(pt); + + boolean rave = te instanceof ArmTileEntity && ((ArmTileEntity) te).phase == Phase.DANCING; + float renderTick = AnimationTickHolder.getRenderTick() + (te.hashCode() % 64); + if (rave) { + baseAngle = (renderTick * 10) % 360; + lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15); + upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95); + headAngle = -lowerArmAngle; + color = ColorHelper.rainbowColor(AnimationTickHolder.ticks * 100); + } + ms.push(); SuperByteBuffer base = AllBlockPartials.ARM_BASE.renderOn(blockState).light(light); @@ -45,24 +64,27 @@ public class ArmRenderer extends KineticTileEntityRenderer { SuperByteBuffer clawGrip = AllBlockPartials.ARM_CLAW_GRIP.renderOn(blockState).light(light); msr.centre(); + + if (blockState.get(ArmBlock.CEILING)) + msr.rotateX(180); ms.translate(0, 4 / 16d, 0); - msr.rotateY(arm.baseAngle.get(pt)); + msr.rotateY(baseAngle); base.renderInto(ms, builder); ms.translate(0, 1 / 16d, -2 / 16d); - msr.rotateX(arm.lowerArmAngle.get(pt) - 135); + msr.rotateX(lowerArmAngle); ms.translate(0, -1 / 16d, 0); lowerBody.color(color) .renderInto(ms, builder); ms.translate(0, 12 / 16d, 12 / 16d); - msr.rotateX(arm.upperArmAngle.get(pt) - 90); + msr.rotateX(upperArmAngle); upperBody.color(color) .renderInto(ms, builder); ms.translate(0, 11 / 16d, -11 / 16d); - msr.rotateX(arm.headAngle.get(pt)); + msr.rotateX(headAngle); head.renderInto(ms, builder); ms.translate(0, 0, -4 / 16d); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java index 849406f4f..77be7ffc7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java @@ -6,11 +6,15 @@ import java.util.List; import javax.annotation.Nullable; import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPoint.Jukebox; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPoint.Mode; +import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.gui.widgets.InterpolatedAngle; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.NBTHelper; +import net.minecraft.block.BlockState; +import net.minecraft.block.JukeboxBlock; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.INBT; @@ -43,7 +47,7 @@ public class ArmTileEntity extends KineticTileEntity { boolean updateInteractionPoints; enum Phase { - SEARCH_INPUTS, MOVE_TO_INPUT, SEARCH_OUTPUTS, MOVE_TO_OUTPUT, IDLE + SEARCH_INPUTS, MOVE_TO_INPUT, SEARCH_OUTPUTS, MOVE_TO_OUTPUT, DANCING } public ArmTileEntity(TileEntityType typeIn) { @@ -86,12 +90,34 @@ public class ArmTileEntity extends KineticTileEntity { return; if (chasedPointProgress < .5f) return; - if (phase == Phase.SEARCH_INPUTS) + if (phase == Phase.SEARCH_INPUTS || phase == Phase.DANCING) { + checkForMusic(); searchForItem(); + } if (phase == Phase.SEARCH_OUTPUTS) searchForDestination(); } + private void checkForMusic() { + boolean hasMusic = checkForMusicAmong(inputs) || checkForMusicAmong(outputs); + if (hasMusic != (phase == Phase.DANCING)) { + phase = hasMusic ? Phase.DANCING : Phase.SEARCH_INPUTS; + markDirty(); + sendData(); + } + } + + private boolean checkForMusicAmong(List list) { + for (ArmInteractionPoint armInteractionPoint : list) { + if (!(armInteractionPoint instanceof Jukebox)) + continue; + BlockState state = world.getBlockState(armInteractionPoint.pos); + if (state.has(JukeboxBlock.HAS_RECORD) && state.get(JukeboxBlock.HAS_RECORD)) + return true; + } + return false; + } + private void tickMovementProgress() { chasedPointProgress += Math.min(256, Math.abs(getSpeed())) / 1024f; if (chasedPointProgress > 1) @@ -101,8 +127,8 @@ public class ArmTileEntity extends KineticTileEntity { ArmInteractionPoint targetedInteractionPoint = getTargetedInteractionPoint(); ArmAngleTarget previousTarget = this.previousTarget; - ArmAngleTarget target = - targetedInteractionPoint == null ? ArmAngleTarget.NO_TARGET : targetedInteractionPoint.getTargetAngles(pos); + ArmAngleTarget target = targetedInteractionPoint == null ? ArmAngleTarget.NO_TARGET + : targetedInteractionPoint.getTargetAngles(pos, isOnCeiling()); baseAngle.set(AngleHelper.angleLerp(chasedPointProgress, previousBaseAngle, target == ArmAngleTarget.NO_TARGET ? previousBaseAngle : target.baseAngle)); @@ -116,7 +142,13 @@ public class ArmTileEntity extends KineticTileEntity { lowerArmAngle.set(MathHelper.lerp(progress, previousTarget.lowerArmAngle, target.lowerArmAngle)); upperArmAngle.set(MathHelper.lerp(progress, previousTarget.upperArmAngle, target.upperArmAngle)); - headAngle.set(AngleHelper.angleLerp(progress, previousTarget.headAngle, target.headAngle)); + + headAngle.set(AngleHelper.angleLerp(progress, previousTarget.headAngle % 360, target.headAngle % 360)); + } + + protected boolean isOnCeiling() { + BlockState state = getBlockState(); + return hasWorld() && state != null && state.has(ArmBlock.CEILING) && state.get(ArmBlock.CEILING); } @Nullable @@ -182,6 +214,9 @@ public class ArmTileEntity extends KineticTileEntity { chasedPointIndex = -1; sendData(); markDirty(); + + if (!world.isRemote) + AllTriggers.triggerForNearbyPlayers(AllTriggers.MECHANICAL_ARM, world, pos, 10); } protected void collectItem() { @@ -277,9 +312,9 @@ public class ArmTileEntity extends KineticTileEntity { int previousIndex = chasedPointIndex; Phase previousPhase = phase; ListNBT interactionPointTagBefore = interactionPointTag; - super.readClientUpdate(tag); + boolean ceiling = isOnCeiling(); if (interactionPointTagBefore == null || interactionPointTagBefore.size() != interactionPointTag.size()) updateInteractionPoints = true; if (previousIndex != chasedPointIndex || (previousPhase != phase)) { @@ -288,9 +323,10 @@ public class ArmTileEntity extends KineticTileEntity { previousPoint = inputs.get(previousIndex); if (previousPhase == Phase.MOVE_TO_OUTPUT && previousIndex < outputs.size()) previousPoint = outputs.get(previousIndex); - previousTarget = previousPoint == null ? ArmAngleTarget.NO_TARGET : previousPoint.getTargetAngles(pos); + previousTarget = + previousPoint == null ? ArmAngleTarget.NO_TARGET : previousPoint.getTargetAngles(pos, ceiling); if (previousPoint != null) - previousBaseAngle = previousPoint.getTargetAngles(pos).baseAngle; + previousBaseAngle = previousPoint.getTargetAngles(pos, ceiling).baseAngle; } } diff --git a/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java b/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java index 8652270a3..87f2f5c3a 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java @@ -80,9 +80,9 @@ public class AllAdvancements implements IDataProvider { andesiteExpertLane(t, andesite_casing); - Advancement drill = - kinecticAdvancement("mechanical_drill", AllBlocks.MECHANICAL_DRILL.get(), TaskType.NORMAL).withParent(andesite_casing) - .register(t, id + ":mechanical_drill"); + Advancement drill = kinecticAdvancement("mechanical_drill", AllBlocks.MECHANICAL_DRILL.get(), TaskType.NORMAL) + .withParent(andesite_casing) + .register(t, id + ":mechanical_drill"); Advancement press = advancement("press", AllBlocks.MECHANICAL_PRESS.get(), TaskType.MILESTONE).withParent(andesite_casing) @@ -98,8 +98,9 @@ public class AllAdvancements implements IDataProvider { itemAdvancement("electron_tube", AllItems.ELECTRON_TUBE, TaskType.NORMAL).withParent(rose_quartz) .register(t, id + ":electron_tube"); - Advancement saw = kinecticAdvancement("mechanical_saw", AllBlocks.MECHANICAL_SAW.get(), TaskType.NORMAL).withParent(press) - .register(t, id + ":mechanical_saw"); + Advancement saw = + kinecticAdvancement("mechanical_saw", AllBlocks.MECHANICAL_SAW.get(), TaskType.NORMAL).withParent(press) + .register(t, id + ":mechanical_saw"); Advancement basin = advancement("basin", AllBlocks.BASIN.get(), TaskType.NORMAL).withParent(press) .withCriterion("0", placeBlock(AllBlocks.BASIN.get())) @@ -196,6 +197,20 @@ public class AllAdvancements implements IDataProvider { .withCriterion("0", AllTriggers.GIGA_EXTENDO.instance()) .register(t, id + ":dual_extendo_grip"); + Advancement mechanical_arm = advancement("mechanical_arm", AllBlocks.MECHANICAL_ARM.get(), TaskType.GOAL) + .withCriterion("0", placeBlock(AllBlocks.MECHANICAL_ARM.get())) + .withCriterion("1", isPowered(AllBlocks.MECHANICAL_ARM.get())) + .withCriterion("2", AllTriggers.MECHANICAL_ARM.instance()) + .withParent(brass_casing) + .register(t, id + ":mechanical_arm"); + + Advancement musical_arm = advancement("musical_arm", Items.MUSIC_DISC_13, TaskType.MILESTONE) + .withCriterion("0", placeBlock(AllBlocks.MECHANICAL_ARM.get())) + .withCriterion("1", isPowered(AllBlocks.MECHANICAL_ARM.get())) + .withCriterion("2", AllTriggers.MUSICAL_ARM.instance()) + .withParent(mechanical_arm) + .register(t, id + ":musical_arm"); + Advancement deployer = kinecticAdvancement("deployer", AllBlocks.DEPLOYER.get(), TaskType.GOAL).withParent(brass_casing) .register(t, id + ":deployer"); diff --git a/src/main/java/com/simibubi/create/foundation/advancement/AllTriggers.java b/src/main/java/com/simibubi/create/foundation/advancement/AllTriggers.java index 34599e5fa..fe199f622 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/AllTriggers.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/AllTriggers.java @@ -33,6 +33,8 @@ public class AllTriggers { UPGRADED_ZAPPER = simple("upgraded_zapper"), EXTENDO = simple("extendo"), GIGA_EXTENDO = simple("giga_extendo"), + MECHANICAL_ARM = simple("mechanical_arm"), + MUSICAL_ARM = simple("musical_arm"), MIXER_MIX = simple("mixer"); private static SimpleTrigger simple(String id) { diff --git a/src/main/resources/assets/create/lang/default/advancements.json b/src/main/resources/assets/create/lang/default/advancements.json index fe016827a..9efbca048 100644 --- a/src/main/resources/assets/create/lang/default/advancements.json +++ b/src/main/resources/assets/create/lang/default/advancements.json @@ -61,6 +61,10 @@ "advancement.create.crafter.desc": "Place and power some Mechanical Crafters", "advancement.create.deployer": "Poke, Place, and Attack", "advancement.create.deployer.desc": "Place and power a Deployer, the perfect reflection of yourself.", + "advancement.create.mechanical_arm": "Mechanical Grab'n'Drop", + "advancement.create.mechanical_arm.desc": "Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch it do all the work for you.", + "advancement.create.musical_arm": "Play me my Theme Tune!", + "advancement.create.musical_arm.desc": "Watch a Mechanical Arm operate your Jukebox.", "advancement.create.fist_bump": "Pound It, Bro!", "advancement.create.fist_bump.desc": "Make two Deployers fist-bump.", "advancement.create.crushing_wheel": "A Pair of Giants", diff --git a/src/main/resources/assets/create/models/block/funnel/block.json b/src/main/resources/assets/create/models/block/funnel/block.json index 5ec5f5d4d..c9dab296d 100644 --- a/src/main/resources/assets/create/models/block/funnel/block.json +++ b/src/main/resources/assets/create/models/block/funnel/block.json @@ -121,8 +121,8 @@ }, { "name": "Back", - "from": [3, -2, 3], - "to": [13, 2, 13], + "from": [3.1, -1.9, 3.1], + "to": [12.9, 2, 12.9], "faces": { "north": {"uv": [9.5, 9, 14.5, 11], "texture": "#4"}, "east": {"uv": [9.5, 9, 14.5, 11], "texture": "#4"}, diff --git a/src/main/resources/assets/create/textures/block/andesite_funnel_back.png b/src/main/resources/assets/create/textures/block/andesite_funnel_back.png index bc3c352edbe68de83130676763ea8879a540d606..0cf5404047e77f8a0de822507dd252147793793e 100644 GIT binary patch delta 925 zcmV;O17iHr2iOOYNq@os01mX6Ma(=grRSD$DniddTmk!-;uvqt$AW*XuRBK7Wb!K2_>1QFj`{EpGiw zT2T?mgUBGz2|T+UI23V+=P}UchCL3bu}FY4-@JGz7vSWBtzwK)iKtjL3hF?P;l6Sm za2!y-*Ak*K4stB&5H$?+k>gau{xkjyQ013nRQTnxzhuLZ`>XadIxgdmbEz%Bq+CWp zj=7Y8QPM6W$A78AZZ9{MqMEs%i@_t|4+DKT4yanGMzQ9;C7qleCm&#t^kI=wYDSb_ zIgJ!WvBYp+xlW{rxTJC*JeBWdw{+T{VKCfg{0-nSzH0sJm>C>*RrIYk&P1D{>$<3n z3s!v@l+{1YqJ!x_>N&F`G)# zwd)DWWpY$1l_(O4SS$;go5)%+@?pC$P=Jb;Dw9qNr&gDEE3~%1-yqP!O*_mBo;a*0MhJtV~b`{)cwOSAi27e8&PrAJaHMPa+PGh*m zt$dLL5d&!u9t?B>pWO%_usDpTF|f@IdmJLXd3sCVRFcf`N-iP8_ePr4ao|zMp}4iR zH9@2S{J_V08HevH8up*@KLOG0Z65~4@?})`{-XVi`o-@!=h_0Cl!_Plm~$oIMRp!O zP8@c7xq%l7?SJQdos`BjwRc2cp#P+z{D zODHTZBkVI@q#X7zK@g0ZKZK=M zOL`)ifWq$rghC;s8DLPGs;Z_RFR%Aj(FUz~3UXb8_kW-FEt!nEFk$)KvVJEw4~bX; zl&Zq46Zjn2*xZKV`U>pSk`NAu0S>>x-T5n)gjPREBT2&)c=qHGY;OI4hT1fm0m7jP zqXuv!m*GM(#p>9nP>^7EXBRr14#Z+HD3wZZJt|ug`nY}MngA&zEWTJYwK`EMM(yn0 z#;0P;R)0>a%y!!ys8*{i0knZYK<_0aP(lx~+DMA91aRWK)IS!(n8{|~(&aQ1^F^ps zDiDvyEtV3R9V=KA`LIPfRihpqe1m(jO@TFWXv&r!kn0seTMAn`V zTX_%ckE$HXDr}UZ@UuPB+eVc=LoD9{oZJaYf@geu+_d(D2=uYo6(K}C?}(;p%(`Lk zW1o~y2$dj<;KT?iLWqjoKihu;J|VtP8(FF&BJQhKNHs6m6(M~65BO1yR?e>;@s$86 zK!0DmLAKfK->OcQFcZKxbQshJ6`-wivfXZ%C4zR4Pq2%Kn4X?CYG+BMQWp8}aw70_ z*nPTJ5WFF4wVL5s{}W6F=;Ck#lf@)(l~d}jIdNJnIQp1~-Jfdh86z4A%w)67LGX+Y tDg=HDh`I0)%m$?1&DLM7S04c2518gVB@i*Md)fd1002ovPDHLkV1fumwHW{a diff --git a/src/main/resources/assets/create/textures/block/andesite_funnel_plating.png b/src/main/resources/assets/create/textures/block/andesite_funnel_plating.png index dd858ec5ec5d29ed81260db619549e91e56ad2e2..2d24fe7312f14926632abab5da6cb63998282328 100644 GIT binary patch delta 1376 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 FV1jX_i3b1x diff --git a/src/main/resources/assets/create/textures/block/andesite_tunnel.png b/src/main/resources/assets/create/textures/block/andesite_tunnel.png index 398c50661caf5f02504bb1e1f67cdd0560716f39..3e3042ec0e8dbb15507527ee4bd74aaf26c35087 100644 GIT binary patch delta 2487 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 B#hCyA delta 2491 zcmV;s2}JgX6pIv)R)3&LL_t(|UhP_IY#dh=KKtJFzPwIs$BCVkG>Y9cZGsvj;13EQ zp-LbXRftxV_|wt~_)(-5wNOwRA<=^PQ3*s-ADJ8l{eoj^Jbd}ad+3k&3Q+P+Qk#n6fXcG{vK*m+rb|9}N!tWYk$A~`@pz)lW$>6b6_i`5_3qnER(@@-#FtQ6_wGG>Y+eYJ%fF)(pdXe%+!fXZ z%N&#N(;wJ|wnjHGi!^u+YIdK4iOcYctB_-!UGrRQb&*t6<0$0NpI;j)%|+X{I0`DeAy-hU6(hF9LGBvR@n_3Ostzx=I} zUt%r!j>n&Tyle{!WPJ@77a3TWZ;5T?W5nOoREp~A7Pq9hrZ0P$k3MW*Mn}fD4=^vT zB7e~^xBKtCuVQ@1GtWI!w4hNtRxoR_>(W)eiA*g<;Ddp-z0EYNmZE@UV!3wxdOs^t z_?NGIM05S8==#kmJ~wY>wrvT~mIGg-)_wPJVq1y-$ZLP+b2Hv}>MP6mPL3hTTxkM$p^wJxFz+MLgeOCOEX;5AaRTSgC8i32-At)*| z?^tw`AOskH#CT#n_qvBU0eWvtHV_=5Q_@UHA8(pAC)9Kd@Ph= zd}uN;tskwNfToivZspvJ`~Cl>H{QBP3z-EXuajI(2P*&@n+Fc;A?J>E9%p>65#ZnT zgWt0P^e)C9FZOG1zwoVPd?yaz0b)_KW256-OT+Q#_*MGk<3YX#7_AF#)AlCLsxy73 z$Tik~O?9(9H229liX?j|aO;w4uTX5}GL3YfAZ_4%a*ke5(nSX!_#EF)_%wKq+`}Jm z-%6XAs0!Qg#5uZk@$FUl=1P*liq9c{ni(?U>C>mF>%xZ|gWX-{S^BQ_(~W_C{#cAT zbLI>SGARb_kRrh#1#5g13VP`?J8F5X#H{e)F@ELd zzz_d)j^68?bU^<4;V8>jfBQ~xPw(}(SLI{pXa0i# z)VQsI1+I!#Am9M^BH<8vUBD{u>c z2tSw0lgI6*>DkIDRTubZZlvow*)Q6@8|ydgySf|EkZ8(=jkQTSQ)0k;D}BUe}q?Mm^T63akx zI?ns)cmHvglO9USaC;<0v~YX0AObRfV*pWQ)A^@Qt%d zqtap?$1xzu2Y?H@of;<>0qTT46$0o(@=0eFYjbc_k3LR3&&Z#dE4AQ5-~S#jXkfu> zgYk;n(MF>dpk#LBo)OfYA%;z;qt9AR$@dOQzPt(v?TurkxD!k@s za5SY9qmiZr&j8oVpNuc=8-9I%>Vk&3`^42D3LgGO8t$7&r7OF{HF&gsFSRzMTLP$ad@~V*7|KNA| zKCpt3A80+y9D!IFzzZj@yi-xW<5#b|q9NfKVI~1kj(K}53P4^Ej{)R=pOD7z0?b|| zYl*ewJAU!(UKW8Zm9gXS?)0HQRbf~*v2>;ugG|8G7k0Gc@dhvWaV z0-$-L2Y6M|0}6!&%4XA?Nb@T8+-lkZ63GMwf>Clg7C70K^IS9RmgI^duvQ*mR{?fQ za#ddyh6mUwiQO^(7qA0=Now#e&v-WtcAaF2_nj%qWY0gjTn10%DNs$}7{4wQU{zAH z`hCD{OJdcEI*XE+)$apVEQwV!;Kt^X*h;?-uquhI3lHe(K3QB839Nn}kW}j+SRKg{ zyIP>?6=1idR`m*ym^PNg5CX71WMC}C`5>9rtV?42w~B$RZZ3&`u?HyYx9+TGfd?2- zQWDeKss%g%Q<||PhIohd`)*9owV_G&08E3HB{4o*2QZezb~S|A10eE01x$mMB{BY6 z#lTdCjhL|{HZYXr?4OFy7H0v(zhy~`|5iB=0>+Y9O=NNI$4r1(0INcTz->!n)d<8f zU@VDA4ge7UG7DH@Z(V(XzEfL1ImApw}J4;cG^s#kzrtebT} zx!6>I-fmcIDnM^HEH)LOw;L9l3eejPi%kXS?FI$We*jrif+%2?-f;i`002ovPDHLk FV1fz8t~USx diff --git a/src/main/resources/assets/create/textures/block/andesite_tunnel_top.png b/src/main/resources/assets/create/textures/block/andesite_tunnel_top.png index 272c1cf07e8493f4cd55e162991563fe0dffdd25..606dabda8e30602019e5da3631655f02732ace04 100644 GIT binary patch delta 172 zcmV;d08{^|0;vL!g@3{T01m>R(xC~) zPAu@%Jj9RHX(4Y_IyYmjVcRSCV5z;sG;A}Y++V1uctjIdV4@gmR8t66&h0000)dj4>>b9+FPXe~GxO$s^UdtL6T|m<9FiCq`F{dqL@Je{a5(IGS)4!K zK%w$7*UP_0p|}(MkA>xqtpNf}z?`0ZHJwqmuXBsCCivq33&FRaeNvNp157?}e|SbE z#;G5^`s$I;V|cCJM{M0s7Bph;=u4_lbSruLrE*I6x`T-_@8SC(C2< z0mQK7J}R6Z!)x_ES4@sk1W+Ce$?2cNW?X&|%e5WlS;u;DfN&i3V^}hT5N@wDh?}vU zPGdt$Q5#K6f26kN-A;L#CDIw2q@|OWhjKOudN7YbB7c<*95gXCPKWmFckVo&5;Zk7 zbmmAM4q)qqx-Ja{`ogSaDx0*}t9bN!!8`H5%g;zEKxpXg4PZmy&%^;!P=I7_t z8;Qr`-do|5vjs`rN_dKdLLv1=pvd5x1!3E^H-G0nLIBB4U=lj8FANZ>T3c;jENd!;_iUprs zKRvJ^1^Cx4pG_u{s&BFki%(NgQK4)h@S3_!A@xZDCM!QRMFcjV&&W{#Ma6_@G`dE< zpmktn7`pEfsH&=RduDJYglgxGMcq-NE2p+m@6pY!x7NSdxi!bX(DCPQposPEa1ONX zRlfzOhNgOe*9(%@&$iP0u@7``*FII4@YBoXRrk4Qq5QhjYK+VA>DW^#C(&sjDpj delta 888 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 b&s%>3