Why are we still here, Part IV

- Mixers can no longer process single-item recipes
- Added processing recipes for items in AE2
- Fixed pams harvestcraft recipe catalysts not recycling properly
- Windmill bearings no longer assemble when the attached kinetics update
- Hose pulleys now display additional goggle info when their target fluid body is considered infinite
- Protected the natural scoria model from vertex-format changes made by optifine
- Andesite tunnels now split off single items to side outputs
- Fixed non-interpolated item animation on the Mechanical Saw
- Attempted fix to oriented contraption causing serialization issues
- Fixed mounted contraptions not updating yaw interpolation when stalled
- Fixed "shifting gears" advancement not triggering when using the cogwheel placement assist
- Schematicannons no longer cause pasted kinetic networks to be virtually interconnected
- Added sandstone -> sand; milling/crushing recipe
- Fixed Spouts duplicating container items in some configurations
- Fixed block cutting recipe outputs piling up beyond the gui boundaries
This commit is contained in:
simibubi 2021-01-03 22:29:55 +01:00
parent f611102bf3
commit 1498cb1cfc
55 changed files with 687 additions and 286 deletions

View file

@ -22,7 +22,7 @@ boolean dev = System.getenv('RELEASE') == null || System.getenv('RELEASE').equal
ext.buildnumber = 0
project.buildnumber = System.getenv('BUILD_NUMBER') != null ? System.getenv('BUILD_NUMBER') : "custom"
version = "mc${minecraft_version}_v${mod_version}" + (dev ? "+${buildnumber}" : '')
version = "mc${minecraft_version}_v${mod_version}"
group = 'com.simibubi.create'
archivesBaseName = 'create'

View file

@ -398,16 +398,16 @@ a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.j
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
ff5ca8ad030f1dd58a05c2fef2c3788292db5bd1 assets/create/lang/en_ud.json
211b6a54a5e9eca29d4112aeb98796b250bd1ac7 assets/create/lang/en_us.json
0ffb102de8e43fb20a7efbd5887e01f6708642a1 assets/create/lang/unfinished/de_de.json
f1ae1b2b0e4b686bdee17cf357fb999462a90a56 assets/create/lang/unfinished/fr_fr.json
8634445232b6492effe3c790a6a6abdfc606d8c1 assets/create/lang/unfinished/it_it.json
c7ba4d035c7382b9c1f9dc0f4f310a1714b59fea assets/create/lang/unfinished/ja_jp.json
e484dee6af6788321928691164ae8b78a827afd4 assets/create/lang/unfinished/ko_kr.json
8bcf3a906818d89ebc9abb7ba35889d9ddc4ed32 assets/create/lang/unfinished/nl_nl.json
015c286766cf66b8482f08636b6c2ab5924d2bf6 assets/create/lang/unfinished/pt_br.json
7e337a8928f40aa29c69682b26190c134adbddb1 assets/create/lang/unfinished/ru_ru.json
9e5e9e4583543468ad3f7fe16c12dcfbad68d8cb assets/create/lang/unfinished/zh_cn.json
a8ad953d1d7cbdad4a962aa578c498ecdd7a1ec0 assets/create/lang/en_us.json
5f151d6f69aadf7b206468174e303b96349c74e4 assets/create/lang/unfinished/de_de.json
8a146456612f307e39f6cada321d528c0f626daf assets/create/lang/unfinished/fr_fr.json
2230f25d6f42a54072b184f8dc7fb372e33a0ad5 assets/create/lang/unfinished/it_it.json
72b83aa84cd6b5688c2ff88d63e54b6fee6e9e0b assets/create/lang/unfinished/ja_jp.json
0e1f1922cc50cce5839b3bf71f32750ac605a578 assets/create/lang/unfinished/ko_kr.json
dec3bf706c1810e7d0840f9d7b19c563ca5b7af5 assets/create/lang/unfinished/nl_nl.json
d67a1d50c33da6577aad12c7b3e47c8d75fb2999 assets/create/lang/unfinished/pt_br.json
8697e07ce453d4aad2af91a2a142f04d77cd44d7 assets/create/lang/unfinished/ru_ru.json
2c86a2f313e2650ec02c8368b1ea728a65fbc530 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
@ -1622,6 +1622,7 @@ fc07b75f81782fa06990c7eb7febc635621df91a data/create/advancements/recipes/buildi
e2475d1fad9aaa82e99415a2a5d07a2343ce84a6 data/create/advancements/recipes/building_blocks/blasting/nickel_ingot_compat_thermal.json
f994f545e3a1990448e852c556d94f7eaf9954a0 data/create/advancements/recipes/building_blocks/blasting/platinum_ingot_compat_silents_mechanisms.json
85b1a8c173ca7e5421f9d2bd0f3f997c8431d15c data/create/advancements/recipes/building_blocks/blasting/quicksilver_ingot_compat_mysticalworld.json
a61045a27757950d96fee77768bfd96f935f98b2 data/create/advancements/recipes/building_blocks/blasting/silver_ingot_compat_iceandfire.json
9b48187d487ddabcad4f4e4f75b67813f26a746d data/create/advancements/recipes/building_blocks/blasting/silver_ingot_compat_mysticalworld.json
96bf046af4d23dddcca5915cfbfc04a46b0d2912 data/create/advancements/recipes/building_blocks/blasting/silver_ingot_compat_silents_mechanisms.json
96a3efecf663433123861136467d9fa28ea26a1e data/create/advancements/recipes/building_blocks/blasting/silver_ingot_compat_thermal.json
@ -1648,6 +1649,7 @@ cdf4697b74e4a6add2ea41825733f4d9ff2b83e6 data/create/advancements/recipes/buildi
6dff1a0b51d7a81d6a4e8f4fd8fa558f9befea1b data/create/advancements/recipes/building_blocks/smelting/nickel_ingot_compat_thermal.json
70d98f34671f09331f6765447b95cd00c3b8d4e5 data/create/advancements/recipes/building_blocks/smelting/platinum_ingot_compat_silents_mechanisms.json
8e5beb04ea241145f4e34320cba1745fd9d386e6 data/create/advancements/recipes/building_blocks/smelting/quicksilver_ingot_compat_mysticalworld.json
6c6fd69e9efb6a1bda750c6d73109c98e774a498 data/create/advancements/recipes/building_blocks/smelting/silver_ingot_compat_iceandfire.json
60fd25d05bfe101d83e3a13678cca9940665771c data/create/advancements/recipes/building_blocks/smelting/silver_ingot_compat_mysticalworld.json
29685c6f05455faa657cb51433352d005b798cf4 data/create/advancements/recipes/building_blocks/smelting/silver_ingot_compat_silents_mechanisms.json
05b68914ac2fb0da7609a32369bf739e28256e41 data/create/advancements/recipes/building_blocks/smelting/silver_ingot_compat_thermal.json
@ -2689,6 +2691,7 @@ aeb345e5b4c266ac9e2ef6929b153cb535468d01 data/create/recipes/blasting/lead_ingot
bd26be2cc7044537628e10ff057a7ce78b720025 data/create/recipes/blasting/nickel_ingot_compat_thermal.json
a99be7aae1706cce96a3b6fadd38295bb53d10b7 data/create/recipes/blasting/platinum_ingot_compat_silents_mechanisms.json
3419a88787e331d59e0da8b9084d8c8a72a84ec0 data/create/recipes/blasting/quicksilver_ingot_compat_mysticalworld.json
88ee97cacce93436dcb6d2cb37219435bcaaf3cb data/create/recipes/blasting/silver_ingot_compat_iceandfire.json
84b73c8ef561ab0ecc2954cd86160595975811d6 data/create/recipes/blasting/silver_ingot_compat_mysticalworld.json
3ce20049c90fc3ce446efac1d166b5e1b2855980 data/create/recipes/blasting/silver_ingot_compat_silents_mechanisms.json
c49e88f38ad624a56865bb293e2b81da09ebdf37 data/create/recipes/blasting/silver_ingot_compat_thermal.json
@ -3184,6 +3187,7 @@ ea6fb7e30fa22cd87ff4760288e11f909b78ac86 data/create/recipes/milling/red_tulip.j
bda581c2039f41f7d55527814a46903f10da7e05 data/create/recipes/milling/rose_bush.json
54be62a1bf098a370d315f79068ec326e4f4d6c2 data/create/recipes/milling/saddle.json
8bc6124293f4efb5f2d0fa4a3166c6d00a88a14c data/create/recipes/milling/sand.json
42c5837c16132632da52325cddea3cdbb318e822 data/create/recipes/milling/sandstone.json
87e30347cc28aa5fb2daefae4c25fa81ce92b0f1 data/create/recipes/milling/silver_ore.json
1e14bd30032aab6dfaff5bca50c791332ffc1aaa data/create/recipes/milling/sugar_cane.json
af2beca9f934601ad029f34bad08be3cee07f6b4 data/create/recipes/milling/sunflower.json
@ -3395,6 +3399,7 @@ bf0e5df5a88e583e39a4e14b006cbf33b99611e1 data/create/recipes/smelting/limestone.
92c308baf81fe2c8a63c90b0dfc7cf8cc2183c4b data/create/recipes/smelting/quicksilver_ingot_compat_mysticalworld.json
2c230522bb0946bde6a51442cb15c5efeea99b15 data/create/recipes/smelting/scoria.json
f5317c85a9e10a5f9346e13aef8bb364a5203346 data/create/recipes/smelting/scoria_from_natural.json
893a857a02ef643296473148216da05102a09e05 data/create/recipes/smelting/silver_ingot_compat_iceandfire.json
96c2b799b812e469bb1785200d68c1e8f8cfacf7 data/create/recipes/smelting/silver_ingot_compat_mysticalworld.json
21c5fbce648ca8812d4c75e3c71934bc269e2216 data/create/recipes/smelting/silver_ingot_compat_silents_mechanisms.json
c01f5fdef7419a2da5e0f24d61637ec35a006fd1 data/create/recipes/smelting/silver_ingot_compat_thermal.json
@ -3418,6 +3423,7 @@ c4d680eed98791fe45fa93aeeae9e8dbd508d6f5 data/create/recipes/splashing/gravel.js
7af4d9ae50af13da0d4fc814687f9586ff872798 data/create/recipes/splashing/gray_concrete_powder.json
23fb61c0e4bcca58fa7241db9cbef07bf4bd9a9b data/create/recipes/splashing/green_concrete_powder.json
0a15fffe26190b78d2177c8302c92fc2232ce398 data/create/recipes/splashing/ice.json
42e05e89ad9c83bd74ea67878930056ee0491fa8 data/create/recipes/splashing/iceandfire/crushed_silver_ore.json
1c978c74c949e9325a4078f25d8b39ed2d70f4a0 data/create/recipes/splashing/immersiveengineering/crushed_aluminum_ore.json
10ce4f124a8caf28027f4976f49a54561bfb7d18 data/create/recipes/splashing/immersiveengineering/crushed_lead_ore.json
ab433eb5d0739ca5932588f48308151d7e0bacc2 data/create/recipes/splashing/immersiveengineering/crushed_nickel_ore.json

View file

@ -1084,6 +1084,8 @@
"create.tooltip.chute.fans_pull_up": "Fans pull from Above",
"create.tooltip.chute.fans_pull_down": "Fans pull from Below",
"create.hint.hose_pulley.title": "Bottomless Supply",
"create.hint.hose_pulley": "The targeted body of fluid is considered infinite.",
"create.hint.mechanical_arm_no_targets.title": "No Targets",
"create.hint.mechanical_arm_no_targets": "It appears this _Mechanical_ _Arm_ has not been assigned any _targets._ Select belts, depots, funnels and other blocks by _right-clicking_ them while _holding_ the _Mechanical_ _Arm_ in your _hand_.",
"create.hint.horizontal_funnel.title": "Horizontal Funnels",
@ -1503,7 +1505,7 @@
"block.create.reinforced_rail.tooltip.summary": "A timber stabilized rail, _does not need supports_.",
"block.create.mechanical_mixer.tooltip": "MECHANICAL MIXER",
"block.create.mechanical_mixer.tooltip.summary": "A kinetic whisk for applying any shapeless crafting recipes to items beneath it. Requires constant _Rotational Force_ and a _Basin_ placed below (with a gap in between).",
"block.create.mechanical_mixer.tooltip.summary": "A kinetic whisk providing automated shapeless crafting recipes of multiple ingredients. Requires constant _Rotational Force_ and a _Basin_ placed below (with a gap in between).",
"block.create.mechanical_mixer.tooltip.condition1": "When above Basin",
"block.create.mechanical_mixer.tooltip.behaviour1": "Starts to mix items in the basin whenever all necessary ingredients are present. To prevent unwanted recipes, use the filter slot on the basin or cut the rotational force until all desired ingredients have been added.",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1209",
"_": "Missing Localizations: 1211",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1085,6 +1085,8 @@
"create.tooltip.chute.fans_pull_up": "UNLOCALIZED: Fans pull from Above",
"create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below",
"create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply",
"create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.",
"create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets",
"create.hint.mechanical_arm_no_targets": "UNLOCALIZED: It appears this _Mechanical_ _Arm_ has not been assigned any _targets._ Select belts, depots, funnels and other blocks by _right-clicking_ them while _holding_ the _Mechanical_ _Arm_ in your _hand_.",
"create.hint.horizontal_funnel.title": "UNLOCALIZED: Horizontal Funnels",
@ -1504,7 +1506,7 @@
"block.create.reinforced_rail.tooltip.summary": "UNLOCALIZED: A timber stabilized rail, _does not need supports_.",
"block.create.mechanical_mixer.tooltip": "UNLOCALIZED: MECHANICAL MIXER",
"block.create.mechanical_mixer.tooltip.summary": "UNLOCALIZED: A kinetic whisk for applying any shapeless crafting recipes to items beneath it. Requires constant _Rotational Force_ and a _Basin_ placed below (with a gap in between).",
"block.create.mechanical_mixer.tooltip.summary": "UNLOCALIZED: A kinetic whisk providing automated shapeless crafting recipes of multiple ingredients. Requires constant _Rotational Force_ and a _Basin_ placed below (with a gap in between).",
"block.create.mechanical_mixer.tooltip.condition1": "UNLOCALIZED: When above Basin",
"block.create.mechanical_mixer.tooltip.behaviour1": "UNLOCALIZED: Starts to mix items in the basin whenever all necessary ingredients are present. To prevent unwanted recipes, use the filter slot on the basin or cut the rotational force until all desired ingredients have been added.",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 860",
"_": "Missing Localizations: 862",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1085,6 +1085,8 @@
"create.tooltip.chute.fans_pull_up": "UNLOCALIZED: Fans pull from Above",
"create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below",
"create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply",
"create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.",
"create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets",
"create.hint.mechanical_arm_no_targets": "UNLOCALIZED: It appears this _Mechanical_ _Arm_ has not been assigned any _targets._ Select belts, depots, funnels and other blocks by _right-clicking_ them while _holding_ the _Mechanical_ _Arm_ in your _hand_.",
"create.hint.horizontal_funnel.title": "UNLOCALIZED: Horizontal Funnels",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 844",
"_": "Missing Localizations: 846",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1085,6 +1085,8 @@
"create.tooltip.chute.fans_pull_up": "UNLOCALIZED: Fans pull from Above",
"create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below",
"create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply",
"create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.",
"create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets",
"create.hint.mechanical_arm_no_targets": "UNLOCALIZED: It appears this _Mechanical_ _Arm_ has not been assigned any _targets._ Select belts, depots, funnels and other blocks by _right-clicking_ them while _holding_ the _Mechanical_ _Arm_ in your _hand_.",
"create.hint.horizontal_funnel.title": "UNLOCALIZED: Horizontal Funnels",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 843",
"_": "Missing Localizations: 845",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1085,6 +1085,8 @@
"create.tooltip.chute.fans_pull_up": "UNLOCALIZED: Fans pull from Above",
"create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below",
"create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply",
"create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.",
"create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets",
"create.hint.mechanical_arm_no_targets": "UNLOCALIZED: It appears this _Mechanical_ _Arm_ has not been assigned any _targets._ Select belts, depots, funnels and other blocks by _right-clicking_ them while _holding_ the _Mechanical_ _Arm_ in your _hand_.",
"create.hint.horizontal_funnel.title": "UNLOCALIZED: Horizontal Funnels",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 48",
"_": "Missing Localizations: 50",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1085,6 +1085,8 @@
"create.tooltip.chute.fans_pull_up": "선풍기가 위에서 당김",
"create.tooltip.chute.fans_pull_down": "선풍기가 아래에서 당김",
"create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply",
"create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.",
"create.hint.mechanical_arm_no_targets.title": "목표 없음",
"create.hint.mechanical_arm_no_targets": "이 _기계 팔_은 _목표_가 설정되지 않은 것 같습니다. _기계 팔을 손에 들고_ 벨트, 아이템 거치대, 깔때기를 _우클릭_하여 목표로 지정하세요.",
"create.hint.horizontal_funnel.title": "깔때기가 수평임",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1150",
"_": "Missing Localizations: 1152",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1085,6 +1085,8 @@
"create.tooltip.chute.fans_pull_up": "UNLOCALIZED: Fans pull from Above",
"create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below",
"create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply",
"create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.",
"create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets",
"create.hint.mechanical_arm_no_targets": "UNLOCALIZED: It appears this _Mechanical_ _Arm_ has not been assigned any _targets._ Select belts, depots, funnels and other blocks by _right-clicking_ them while _holding_ the _Mechanical_ _Arm_ in your _hand_.",
"create.hint.horizontal_funnel.title": "UNLOCALIZED: Horizontal Funnels",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1216",
"_": "Missing Localizations: 1218",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1085,6 +1085,8 @@
"create.tooltip.chute.fans_pull_up": "UNLOCALIZED: Fans pull from Above",
"create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below",
"create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply",
"create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.",
"create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets",
"create.hint.mechanical_arm_no_targets": "UNLOCALIZED: It appears this _Mechanical_ _Arm_ has not been assigned any _targets._ Select belts, depots, funnels and other blocks by _right-clicking_ them while _holding_ the _Mechanical_ _Arm_ in your _hand_.",
"create.hint.horizontal_funnel.title": "UNLOCALIZED: Horizontal Funnels",
@ -1504,7 +1506,7 @@
"block.create.reinforced_rail.tooltip.summary": "UNLOCALIZED: A timber stabilized rail, _does not need supports_.",
"block.create.mechanical_mixer.tooltip": "UNLOCALIZED: MECHANICAL MIXER",
"block.create.mechanical_mixer.tooltip.summary": "UNLOCALIZED: A kinetic whisk for applying any shapeless crafting recipes to items beneath it. Requires constant _Rotational Force_ and a _Basin_ placed below (with a gap in between).",
"block.create.mechanical_mixer.tooltip.summary": "UNLOCALIZED: A kinetic whisk providing automated shapeless crafting recipes of multiple ingredients. Requires constant _Rotational Force_ and a _Basin_ placed below (with a gap in between).",
"block.create.mechanical_mixer.tooltip.condition1": "UNLOCALIZED: When above Basin",
"block.create.mechanical_mixer.tooltip.behaviour1": "UNLOCALIZED: Starts to mix items in the basin whenever all necessary ingredients are present. To prevent unwanted recipes, use the filter slot on the basin or cut the rotational force until all desired ingredients have been added.",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 519",
"_": "Missing Localizations: 521",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1085,6 +1085,8 @@
"create.tooltip.chute.fans_pull_up": "UNLOCALIZED: Fans pull from Above",
"create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below",
"create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply",
"create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.",
"create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets",
"create.hint.mechanical_arm_no_targets": "UNLOCALIZED: It appears this _Mechanical_ _Arm_ has not been assigned any _targets._ Select belts, depots, funnels and other blocks by _right-clicking_ them while _holding_ the _Mechanical_ _Arm_ in your _hand_.",
"create.hint.horizontal_funnel.title": "UNLOCALIZED: Horizontal Funnels",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1",
"_": "Missing Localizations: 3",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1085,6 +1085,8 @@
"create.tooltip.chute.fans_pull_up": "鼓风机从下方进行吸引",
"create.tooltip.chute.fans_pull_down": "鼓风机从上方进行吸引",
"create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply",
"create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.",
"create.hint.mechanical_arm_no_targets.title": "没有目标",
"create.hint.mechanical_arm_no_targets": "看起来这个_动力臂_没有被分配任何_目标_。在手持机械臂的同时右键选取传送带、置物台、漏斗或其他设备来设置目标。",
"create.hint.horizontal_funnel.title": "水平漏斗",

View file

@ -0,0 +1,14 @@
{
"type": "create:milling",
"ingredients": [
{
"item": "minecraft:sandstone"
}
],
"results": [
{
"item": "minecraft:sand"
}
],
"processingTime": 150
}

View file

@ -24,7 +24,6 @@ import com.simibubi.create.foundation.data.LangMerger;
import com.simibubi.create.foundation.data.recipe.MechanicalCraftingRecipeGen;
import com.simibubi.create.foundation.data.recipe.ProcessingRecipeGen;
import com.simibubi.create.foundation.data.recipe.StandardRecipeGen;
import com.simibubi.create.foundation.entity.CreateDataSerializers;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.worldgen.AllWorldFeatures;
import com.tterrag.registrate.util.NonNullLazyValue;
@ -93,7 +92,6 @@ public class Create {
modEventBus.addListener(EventPriority.LOWEST, this::gatherData);
AllConfigs.register();
CreateDataSerializers.register();
random = new Random();
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> CreateClient.addClientListeners(modEventBus));

View file

@ -114,8 +114,9 @@ public class CreateJEI implements IModPlugin {
.build(),
autoShapeless = register("automatic_shapeless", MixingCategory::autoShapeless)
.recipes(r -> r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS
&& !MechanicalPressTileEntity.canCompress(r.getIngredients()), BasinRecipe::convertShapeless)
.recipes(r -> r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS && r.getIngredients()
.size() > 1 && !MechanicalPressTileEntity.canCompress(r.getIngredients()),
BasinRecipe::convertShapeless)
.catalyst(AllBlocks.MECHANICAL_MIXER::get)
.catalyst(AllBlocks.BASIN::get)
.enableWhen(c -> c.allowShapelessInMixer)
@ -171,6 +172,8 @@ public class CreateJEI implements IModPlugin {
.build(),
autoShaped = register("automatic_shaped", MechanicalCraftingCategory::new)
.recipes(r -> r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS && r.getIngredients()
.size() == 1)
.recipes(
r -> (r.getType() == IRecipeType.CRAFTING && r.getType() != AllRecipeTypes.MECHANICAL_CRAFTING.type)
&& (r instanceof ShapedRecipe))

View file

@ -46,20 +46,20 @@ public class BlockCuttingCategory extends CreateRecipeCategory<CondensedBlockCut
itemStacks.init(0, true, 4, 4);
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks()));
List<ItemStack> results = recipe.getOutputs();
List<List<ItemStack>> results = recipe.getCondensedOutputs();
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) {
int xOffset = (outputIndex % 5) * 19;
int yOffset = (outputIndex / 5) * -19;
itemStacks.init(outputIndex + 1, false, 77 + xOffset, 47 + yOffset);
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
itemStacks.set(outputIndex + 1, results.get(outputIndex));
}
}
@Override
public void draw(CondensedBlockCuttingRecipe recipe, double mouseX, double mouseY) {
AllGuiTextures.JEI_SLOT.draw(4, 4);
int size = recipe.getOutputs().size();
int size = Math.min(recipe.getOutputs().size(), 15);
for (int i = 0; i < size; i++) {
int xOffset = (i % 5) * 19;
int yOffset = (i / 5) * -19;
@ -84,6 +84,23 @@ public class BlockCuttingCategory extends CreateRecipeCategory<CondensedBlockCut
public List<ItemStack> getOutputs() {
return outputs;
}
public List<List<ItemStack>> getCondensedOutputs() {
List<List<ItemStack>> result = new ArrayList<>();
int index = 0;
boolean firstPass = true;
for (ItemStack itemStack : outputs) {
if (firstPass)
result.add(new ArrayList<>());
result.get(index).add(itemStack);
index++;
if (index >= 15) {
index = 0;
firstPass = false;
}
}
return result;
}
public static List<CondensedBlockCuttingRecipe> condenseRecipes(List<IRecipe<?>> stoneCuttingRecipes) {
List<CondensedBlockCuttingRecipe> condensed = new ArrayList<>();

View file

@ -8,6 +8,7 @@ import java.util.stream.Collectors;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.compat.jei.category.animations.AnimatedCrafter;
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.constants.VanillaTypes;
@ -23,13 +24,14 @@ import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Rarity;
import net.minecraft.item.crafting.ICraftingRecipe;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.util.NonNullList;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextFormatting;
public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecipe> {
public class MechanicalCraftingCategory extends CreateRecipeCategory<ICraftingRecipe> {
private final AnimatedCrafter crafter = new AnimatedCrafter();
@ -38,13 +40,13 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecip
}
@Override
public void setIngredients(ShapedRecipe recipe, IIngredients ingredients) {
public void setIngredients(ICraftingRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients());
ingredients.setOutput(VanillaTypes.ITEM, recipe.getRecipeOutput());
}
@Override
public void setRecipe(IRecipeLayout recipeLayout, ShapedRecipe recipe, IIngredients ingredients) {
public void setRecipe(IRecipeLayout recipeLayout, ICraftingRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
NonNullList<Ingredient> recipeIngredients = recipe.getIngredients();
@ -61,8 +63,8 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecip
for (int i = 0; i < size; i++) {
float f = 19 * scale;
int slotSize = (int) (16 * scale);
int xPosition = (int) (x + 1 + (i % recipe.getWidth()) * f);
int yPosition = (int) (y + 1 + (i / recipe.getWidth()) * f);
int xPosition = (int) (x + 1 + (i % getWidth(recipe)) * f);
int yPosition = (int) (y + 1 + (i / getWidth(recipe)) * f);
itemStacks.init(i + 1, true, renderer, xPosition, yPosition, slotSize, slotSize, 0, 0);
itemStacks.set(i + 1, Arrays.asList(recipeIngredients.get(i)
.getMatchingStacks()));
@ -72,30 +74,38 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecip
static int maxSize = 100;
public static float getScale(ShapedRecipe recipe) {
int w = recipe.getWidth();
int h = recipe.getHeight();
public static float getScale(ICraftingRecipe recipe) {
int w = getWidth(recipe);
int h = getHeight(recipe);
return Math.min(1, maxSize / (19f * Math.max(w, h)));
}
public static int getYPadding(ShapedRecipe recipe) {
return 3 + 50 - (int) (getScale(recipe) * recipe.getHeight() * 19 * .5);
public static int getYPadding(ICraftingRecipe recipe) {
return 3 + 50 - (int) (getScale(recipe) * getHeight(recipe) * 19 * .5);
}
public static int getXPadding(ShapedRecipe recipe) {
return 3 + 50 - (int) (getScale(recipe) * recipe.getWidth() * 19 * .5);
public static int getXPadding(ICraftingRecipe recipe) {
return 3 + 50 - (int) (getScale(recipe) * getWidth(recipe) * 19 * .5);
}
private static int getWidth(ICraftingRecipe recipe) {
return recipe instanceof ShapedRecipe ? ((ShapedRecipe) recipe).getWidth() : 1;
}
private static int getHeight(ICraftingRecipe recipe) {
return recipe instanceof ShapedRecipe ? ((ShapedRecipe) recipe).getHeight() : 1;
}
@Override
public void draw(ShapedRecipe recipe, double mouseX, double mouseY) {
public void draw(ICraftingRecipe recipe, double mouseX, double mouseY) {
RenderSystem.pushMatrix();
float scale = getScale(recipe);
RenderSystem.translated(getXPadding(recipe), getYPadding(recipe), 0);
for (int row = 0; row < recipe.getHeight(); row++)
for (int col = 0; col < recipe.getWidth(); col++)
for (int row = 0; row < getHeight(recipe); row++)
for (int col = 0; col < getWidth(recipe); col++)
if (!recipe.getIngredients()
.get(row * recipe.getWidth() + col)
.get(row * getWidth(recipe) + col)
.hasNoMatchingItems()) {
RenderSystem.pushMatrix();
RenderSystem.translated(col * 19 * scale, row * 19 * scale, 0);
@ -126,15 +136,15 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecip
}
@Override
public Class<? extends ShapedRecipe> getRecipeClass() {
return ShapedRecipe.class;
public Class<? extends ICraftingRecipe> getRecipeClass() {
return ICraftingRecipe.class;
}
private static final class CrafterIngredientRenderer implements IIngredientRenderer<ItemStack> {
private final ShapedRecipe recipe;
private final ICraftingRecipe recipe;
public CrafterIngredientRenderer(ShapedRecipe recipe) {
public CrafterIngredientRenderer(ICraftingRecipe recipe) {
this.recipe = recipe;
}

View file

@ -206,7 +206,9 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
@Override
protected <C extends IInventory> boolean matchStaticFilters(IRecipe<C> r) {
return ((r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS
&& AllConfigs.SERVER.recipes.allowShapelessInMixer.get()) || r.getType() == AllRecipeTypes.MIXING.type);
&& AllConfigs.SERVER.recipes.allowShapelessInMixer.get() && r.getIngredients()
.size() > 1)
|| r.getType() == AllRecipeTypes.MIXING.type);
}
@Override

View file

@ -93,8 +93,9 @@ public class SawRenderer extends SafeTileEntityRenderer<SawTileEntity> {
boolean moving = te.inventory.recipeDuration != 0;
float offset = moving ? (float) (te.inventory.remainingTime) / te.inventory.recipeDuration : 0;
float processingSpeed = MathHelper.clamp(Math.abs(te.getSpeed()) / 32, 1, 128);
if (moving)
offset = MathHelper.clamp(offset + (-partialTicks + .5f) / te.inventory.recipeDuration, 0, 1);
offset = MathHelper.clamp(offset + ((-partialTicks + .5f) * processingSpeed) / te.inventory.recipeDuration, 0, 1);
if (te.getSpeed() == 0)
offset = .5f;

View file

@ -46,7 +46,9 @@ public abstract class AbstractContraptionEntityRenderer<C extends AbstractContra
ms.push();
transform(entity, partialTicks, matrixStacks);
ContraptionRenderer.render(entity.world, entity.getContraption(), ms, msLocal, buffers);
Contraption contraption = entity.getContraption();
if (contraption != null)
ContraptionRenderer.render(entity.world, contraption, ms, msLocal, buffers);
ms.pop();
}

View file

@ -13,7 +13,6 @@ import com.simibubi.create.content.contraptions.components.structureMovement.mou
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption;
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController;
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController;
import com.simibubi.create.foundation.entity.CreateDataSerializers;
import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Couple;
@ -54,8 +53,8 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
private static final DataParameter<Optional<UUID>> COUPLING =
EntityDataManager.createKey(OrientedContraptionEntity.class, DataSerializers.OPTIONAL_UNIQUE_ID);
private static final DataParameter<Optional<Direction>> INITIAL_ORIENTATION =
EntityDataManager.createKey(OrientedContraptionEntity.class, CreateDataSerializers.OPTIONAL_DIRECTION);
private static final DataParameter<Direction> INITIAL_ORIENTATION =
EntityDataManager.createKey(OrientedContraptionEntity.class, DataSerializers.DIRECTION);
protected Vec3d motionBeforeStall;
protected boolean forceAngle;
@ -92,15 +91,15 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
}
public void setInitialOrientation(Direction direction) {
dataManager.set(INITIAL_ORIENTATION, Optional.of(direction));
dataManager.set(INITIAL_ORIENTATION, direction);
}
public Optional<Direction> getInitialOrientation() {
public Direction getInitialOrientation() {
return dataManager.get(INITIAL_ORIENTATION);
}
public void deferOrientation(Direction newInitialAngle) {
dataManager.set(INITIAL_ORIENTATION, Optional.empty());
dataManager.set(INITIAL_ORIENTATION, Direction.UP);
yaw = initialYawOffset = newInitialAngle.getHorizontalAngle();
}
@ -110,8 +109,7 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
}
public float getInitialYaw() {
return dataManager.get(INITIAL_ORIENTATION)
.orElse(Direction.SOUTH)
return (isInitialOrientationPresent() ? dataManager.get(INITIAL_ORIENTATION) : Direction.SOUTH)
.getHorizontalAngle();
}
@ -119,7 +117,7 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
protected void registerData() {
super.registerData();
dataManager.register(COUPLING, Optional.empty());
dataManager.register(INITIAL_ORIENTATION, Optional.empty());
dataManager.register(INITIAL_ORIENTATION, Direction.UP);
}
@Override
@ -177,9 +175,10 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
compound.put("CachedMotion",
newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z));
Optional<Direction> optional = dataManager.get(INITIAL_ORIENTATION);
if (optional.isPresent())
NBTHelper.writeEnum(compound, "InitialOrientation", optional.get());
Direction optional = dataManager.get(INITIAL_ORIENTATION);
if (optional.getAxis()
.isHorizontal())
NBTHelper.writeEnum(compound, "InitialOrientation", optional);
if (forceAngle) {
compound.putFloat("ForceYaw", yaw);
forceAngle = false;
@ -195,11 +194,16 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
@Override
public void notifyDataManagerChange(DataParameter<?> key) {
super.notifyDataManagerChange(key);
if (key == INITIAL_ORIENTATION && dataManager.get(INITIAL_ORIENTATION)
.isPresent())
if (key == INITIAL_ORIENTATION && isInitialOrientationPresent())
startAtInitialYaw();
}
public boolean isInitialOrientationPresent() {
return dataManager.get(INITIAL_ORIENTATION)
.getAxis()
.isHorizontal();
}
public void startAtInitialYaw() {
startAtYaw(getInitialYaw());
}
@ -343,6 +347,7 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
return false;
}
prevYaw = yaw;
if (wasStalled)
return false;
@ -353,8 +358,7 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
movementVector = getPositionVec().subtract(prevPosX, prevPosY, prevPosZ);
Vec3d motion = movementVector.normalize();
if (!dataManager.get(INITIAL_ORIENTATION)
.isPresent() && !world.isRemote) {
if (!isInitialOrientationPresent() && !world.isRemote) {
if (motion.length() > 0) {
Direction facingFromVector = Direction.getFacingFromVector(motion.x, motion.y, motion.z);
if (initialYawOffset != -1)

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
import java.util.Optional;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
@ -55,8 +53,7 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour {
if (axis.isVertical())
offset = -orientedCE.getYaw(renderPartialTicks);
else {
Optional<Direction> initialOrientation = orientedCE.getInitialOrientation();
if (initialOrientation.isPresent() && initialOrientation.get()
if (orientedCE.isInitialOrientationPresent() && orientedCE.getInitialOrientation()
.getAxis() == axis)
offset = -orientedCE.getPitch(renderPartialTicks);
}

View file

@ -26,6 +26,13 @@ public class WindmillBearingTileEntity extends MechanicalBearingTileEntity {
super.updateGeneratedRotation();
lastGeneratedSpeed = getGeneratedSpeed();
}
@Override
public void onSpeedChanged(float prevSpeed) {
boolean cancelAssembly = assembleNextTick;
super.onSpeedChanged(prevSpeed);
assembleNextTick = cancelAssembly;
}
@Override
public float getGeneratedSpeed() {

View file

@ -244,9 +244,8 @@ public class MinecartContraptionItem extends Item {
tag.remove("Pos");
tag.remove("Motion");
Optional<Direction> initialOrientation = entity.getInitialOrientation();
if (initialOrientation.isPresent())
NBTHelper.writeEnum(tag, "InitialOrientation", initialOrientation.get());
if (entity.isInitialOrientationPresent())
NBTHelper.writeEnum(tag, "InitialOrientation", entity.getInitialOrientation());
stack.getOrCreateTag()
.put("Contraption", tag);

View file

@ -174,6 +174,7 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour {
infinite = false;
setValidationTimer();
frontier.add(new BlockPosEntry(root, 0));
tileEntity.sendData();
}
protected boolean checkValid(World world, BlockPos root) {
@ -322,6 +323,7 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour {
newValidationSet.clear();
validationFrontier.clear();
validationVisited.clear();
tileEntity.sendData();
}
public static BehaviourType<FluidDrainingBehaviour> TYPE = new BehaviourType<>();

View file

@ -76,6 +76,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour {
if (!infinite) {
reset();
infinite = true;
tileEntity.sendData();
}
infinityCheckFrontier.clear();
setLongValidationTimer();
@ -236,6 +237,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour {
queue.enqueue(new BlockPosEntry(root, 0));
infinite = false;
setValidationTimer();
tileEntity.sendData();
}
enum SpaceType {

View file

@ -4,6 +4,7 @@ import java.util.List;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.fluid.SmartFluidTank;
import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.LerpedFloat;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
@ -28,6 +29,8 @@ public class HosePulleyTileEntity extends KineticTileEntity {
private LazyOptional<IFluidHandler> capability;
private FluidDrainingBehaviour drainer;
private FluidFillingBehaviour filler;
private HosePulleyFluidHandler handler;
private boolean infinite;
public HosePulleyTileEntity(TileEntityType<?> typeIn) {
super(typeIn);
@ -35,11 +38,25 @@ public class HosePulleyTileEntity extends KineticTileEntity {
.startWithValue(0);
isMoving = true;
internalTank = new SmartFluidTank(1500, this::onTankContentsChanged);
IFluidHandler handler = new HosePulleyFluidHandler(internalTank, filler, drainer,
handler = new HosePulleyFluidHandler(internalTank, filler, drainer,
() -> pos.down((int) Math.ceil(offset.getValue())), () -> !this.isMoving);
capability = LazyOptional.of(() -> handler);
}
@Override
public void sendData() {
infinite = filler.infinite || drainer.infinite;
super.sendData();
}
@Override
public boolean addToGoggleTooltip(List<String> tooltip, boolean isPlayerSneaking) {
boolean addToGoggleTooltip = super.addToGoggleTooltip(tooltip, isPlayerSneaking);
if (infinite)
TooltipHelper.addHint(tooltip, "hint.hose_pulley");
return addToGoggleTooltip;
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
drainer = new FluidDrainingBehaviour(this);
@ -59,10 +76,10 @@ public class HosePulleyTileEntity extends KineticTileEntity {
offset.setValue(Math.round(offset.getValue()));
isMoving = false;
}
if (isMoving) {
float newOffset = offset.getValue() + getMovementSpeed();
if (newOffset < 0)
if (newOffset < 0)
isMoving = false;
if (!world.getBlockState(pos.down((int) Math.ceil(newOffset)))
.getMaterial()
@ -74,7 +91,7 @@ public class HosePulleyTileEntity extends KineticTileEntity {
filler.reset();
}
}
super.onSpeedChanged(previousSpeed);
}
@ -127,6 +144,8 @@ public class HosePulleyTileEntity extends KineticTileEntity {
filler.reset();
return;
}
sendData();
}
@Override
@ -134,6 +153,8 @@ public class HosePulleyTileEntity extends KineticTileEntity {
compound.put("Offset", offset.writeNBT());
compound.put("Tank", internalTank.writeToNBT(new CompoundNBT()));
super.write(compound, clientPacket);
if (clientPacket)
compound.putBoolean("Infinite", infinite);
}
@Override
@ -141,6 +162,8 @@ public class HosePulleyTileEntity extends KineticTileEntity {
offset.readNBT(compound.getCompound("Offset"), clientPacket);
internalTank.readFromNBT(compound.getCompound("Tank"));
super.read(compound, clientPacket);
if (clientPacket)
infinite = compound.getBoolean("Infinite");
}
@Override

View file

@ -118,7 +118,7 @@ public class SpoutTileEntity extends SmartTileEntity {
.setFluid(fluid);
sendSplash = true;
notifyUpdate();
return PASS;
return HOLD;
}
private FluidStack getCurrentFluidInTank() {

View file

@ -99,6 +99,10 @@ public class BasinRecipe extends ProcessingRecipe<SmartInventory> {
ItemStack extracted = availableItems.extractItem(slot, 1, true);
if (!ingredient.test(extracted))
continue;
// Catalyst items are never consumed
if (extracted.hasContainerItem() && extracted.getContainerItem()
.isItemEqual(extracted))
continue Ingredients;
if (!simulate)
availableItems.extractItem(slot, 1, false);
else if (extracted.hasContainerItem())

View file

@ -308,7 +308,7 @@ public class BasinTileEntity extends SmartTileEntity {
: te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite())
.orElse(null);
boolean update = false;
for (Iterator<ItemStack> iterator = spoutputBuffer.iterator(); iterator.hasNext();) {
ItemStack itemStack = iterator.next();
@ -330,7 +330,7 @@ public class BasinTileEntity extends SmartTileEntity {
iterator.remove();
visualizedOutputItems.add(IntAttached.withZero(itemStack));
}
if (update) {
notifyChangeOfContents();
sendData();
@ -435,6 +435,11 @@ public class BasinTileEntity extends SmartTileEntity {
if (targetInv == null && !outputItems.isEmpty())
return false;
for (ItemStack itemStack : outputItems) {
// Catalyst items are never consumed
if (itemStack.hasContainerItem() && itemStack.getContainerItem()
.isItemEqual(itemStack))
continue;
if (simulate || direction == Direction.DOWN) {
if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), simulate)
.isEmpty())

View file

@ -408,11 +408,11 @@ public class BeltInventory {
public void applyToEachWithin(float position, float maxDistanceToPosition,
Function<TransportedItemStack, TransportedResult> processFunction) {
boolean dirty = false;
for (TransportedItemStack transforted : items) {
ItemStack stackBefore = transforted.stack.copy();
if (Math.abs(position - transforted.beltPosition) >= maxDistanceToPosition)
for (TransportedItemStack transported : items) {
ItemStack stackBefore = transported.stack.copy();
if (Math.abs(position - transported.beltPosition) >= maxDistanceToPosition)
continue;
TransportedResult result = processFunction.apply(transforted);
TransportedResult result = processFunction.apply(transported);
if (result == null|| result.didntChangeFrom(stackBefore))
continue;
@ -423,7 +423,7 @@ public class BeltInventory {
toInsert.add(held);
}
toInsert.addAll(result.getOutputs());
toRemove.add(transforted);
toRemove.add(transported);
}
if (dirty) {
belt.markDirty();

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.contraptions.relays.belt.transport;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
@ -8,12 +9,18 @@ import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock;
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelTileEntity;
import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelBlock;
import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.items.ItemHandlerHelper;
public class BeltTunnelInteractionHandler {
@ -26,38 +33,77 @@ public class BeltTunnelInteractionHandler {
Direction movementFacing = beltInventory.belt.getMovementFacing();
if (!beltInventory.beltMovementPositive && nextOffset == 0)
upcomingSegment = -1;
if (currentSegment != upcomingSegment) {
if (stuckAtTunnel(beltInventory, upcomingSegment, current.stack, movementFacing)) {
current.beltPosition = currentSegment + (beltInventory.beltMovementPositive ? .99f : .01f);
return true;
if (currentSegment == upcomingSegment)
return false;
if (stuckAtTunnel(beltInventory, upcomingSegment, current.stack, movementFacing)) {
current.beltPosition = currentSegment + (beltInventory.beltMovementPositive ? .99f : .01f);
return true;
}
World world = beltInventory.belt.getWorld();
boolean onServer = !world.isRemote;
boolean removed = false;
BeltTunnelTileEntity nextTunnel = getTunnelOnSegement(beltInventory, upcomingSegment);
if (nextTunnel instanceof BrassTunnelTileEntity) {
BrassTunnelTileEntity brassTunnel = (BrassTunnelTileEntity) nextTunnel;
if (brassTunnel.hasDistributionBehaviour()) {
if (!brassTunnel.canTakeItems())
return true;
if (onServer) {
brassTunnel.setStackToDistribute(current.stack);
current.stack = ItemStack.EMPTY;
beltInventory.belt.sendData();
beltInventory.belt.markDirty();
}
removed = true;
}
boolean onServer = !beltInventory.belt.getWorld().isRemote;
boolean removed = false;
BeltTunnelTileEntity nextTunnel = getTunnelOnSegement(beltInventory, upcomingSegment);
if (nextTunnel instanceof BrassTunnelTileEntity) {
BrassTunnelTileEntity brassTunnel = (BrassTunnelTileEntity) nextTunnel;
if (brassTunnel.hasDistributionBehaviour()) {
if (!brassTunnel.canTakeItems())
} else if (nextTunnel != null) {
BlockState blockState = nextTunnel.getBlockState();
if (current.stack.getCount() > 1 && AllBlocks.ANDESITE_TUNNEL.has(blockState)
&& BeltTunnelBlock.isJunction(blockState)
&& movementFacing.getAxis() == blockState.get(BeltTunnelBlock.HORIZONTAL_AXIS)) {
for (Direction d : Iterate.horizontalDirections) {
if (d.getAxis() == blockState.get(BeltTunnelBlock.HORIZONTAL_AXIS))
continue;
if (!nextTunnel.flaps.containsKey(d))
continue;
BlockPos outpos = nextTunnel.getPos()
.down()
.offset(d);
if (!world.isBlockPresent(outpos))
return true;
if (onServer) {
brassTunnel.setStackToDistribute(current.stack);
current.stack = ItemStack.EMPTY;
beltInventory.belt.sendData();
beltInventory.belt.markDirty();
}
removed = true;
DirectBeltInputBehaviour behaviour =
TileEntityBehaviour.get(world, outpos, DirectBeltInputBehaviour.TYPE);
if (behaviour == null)
continue;
if (!behaviour.canInsertFromSide(d))
continue;
ItemStack toinsert = ItemHandlerHelper.copyStackWithSize(current.stack, 1);
if (!behaviour.handleInsertion(toinsert, d, false).isEmpty())
return true;
if (onServer)
flapTunnel(beltInventory, upcomingSegment, d, false);
current.stack.shrink(1);
beltInventory.belt.sendData();
if (current.stack.getCount() <= 1)
break;
}
}
if (onServer) {
flapTunnel(beltInventory, currentSegment, movementFacing, false);
flapTunnel(beltInventory, upcomingSegment, movementFacing.getOpposite(), true);
}
if (removed)
return true;
}
if (onServer) {
flapTunnel(beltInventory, currentSegment, movementFacing, false);
flapTunnel(beltInventory, upcomingSegment, movementFacing.getOpposite(), true);
}
if (removed)
return true;
return false;
}

View file

@ -1,5 +0,0 @@
package com.simibubi.create.content.contraptions.relays.elementary;
public class CogWheelPlacementHelper {
}

View file

@ -1,5 +1,10 @@
package com.simibubi.create.content.contraptions.relays.elementary;
import static com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock.AXIS;
import java.util.List;
import java.util.function.Predicate;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
@ -11,6 +16,7 @@ import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
@ -25,11 +31,6 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.World;
import java.util.List;
import java.util.function.Predicate;
import static com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock.AXIS;
public class CogwheelBlockItem extends BlockItem {
boolean large;
@ -48,18 +49,24 @@ public class CogwheelBlockItem extends BlockItem {
@Override
public ActionResultType tryPlace(BlockItemUseContext context) {
World world = context.getWorld();
BlockPos pos = context.getPos().offset(context.getFace().getOpposite());
BlockPos pos = context.getPos()
.offset(context.getFace()
.getOpposite());
BlockState state = world.getBlockState(pos);
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
PlayerEntity player = context.getPlayer();
if (helper.matchesState(state)) {
PlacementOffset offset = helper.getOffset(world, state, pos, new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true));
PlacementOffset offset = helper.getOffset(world, state, pos,
new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true));
if (!offset.isReplaceable(world))
return super.tryPlace(context);
offset.placeInWorld(world, this, context.getPlayer(), context.getItem());
offset.placeInWorld(world, this, player, context.getItem());
triggerShiftingGearsAdvancement(world, new BlockPos(offset.getPos()), offset.getTransform()
.apply(getBlock().getDefaultState()), player);
return ActionResultType.SUCCESS;
}
@ -68,92 +75,61 @@ public class CogwheelBlockItem extends BlockItem {
helper = PlacementHelpers.get(integratedCogHelperId);
if (helper.matchesState(state)) {
PlacementOffset offset = helper.getOffset(world, state, pos, new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true));
PlacementOffset offset = helper.getOffset(world, state, pos,
new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true));
if (!offset.isReplaceable(world))
return super.tryPlace(context);
offset.placeInWorld(world, this, context.getPlayer(), context.getItem());
offset.placeInWorld(world, this, player, context.getItem());
triggerShiftingGearsAdvancement(world, new BlockPos(offset.getPos()), offset.getTransform()
.apply(getBlock().getDefaultState()), player);
return ActionResultType.SUCCESS;
}
}
return super.tryPlace(context);
/*if (!(placedOnState.getBlock() instanceof CogWheelBlock))
return super.tryPlace(context);
if (face.getAxis() == placedOnState.get(CogWheelBlock.AXIS))
return super.tryPlace(context);
boolean placedOnLarge = CogWheelBlock.isLargeCog(placedOnState);
if (placedOnLarge || large) {
boolean largeOnLarge = placedOnLarge && large;
Axis offsetAxis = Axis.X;
for (Axis axis : Axis.values()) {
if (placedOnState.get(CogWheelBlock.AXIS) == axis)
continue;
if (axis == face.getAxis())
continue;
offsetAxis = axis;
}
if (largeOnLarge)
offsetAxis = placedOnState.get(CogWheelBlock.AXIS);
Vec3d hitVec = context.getHitVec().subtract(VecHelper.getCenterOf(placedOnPos));
hitVec = hitVec
.mul(new Vec3d(Direction.getFacingFromAxis(AxisDirection.POSITIVE, offsetAxis).getDirectionVec()));
BlockPos correctPos =
context.getPos().add(Math.signum(hitVec.x), Math.signum(hitVec.y), Math.signum(hitVec.z));
if (context.getWorld().getBlockState(correctPos).getMaterial().isReplaceable())
context = BlockItemUseContext.func_221536_a(context, correctPos, largeOnLarge ? face
: Direction.getFacingFromAxis(AxisDirection.POSITIVE, placedOnState.get(CogWheelBlock.AXIS)));
else
return ActionResultType.FAIL;
}
return super.tryPlace(context);*/
}
@Override
// Trigger cogwheel criterion
protected boolean placeBlock(BlockItemUseContext context, BlockState state) {
World world = context.getWorld();
PlayerEntity player = context.getPlayer();
triggerShiftingGearsAdvancement(context.getWorld(), context.getPos(), state, context.getPlayer());
return super.placeBlock(context, state);
}
if (!world.isRemote && player != null) {
Axis axis = state.get(CogWheelBlock.AXIS);
for (Axis perpendicular1 : Iterate.axes) {
if (perpendicular1 == axis)
protected void triggerShiftingGearsAdvancement(World world, BlockPos pos, BlockState state, PlayerEntity player) {
if (world.isRemote || player == null)
return;
Axis axis = state.get(CogWheelBlock.AXIS);
for (Axis perpendicular1 : Iterate.axes) {
if (perpendicular1 == axis)
continue;
Direction d1 = Direction.getFacingFromAxis(AxisDirection.POSITIVE, perpendicular1);
for (Axis perpendicular2 : Iterate.axes) {
if (perpendicular1 == perpendicular2)
continue;
Direction d1 = Direction.getFacingFromAxis(AxisDirection.POSITIVE, perpendicular1);
for (Axis perpendicular2 : Iterate.axes) {
if (perpendicular1 == perpendicular2)
continue;
if (axis == perpendicular2)
continue;
Direction d2 = Direction.getFacingFromAxis(AxisDirection.POSITIVE, perpendicular2);
for (int offset1 : Iterate.positiveAndNegative) {
for (int offset2 : Iterate.positiveAndNegative) {
BlockPos connectedPos = context.getPos().offset(d1, offset1).offset(d2, offset2);
BlockState blockState = world.getBlockState(connectedPos);
if (!(blockState.getBlock() instanceof CogWheelBlock))
continue;
if (blockState.get(CogWheelBlock.AXIS) != axis)
continue;
if (AllBlocks.LARGE_COGWHEEL.has(blockState) == large)
continue;
AllTriggers.triggerFor(AllTriggers.SHIFTING_GEARS, player);
}
if (axis == perpendicular2)
continue;
Direction d2 = Direction.getFacingFromAxis(AxisDirection.POSITIVE, perpendicular2);
for (int offset1 : Iterate.positiveAndNegative) {
for (int offset2 : Iterate.positiveAndNegative) {
BlockPos connectedPos = pos.offset(d1, offset1)
.offset(d2, offset2);
BlockState blockState = world.getBlockState(connectedPos);
if (!(blockState.getBlock() instanceof CogWheelBlock))
continue;
if (blockState.get(CogWheelBlock.AXIS) != axis)
continue;
if (AllBlocks.LARGE_COGWHEEL.has(blockState) == large)
continue;
AllTriggers.triggerFor(AllTriggers.SHIFTING_GEARS, player);
}
}
}
}
return super.placeBlock(context, state);
}
@MethodsReturnNonnullByDefault
@ -170,7 +146,8 @@ public class CogwheelBlockItem extends BlockItem {
return PlacementOffset.fail();
if (!((CogWheelBlock) state.getBlock()).isLarge) {
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS));
List<Direction> directions =
IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS));
for (Direction dir : directions) {
BlockPos newPos = pos.offset(dir);
@ -178,7 +155,9 @@ public class CogwheelBlockItem extends BlockItem {
if (hasLargeCogwheelNeighbor(world, newPos, state.get(AXIS)))
continue;
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
if (!world.getBlockState(newPos)
.getMaterial()
.isReplaceable())
continue;
return PlacementOffset.success(newPos, s -> s.with(AXIS, state.get(AXIS)));
@ -193,7 +172,9 @@ public class CogwheelBlockItem extends BlockItem {
@Override
public void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) {
IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, state.get(AXIS)), ((CogWheelBlock) state.getBlock()).isLarge ? 1.5D : 0.75D);
IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()),
Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, state.get(AXIS)),
((CogWheelBlock) state.getBlock()).isLarge ? 1.5D : 0.75D);
}
}
@ -211,11 +192,16 @@ public class CogwheelBlockItem extends BlockItem {
return PlacementOffset.fail();
if (((CogWheelBlock) state.getBlock()).isLarge) {
Direction side = IPlacementHelper.orderedByDistanceOnlyAxis(pos, ray.getHitVec(), state.get(AXIS)).get(0);
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS));
Direction side = IPlacementHelper.orderedByDistanceOnlyAxis(pos, ray.getHitVec(), state.get(AXIS))
.get(0);
List<Direction> directions =
IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS));
for (Direction dir : directions) {
BlockPos newPos = pos.offset(dir).offset(side);
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
BlockPos newPos = pos.offset(dir)
.offset(side);
if (!world.getBlockState(newPos)
.getMaterial()
.isReplaceable())
continue;
return PlacementOffset.success(newPos, s -> s.with(AXIS, dir.getAxis()));
@ -238,13 +224,18 @@ public class CogwheelBlockItem extends BlockItem {
@Override
public PlacementOffset getOffset(World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) {
//diagonal gears of different size
Direction closest = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS)).get(0);
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS), d -> d.getAxis() != closest.getAxis());
// diagonal gears of different size
Direction closest = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS))
.get(0);
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(),
state.get(AXIS), d -> d.getAxis() != closest.getAxis());
for (Direction dir : directions) {
BlockPos newPos = pos.offset(dir).offset(closest);
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
BlockPos newPos = pos.offset(dir)
.offset(closest);
if (!world.getBlockState(newPos)
.getMaterial()
.isReplaceable())
continue;
if (AllBlocks.COGWHEEL.has(state) && hasSmallCogwheelNeighbor(world, newPos, state.get(AXIS)))
@ -258,11 +249,17 @@ public class CogwheelBlockItem extends BlockItem {
@Override
public void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) {
IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, state.get(AXIS)), 1D);
IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()),
Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, state.get(AXIS)), 1D);
}
protected boolean hitOnShaft(BlockState state, BlockRayTraceResult ray) {
return AllShapes.SIX_VOXEL_POLE.get(state.get(AXIS)).getBoundingBox().grow(0.001).contains(ray.getHitVec().subtract(ray.getHitVec().align(Iterate.axisSet)));
return AllShapes.SIX_VOXEL_POLE.get(state.get(AXIS))
.getBoundingBox()
.grow(0.001)
.contains(ray.getHitVec()
.subtract(ray.getHitVec()
.align(Iterate.axisSet)));
}
static public boolean hasLargeCogwheelNeighbor(World world, BlockPos pos, Direction.Axis axis) {
@ -300,7 +297,8 @@ public class CogwheelBlockItem extends BlockItem {
@Override
public Predicate<BlockState> getStatePredicate() {
return s -> !AllBlocks.COGWHEEL.has(s) && s.getBlock() instanceof IRotate && ((IRotate) s.getBlock()).hasIntegratedCogwheel(null, null, null);
return s -> !AllBlocks.COGWHEEL.has(s) && s.getBlock() instanceof IRotate
&& ((IRotate) s.getBlock()).hasIntegratedCogwheel(null, null, null);
}
@Override
@ -309,24 +307,31 @@ public class CogwheelBlockItem extends BlockItem {
Axis newAxis;
if (state.has(HorizontalKineticBlock.HORIZONTAL_FACING))
newAxis = state.get(HorizontalKineticBlock.HORIZONTAL_FACING).getAxis();
newAxis = state.get(HorizontalKineticBlock.HORIZONTAL_FACING)
.getAxis();
else if (state.has(DirectionalKineticBlock.FACING))
newAxis = state.get(DirectionalKineticBlock.FACING).getAxis();
newAxis = state.get(DirectionalKineticBlock.FACING)
.getAxis();
else
newAxis = Axis.Y;
if (face.getAxis() == newAxis)
return PlacementOffset.fail();
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), face.getAxis(), newAxis);
List<Direction> directions =
IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), face.getAxis(), newAxis);
for (Direction d : directions) {
BlockPos newPos = pos.offset(face).offset(d);
BlockPos newPos = pos.offset(face)
.offset(d);
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
if (!world.getBlockState(newPos)
.getMaterial()
.isReplaceable())
continue;
if (DiagonalCogHelper.hasLargeCogwheelNeighbor(world, newPos, newAxis) || DiagonalCogHelper.hasSmallCogwheelNeighbor(world, newPos, newAxis))
if (DiagonalCogHelper.hasLargeCogwheelNeighbor(world, newPos, newAxis)
|| DiagonalCogHelper.hasSmallCogwheelNeighbor(world, newPos, newAxis))
return PlacementOffset.fail();
return PlacementOffset.success(newPos, s -> s.with(CogWheelBlock.AXIS, newAxis));
@ -337,10 +342,10 @@ public class CogwheelBlockItem extends BlockItem {
@Override
public void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) {
IPlacementHelper.renderArrow(
VecHelper.getCenterOf(pos),
VecHelper.getCenterOf(offset.getPos()),
Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, offset.getTransform().apply(AllBlocks.LARGE_COGWHEEL.getDefaultState()).get(AXIS)));
IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()),
Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, offset.getTransform()
.apply(AllBlocks.LARGE_COGWHEEL.getDefaultState())
.get(AXIS)));
}
}
}

View file

@ -94,6 +94,11 @@ public class BeltTunnelBlock extends Block implements ITE<BeltTunnelTileEntity>,
public static boolean isStraight(BlockState state) {
return hasWindow(state) || state.get(SHAPE) == Shape.STRAIGHT;
}
public static boolean isJunction(BlockState state) {
Shape shape = state.get(SHAPE);
return shape == Shape.CROSS || shape == Shape.T_LEFT || shape == Shape.T_RIGHT;
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {

View file

@ -36,12 +36,15 @@ import net.minecraftforge.items.IItemHandler;
public class BeltTunnelTileEntity extends SmartTileEntity {
public HashMap<Direction, InterpolatedChasingValue> flaps;
public Set<Direction> sides;
protected LazyOptional<IItemHandler> cap = LazyOptional.empty();
protected List<Pair<Direction, Boolean>> flapsToSend;
public BeltTunnelTileEntity(TileEntityType<? extends BeltTunnelTileEntity> type) {
super(type);
flaps = new HashMap<>();
sides = new HashSet<>();
flapsToSend = new LinkedList<>();
}
@ -57,6 +60,12 @@ public class BeltTunnelTileEntity extends SmartTileEntity {
for (Direction direction : flaps.keySet())
flapsNBT.add(IntNBT.of(direction.getIndex()));
compound.put("Flaps", flapsNBT);
ListNBT sidesNBT = new ListNBT();
for (Direction direction : sides)
sidesNBT.add(IntNBT.of(direction.getIndex()));
compound.put("Sides", sidesNBT);
super.write(compound, clientPacket);
if (!clientPacket)
@ -83,6 +92,12 @@ public class BeltTunnelTileEntity extends SmartTileEntity {
for (INBT inbt : flapsNBT)
if (inbt instanceof IntNBT)
newFlaps.add(Direction.byIndex(((IntNBT) inbt).getInt()));
sides.clear();
ListNBT sidesNBT = compound.getList("Sides", NBT.TAG_INT);
for (INBT inbt : sidesNBT)
if (inbt instanceof IntNBT)
sides.add(Direction.byIndex(((IntNBT) inbt).getInt()));
for (Direction d : Iterate.directions)
if (!newFlaps.contains(d))
@ -91,6 +106,10 @@ public class BeltTunnelTileEntity extends SmartTileEntity {
flaps.put(d, new InterpolatedChasingValue().start(.25f)
.target(0)
.withSpeed(.05f));
// Backwards compat
if (!compound.contains("Sides") && compound.contains("Flaps"))
sides.addAll(flaps.keySet());
super.read(compound, clientPacket);
@ -108,11 +127,9 @@ public class BeltTunnelTileEntity extends SmartTileEntity {
public void updateTunnelConnections() {
flaps.clear();
sides.clear();
BlockState tunnelState = getBlockState();
for (Direction direction : Iterate.horizontalDirections) {
BlockState blockState = world.getBlockState(pos.offset(direction));
if (blockState.getBlock() instanceof BeltTunnelBlock)
continue;
if (direction.getAxis() != tunnelState.get(BlockStateProperties.HORIZONTAL_AXIS)) {
boolean positive =
direction.getAxisDirection() == AxisDirection.POSITIVE ^ direction.getAxis() == Axis.Z;
@ -124,11 +141,16 @@ public class BeltTunnelTileEntity extends SmartTileEntity {
if (!positive && shape == Shape.T_RIGHT)
continue;
}
BlockState funnelState = world.getBlockState(getPos().offset(direction));
if (funnelState.getBlock() instanceof BeltFunnelBlock)
if (funnelState.get(BeltFunnelBlock.SHAPE) == BeltFunnelBlock.Shape.EXTENDED
&& funnelState.get(BeltFunnelBlock.HORIZONTAL_FACING) == direction.getOpposite())
sides.add(direction);
// Flap might be occluded
BlockState nextState = world.getBlockState(pos.offset(direction));
if (nextState.getBlock() instanceof BeltTunnelBlock)
continue;
if (nextState.getBlock() instanceof BeltFunnelBlock)
if (nextState.get(BeltFunnelBlock.SHAPE) == BeltFunnelBlock.Shape.EXTENDED
&& nextState.get(BeltFunnelBlock.HORIZONTAL_FACING) == direction.getOpposite())
continue;
flaps.put(direction, new InterpolatedChasingValue().start(.25f)

View file

@ -4,6 +4,7 @@ import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
@ -35,6 +36,10 @@ public class BrassTunnelBlock extends BeltTunnelBlock {
if (p_196243_1_.hasTileEntity()
&& (p_196243_1_.getBlock() != p_196243_4_.getBlock() || !p_196243_4_.hasTileEntity())) {
TileEntityBehaviour.destroy(p_196243_2_, p_196243_3_, FilteringBehaviour.TYPE);
withTileEntityDo(p_196243_2_, p_196243_3_, te -> {
if (te instanceof BrassTunnelTileEntity)
Block.spawnAsEntity(p_196243_2_, p_196243_3_, ((BrassTunnelTileEntity) te).stackToDistribute);
});
p_196243_2_.removeTileEntity(p_196243_3_);
}
}

View file

@ -13,8 +13,6 @@ import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock;
import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock.Shape;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
@ -416,7 +414,7 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity {
continue;
if (direction == movementFacing.getOpposite())
continue;
if (tunnelTE.flaps.containsKey(direction) || tunnelTE.hasValidOutputFunnel(direction)) {
if (tunnelTE.sides.contains(direction)) {
BlockPos offset = tunnelTE.pos.down()
.offset(direction);
DirectBeltInputBehaviour inputBehaviour =
@ -434,17 +432,6 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity {
}
}
protected boolean hasValidOutputFunnel(Direction side) {
BlockState funnelState = world.getBlockState(getPos().offset(side));
if (!(funnelState.getBlock() instanceof BeltFunnelBlock))
return false;
if (funnelState.has(BeltFunnelBlock.POWERED) && funnelState.get(BeltFunnelBlock.POWERED))
return false;
if (funnelState.get(BeltFunnelBlock.HORIZONTAL_FACING) != side.getOpposite())
return false;
return funnelState.get(BeltFunnelBlock.SHAPE) == Shape.EXTENDED;
}
@Override
public void addBehavioursDeferred(List<TileEntityBehaviour> behaviours) {
super.addBehavioursDeferred(behaviours);
@ -462,7 +449,7 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity {
}
private boolean isValidFaceForFilter(Direction side) {
return flaps.containsKey(side);
return sides.contains(side);
}
@Override

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.schematics.block;
import java.util.Optional;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorItem;
@ -161,6 +162,8 @@ public abstract class LaunchedItem {
data.putInt("x", target.getX());
data.putInt("y", target.getY());
data.putInt("z", target.getZ());
if (tile instanceof KineticTileEntity)
((KineticTileEntity) tile).warnOfMovement();
tile.read(data);
}
}

View file

@ -12,6 +12,7 @@ import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ILightReader;
@ -40,18 +41,27 @@ public class ColoredVertexModel extends BakedModelWrapper<IBakedModel> {
List<BakedQuad> quads = new ArrayList<>(super.getQuads(state, side, rand, extraData));
if (!extraData.hasProperty(POSITION_PROPERTY))
return quads;
if (quads.isEmpty())
return quads;
// Optifine might've rejigged vertex data
VertexFormat format = DefaultVertexFormats.BLOCK;
int colorIndex = 0;
for (int j = 0; j < format.getElements().size(); j++) {
VertexFormatElement e = format.getElements().get(j);
if (e.getUsage() == VertexFormatElement.Usage.COLOR)
colorIndex = j;
}
int colorOffset = format.getOffset(colorIndex) / 4;
BlockPos data = extraData.getData(POSITION_PROPERTY);
for (int i = 0; i < quads.size(); i++) {
BakedQuad quad = quads.get(i);
BakedQuad newQuad = new BakedQuad(Arrays.copyOf(quad.getVertexData(), quad.getVertexData().length),
quad.getTintIndex(), quad.getFace(), quad.getSprite(), quad.shouldApplyDiffuseLighting());
VertexFormat format = DefaultVertexFormats.BLOCK;
int[] vertexData = newQuad.getVertexData();
BlockPos data = extraData.getData(POSITION_PROPERTY);
for (int vertex = 0; vertex < vertexData.length; vertex += format.getIntegerSize()) {
int colorOffset = 12 / 4;
float x = Float.intBitsToFloat(vertexData[vertex]);
float y = Float.intBitsToFloat(vertexData[vertex + 1]);
float z = Float.intBitsToFloat(vertexData[vertex + 2]);

View file

@ -39,6 +39,8 @@ public class MillingRecipeGen extends ProcessingRecipeGen {
.output(Items.FLINT)),
SAND = create(() -> Blocks.SAND, b -> b.duration(150)
.output(AllPaletteBlocks.LIMESAND.get())),
SANDSTONE = create(() -> Blocks.SANDSTONE, b -> b.duration(150)
.output(Blocks.SAND)),
DIORITE = create(() -> Blocks.DIORITE, b -> b.duration(200)
.output(AllPaletteBlocks.LIMESAND.get())),

View file

@ -1,38 +0,0 @@
package com.simibubi.create.foundation.entity;
import java.util.Optional;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.IDataSerializer;
import net.minecraft.util.Direction;
public class CreateDataSerializers {
public static final IDataSerializer<Optional<Direction>> OPTIONAL_DIRECTION =
new IDataSerializer<Optional<Direction>>() {
public void write(PacketBuffer buffer, Optional<Direction> opt) {
buffer.writeVarInt(opt.map(Direction::ordinal)
.orElse(-1) + 1);
}
public Optional<Direction> read(PacketBuffer buffer) {
int i = buffer.readVarInt();
return i == 0 ? Optional.empty() : Optional.of(Iterate.directions[i - 1]);
}
public Optional<Direction> copyValue(Optional<Direction> opt) {
return Optional.ofNullable(opt.orElse(null));
}
};
static {
DataSerializers.registerSerializer(OPTIONAL_DIRECTION);
}
public static void register() {}
}

View file

@ -59,7 +59,7 @@ public class PlacementOffset {
public void placeInWorld(World world, BlockItem blockItem, PlayerEntity player, ItemStack item) {
placeInWorld(world, blockItem.getBlock().getDefaultState(), player, item);
}
public void placeInWorld(World world, BlockState defaultState, PlayerEntity player, ItemStack item) {
if (world.isRemote)
return;

View file

@ -449,7 +449,9 @@
"create.tooltip.chute.fans_push_down": "Fans push from Above",
"create.tooltip.chute.fans_pull_up": "Fans pull from Above",
"create.tooltip.chute.fans_pull_down": "Fans pull from Below",
"create.hint.hose_pulley.title": "Bottomless Supply",
"create.hint.hose_pulley": "The targeted body of fluid is considered infinite.",
"create.hint.mechanical_arm_no_targets.title": "No Targets",
"create.hint.mechanical_arm_no_targets": "It appears this _Mechanical_ _Arm_ has not been assigned any _targets._ Select belts, depots, funnels and other blocks by _right-clicking_ them while _holding_ the _Mechanical_ _Arm_ in your _hand_.",
"create.hint.horizontal_funnel.title": "Horizontal Funnels",

View file

@ -377,7 +377,7 @@
"block.create.reinforced_rail.tooltip.summary": "A timber stabilized rail, _does not need supports_.",
"block.create.mechanical_mixer.tooltip": "MECHANICAL MIXER",
"block.create.mechanical_mixer.tooltip.summary": "A kinetic whisk for applying any shapeless crafting recipes to items beneath it. Requires constant _Rotational Force_ and a _Basin_ placed below (with a gap in between).",
"block.create.mechanical_mixer.tooltip.summary": "A kinetic whisk providing automated shapeless crafting recipes of multiple ingredients. Requires constant _Rotational Force_ and a _Basin_ placed below (with a gap in between).",
"block.create.mechanical_mixer.tooltip.condition1": "When above Basin",
"block.create.mechanical_mixer.tooltip.behaviour1": "Starts to mix items in the basin whenever all necessary ingredients are present. To prevent unwanted recipes, use the filter slot on the basin or cut the rotational force until all desired ingredients have been added.",

View file

@ -0,0 +1,31 @@
{
"conditions": [
{
"type": "forge:mod_loaded",
"modid": "appliedenergistics2"
}
],
"type": "create:crushing",
"ingredients": [
{
"item": "appliedenergistics2:quartz_ore"
}
],
"results": [
{
"item": "appliedenergistics2:certus_quartz_crystal",
"count": 2
},
{
"item": "appliedenergistics2:certus_quartz_dust",
"count": 1,
"chance": 0.25
},
{
"item": "minecraft:cobblestone",
"count": 1,
"chance": 0.125
}
],
"processingTime": 300
}

View file

@ -0,0 +1,31 @@
{
"conditions": [
{
"type": "forge:mod_loaded",
"modid": "appliedenergistics2"
}
],
"type": "create:crushing",
"ingredients": [
{
"item": "appliedenergistics2:charged_quartz_ore"
}
],
"results": [
{
"item": "appliedenergistics2:charged_certus_quartz_crystal",
"count": 2
},
{
"item": "appliedenergistics2:certus_quartz_dust",
"count": 1,
"chance": 0.25
},
{
"item": "minecraft:cobblestone",
"count": 1,
"chance": 0.125
}
],
"processingTime": 300
}

View file

@ -0,0 +1,21 @@
{
"conditions": [
{
"type": "forge:mod_loaded",
"modid": "appliedenergistics2"
}
],
"type": "create:milling",
"ingredients": [
{
"tag": "forge:gems/certus_quartz"
}
],
"results": [
{
"item": "appliedenergistics2:certus_quartz_dust",
"count": 1
}
],
"processingTime": 200
}

View file

@ -0,0 +1,21 @@
{
"conditions": [
{
"type": "forge:mod_loaded",
"modid": "appliedenergistics2"
}
],
"type": "create:milling",
"ingredients": [
{
"tag": "forge:ender_pearls"
}
],
"results": [
{
"item": "appliedenergistics2:ender_dust",
"count": 1
}
],
"processingTime": 100
}

View file

@ -0,0 +1,21 @@
{
"conditions": [
{
"type": "forge:mod_loaded",
"modid": "appliedenergistics2"
}
],
"type": "create:milling",
"ingredients": [
{
"item": "appliedenergistics2:certus_quartz_crystal"
}
],
"results": [
{
"item": "appliedenergistics2:certus_quartz_dust",
"count": 1
}
],
"processingTime": 200
}

View file

@ -0,0 +1,21 @@
{
"conditions": [
{
"type": "forge:mod_loaded",
"modid": "appliedenergistics2"
}
],
"type": "create:milling",
"ingredients": [
{
"tag": "forge:ingots/gold"
}
],
"results": [
{
"item": "appliedenergistics2:gold_dust",
"count": 1
}
],
"processingTime": 100
}

View file

@ -0,0 +1,21 @@
{
"conditions": [
{
"type": "forge:mod_loaded",
"modid": "appliedenergistics2"
}
],
"type": "create:milling",
"ingredients": [
{
"tag": "forge:ingots/iron"
}
],
"results": [
{
"item": "appliedenergistics2:iron_dust",
"count": 1
}
],
"processingTime": 200
}

View file

@ -0,0 +1,21 @@
{
"conditions": [
{
"type": "forge:mod_loaded",
"modid": "appliedenergistics2"
}
],
"type": "create:milling",
"ingredients": [
{
"tag": "forge:gems/quartz"
}
],
"results": [
{
"item": "appliedenergistics2:nether_quartz_dust",
"count": 1
}
],
"processingTime": 200
}

View file

@ -0,0 +1,21 @@
{
"conditions": [
{
"type": "forge:mod_loaded",
"modid": "appliedenergistics2"
}
],
"type": "create:milling",
"ingredients": [
{
"item": "appliedenergistics2:sky_stone_block"
}
],
"results": [
{
"item": "appliedenergistics2:sky_dust",
"count": 1
}
],
"processingTime": 300
}

View file

@ -0,0 +1,32 @@
{
"conditions": [
{
"type": "forge:mod_loaded",
"modid": "appliedenergistics2"
}
],
"type": "create:mixing",
"ingredients": [
{
"tag": "forge:dusts/redstone"
},
{
"fluid": "minecraft:water",
"nbt": {},
"amount": 250
},
{
"item": "appliedenergistics2:charged_certus_quartz_crystal"
},
{
"tag": "forge:gems/quartz"
}
],
"results": [
{
"item": "appliedenergistics2:fluix_crystal",
"count": 2
}
],
"heatRequirement": "none"
}