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
|
@ -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
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"ceiling=false": {
|
||||
"model": "create:block/mechanical_arm/block"
|
||||
},
|
||||
"ceiling=true": {
|
||||
"model": "create:block/mechanical_arm/block",
|
||||
"x": 180
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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": "一对大家伙",
|
||||
|
|
|
@ -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"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -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"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -700,7 +700,11 @@ public class AllBlocks {
|
|||
|
||||
public static final BlockEntry<ArmBlock> 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())
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -118,6 +118,13 @@ 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();
|
||||
|
@ -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++) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -61,7 +61,7 @@ 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)
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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<ArmTileEntity> {
|
||||
|
||||
public static final BooleanProperty CEILING = BooleanProperty.create("ceiling");
|
||||
|
||||
public ArmBlock(Properties properties) {
|
||||
super(properties);
|
||||
setDefaultState(getDefaultState().with(CEILING, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillStateContainer(Builder<Block, BlockState> 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<ArmTileEntity> {
|
|||
}
|
||||
|
||||
@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<ArmTileEntity> {
|
|||
@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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<IItemHandler> cachedHandler;
|
||||
private ArmAngleTarget cachedAngles;
|
||||
|
||||
private static ImmutableMap<ArmInteractionPoint, Supplier<ArmInteractionPoint>> POINTS =
|
||||
ImmutableMap.<ArmInteractionPoint, Supplier<ArmInteractionPoint>>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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<BlockPos, ArmInteractionPoint> currentSelection = new HashMap<>();
|
||||
static List<ArmInteractionPoint> 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;
|
||||
}
|
||||
|
@ -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<BlockPos, ArmInteractionPoint> selection) {
|
||||
private static void drawOutlines(Collection<ArmInteractionPoint> selection) {
|
||||
World world = Minecraft.getInstance().world;
|
||||
for (Iterator<Entry<BlockPos, ArmInteractionPoint>> iterator = selection.entrySet()
|
||||
.iterator(); iterator.hasNext();) {
|
||||
Entry<BlockPos, ArmInteractionPoint> entry = iterator.next();
|
||||
BlockPos pos = entry.getKey();
|
||||
for (Iterator<ArmInteractionPoint> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
@ -46,23 +65,26 @@ public class ArmRenderer extends KineticTileEntityRenderer {
|
|||
|
||||
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);
|
||||
|
|
|
@ -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<ArmInteractionPoint> 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,8 +80,8 @@ public class AllAdvancements implements IDataProvider {
|
|||
|
||||
andesiteExpertLane(t, andesite_casing);
|
||||
|
||||
Advancement drill =
|
||||
kinecticAdvancement("mechanical_drill", AllBlocks.MECHANICAL_DRILL.get(), TaskType.NORMAL).withParent(andesite_casing)
|
||||
Advancement drill = kinecticAdvancement("mechanical_drill", AllBlocks.MECHANICAL_DRILL.get(), TaskType.NORMAL)
|
||||
.withParent(andesite_casing)
|
||||
.register(t, id + ":mechanical_drill");
|
||||
|
||||
Advancement press =
|
||||
|
@ -98,7 +98,8 @@ 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)
|
||||
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)
|
||||
|
@ -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");
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"},
|
||||
|
|
Before Width: | Height: | Size: 978 B After Width: | Height: | Size: 984 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 297 B After Width: | Height: | Size: 297 B |
Before Width: | Height: | Size: 948 B After Width: | Height: | Size: 952 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |