From a666f24ee0dacaf7d6f21827f07f61b37767a369 Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Sun, 9 Jan 2022 14:00:55 -0800 Subject: [PATCH] Souls and flames - Fix lit soul blaze burner providing smoking instead of haunting - Fix horses displaying soul particles even when not being haunted - Add hauntable item attribute - Re-add right clicking lit blaze burner with shovel to extinguish it - Move most fan type functionality to abstract methods in the enum constant - Rework FurnaceEngineModifiers --- src/generated/resources/.cache/cache | 30 +- .../resources/assets/create/lang/en_us.json | 2 + .../assets/create/lang/unfinished/de_de.json | 4 +- .../assets/create/lang/unfinished/es_cl.json | 4 +- .../assets/create/lang/unfinished/es_es.json | 4 +- .../assets/create/lang/unfinished/fr_fr.json | 4 +- .../assets/create/lang/unfinished/it_it.json | 4 +- .../assets/create/lang/unfinished/ja_jp.json | 4 +- .../assets/create/lang/unfinished/ko_kr.json | 4 +- .../assets/create/lang/unfinished/nl_nl.json | 4 +- .../assets/create/lang/unfinished/pl_pl.json | 4 +- .../assets/create/lang/unfinished/pt_br.json | 4 +- .../assets/create/lang/unfinished/pt_pt.json | 4 +- .../assets/create/lang/unfinished/ru_ru.json | 4 +- .../assets/create/lang/unfinished/zh_cn.json | 4 +- .../assets/create/lang/unfinished/zh_tw.json | 4 +- src/main/java/com/simibubi/create/Create.java | 4 +- .../components/fan/AirCurrent.java | 109 +---- .../flywheel/engine/FurnaceEngineBlock.java | 2 +- .../engine/FurnaceEngineInteractions.java | 111 ++++++ .../engine/FurnaceEngineModifiers.java | 84 ---- .../engine/FurnaceEngineTileEntity.java | 12 +- .../processing/InWorldProcessing.java | 374 ++++++++++++------ .../burner/LitBlazeBurnerBlock.java | 14 + .../logistics/item/filter/ItemAttribute.java | 1 + .../assets/create/lang/default/interface.json | 2 + 26 files changed, 464 insertions(+), 337 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineInteractions.java delete mode 100644 src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineModifiers.java diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 9035de24e..ca8a7800c 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -531,21 +531,21 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo 7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json f33899d90db924319a1b99065bf1faff1aa40d6a assets/create/lang/en_ud.json -748d2635a4f8c97cee2392c1c08c4716f7424202 assets/create/lang/en_us.json -d5eed56ff394835dae0f514f9317b83f7fd3954c assets/create/lang/unfinished/de_de.json -b44cb66962677538209a02fdafc2e62541542d64 assets/create/lang/unfinished/es_cl.json -617f9f1a37b46066b8f6a14f22cbeec8179ce0cd assets/create/lang/unfinished/es_es.json -91d391799b6579914ef35cf8ebe917684b25b9df assets/create/lang/unfinished/fr_fr.json -787470a30ca417e8cf1da6b47ac40879bb274237 assets/create/lang/unfinished/it_it.json -00f079aaebfe906b84b71903f80b0be4127e8cc7 assets/create/lang/unfinished/ja_jp.json -75a8b1e3ead980456ff4a4607b1e28197d9de2e8 assets/create/lang/unfinished/ko_kr.json -6c7f81042ee0cc25e0ababea6cc254b72557aac9 assets/create/lang/unfinished/nl_nl.json -7a3670aa1d488f637a4787c37419a25ace4813bc assets/create/lang/unfinished/pl_pl.json -2c30f012946ab67f44514e987e9be87535eb5c5d assets/create/lang/unfinished/pt_br.json -d466d2f81d81296313375de4766d4e36d7a5e3e4 assets/create/lang/unfinished/pt_pt.json -516e0f0149f814ceec3b15cfb2d46c3c4c8a877c assets/create/lang/unfinished/ru_ru.json -d9b421597a5b0b3ae662a12a94c833d853b24fe5 assets/create/lang/unfinished/zh_cn.json -68b91bb8f3822d2b0798a6ec8a85d7d188c5c4d1 assets/create/lang/unfinished/zh_tw.json +88272181311c543ee6790c7b2d1d434570a5fbad assets/create/lang/en_us.json +1b43ebff99b4a65873acc84996b221d17808da82 assets/create/lang/unfinished/de_de.json +01f3f59f6007c352addcb6e26afc6c29990e577d assets/create/lang/unfinished/es_cl.json +a225447219328491bb5a27c8a4013a627949d86e assets/create/lang/unfinished/es_es.json +6b68c9da5fe9b499621e4cfc39c1161d59ceffe1 assets/create/lang/unfinished/fr_fr.json +5c1858916d9390961f43d0b0304253e7615d1f60 assets/create/lang/unfinished/it_it.json +4e09507f40d2c8c31bc9f0efa105c92a68f091dc assets/create/lang/unfinished/ja_jp.json +c3079836f5899cbb39f95e1278cfa1e9b16e2f6c assets/create/lang/unfinished/ko_kr.json +2b7bbe3efddf575b13d13944877aff1b9c16bb0a assets/create/lang/unfinished/nl_nl.json +51ff37d88dfab3dcc9bd269a651a53c98e5f9fc8 assets/create/lang/unfinished/pl_pl.json +23eefb78c4dfd085ad24b48f24203fdd337e221d assets/create/lang/unfinished/pt_br.json +b82282978c9213e42b78d5ed86cab3cdc63cb53f assets/create/lang/unfinished/pt_pt.json +9b5958c6c7065ff41e9ed74cbe0934910742d39d assets/create/lang/unfinished/ru_ru.json +05c401cdcbace483e56e754123922e73ef7e474d assets/create/lang/unfinished/zh_cn.json +368a87626c80ddc8aee6aa681e6479fbc06f3716 assets/create/lang/unfinished/zh_tw.json 487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json 3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 74f903671..eb796d780 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -1165,6 +1165,8 @@ "create.item_attributes.furnace_fuel.inverted": "is not furnace fuel", "create.item_attributes.washable": "can be Washed", "create.item_attributes.washable.inverted": "cannot be Washed", + "create.item_attributes.hauntable": "can be Haunted", + "create.item_attributes.hauntable.inverted": "cannot be Haunted", "create.item_attributes.crushable": "can be Crushed", "create.item_attributes.crushable.inverted": "cannot be Crushed", "create.item_attributes.smeltable": "can be Smelted", diff --git a/src/generated/resources/assets/create/lang/unfinished/de_de.json b/src/generated/resources/assets/create/lang/unfinished/de_de.json index 45434545e..6f7a2e7c1 100644 --- a/src/generated/resources/assets/create/lang/unfinished/de_de.json +++ b/src/generated/resources/assets/create/lang/unfinished/de_de.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 1322", + "_": "Missing Localizations: 1324", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "ist nicht Brennstoff", "create.item_attributes.washable": "kann gewaschen werden", "create.item_attributes.washable.inverted": "kann nicht gewaschen werden", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "kann zerkleinert werden", "create.item_attributes.crushable.inverted": "kann nicht zerkleinert werden", "create.item_attributes.smeltable": "kann geschmolzen werden", diff --git a/src/generated/resources/assets/create/lang/unfinished/es_cl.json b/src/generated/resources/assets/create/lang/unfinished/es_cl.json index 4b1c36ea0..bdb63e8ac 100644 --- a/src/generated/resources/assets/create/lang/unfinished/es_cl.json +++ b/src/generated/resources/assets/create/lang/unfinished/es_cl.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 333", + "_": "Missing Localizations: 335", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "no es cumbustible", "create.item_attributes.washable": "puede Lavarse", "create.item_attributes.washable.inverted": "no puede Lavarse", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "puede ser Triturado", "create.item_attributes.crushable.inverted": "no puede ser Triturado", "create.item_attributes.smeltable": "puede ser Derretido", diff --git a/src/generated/resources/assets/create/lang/unfinished/es_es.json b/src/generated/resources/assets/create/lang/unfinished/es_es.json index d05e5152b..8039c53ca 100644 --- a/src/generated/resources/assets/create/lang/unfinished/es_es.json +++ b/src/generated/resources/assets/create/lang/unfinished/es_es.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 333", + "_": "Missing Localizations: 335", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "no es combustible para hornos", "create.item_attributes.washable": "se puede lavar", "create.item_attributes.washable.inverted": "no se puede lavar", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "puede ser molido", "create.item_attributes.crushable.inverted": "no puede ser molido", "create.item_attributes.smeltable": "se puede fundir", diff --git a/src/generated/resources/assets/create/lang/unfinished/fr_fr.json b/src/generated/resources/assets/create/lang/unfinished/fr_fr.json index 68ba13ae0..17912a7d3 100644 --- a/src/generated/resources/assets/create/lang/unfinished/fr_fr.json +++ b/src/generated/resources/assets/create/lang/unfinished/fr_fr.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 1584", + "_": "Missing Localizations: 1586", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "n'est pas un combustible", "create.item_attributes.washable": "peut être lavé", "create.item_attributes.washable.inverted": "ne peut pas être lavé", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "peut être concassé", "create.item_attributes.crushable.inverted": "ne peut pas être concassé", "create.item_attributes.smeltable": "peut être fondu", diff --git a/src/generated/resources/assets/create/lang/unfinished/it_it.json b/src/generated/resources/assets/create/lang/unfinished/it_it.json index 5bdbf0908..057040e73 100644 --- a/src/generated/resources/assets/create/lang/unfinished/it_it.json +++ b/src/generated/resources/assets/create/lang/unfinished/it_it.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 1273", + "_": "Missing Localizations: 1275", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "non è un combustibile per fornace", "create.item_attributes.washable": "può essere lavato", "create.item_attributes.washable.inverted": "non può essere lavato", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "può essere frantumato", "create.item_attributes.crushable.inverted": "non può essere frantumato", "create.item_attributes.smeltable": "può essere fuso", diff --git a/src/generated/resources/assets/create/lang/unfinished/ja_jp.json b/src/generated/resources/assets/create/lang/unfinished/ja_jp.json index ffe21cbf8..b7d9e5414 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ja_jp.json +++ b/src/generated/resources/assets/create/lang/unfinished/ja_jp.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 3", + "_": "Missing Localizations: 5", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "かまどの燃料でないか", "create.item_attributes.washable": "洗浄できるかか", "create.item_attributes.washable.inverted": "洗浄できないか", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "粉砕できるかか", "create.item_attributes.crushable.inverted": "粉砕できないか", "create.item_attributes.smeltable": "精錬できるかか", diff --git a/src/generated/resources/assets/create/lang/unfinished/ko_kr.json b/src/generated/resources/assets/create/lang/unfinished/ko_kr.json index 45559e9d3..eef5e9529 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ko_kr.json +++ b/src/generated/resources/assets/create/lang/unfinished/ko_kr.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 5", + "_": "Missing Localizations: 7", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "화로 연료로 쓸 수 없음", "create.item_attributes.washable": "세척될 수 있음", "create.item_attributes.washable.inverted": "세척될 수 없음", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "분쇄될 수 있음", "create.item_attributes.crushable.inverted": "분쇄될 수 없음", "create.item_attributes.smeltable": "구워질 수 있음", diff --git a/src/generated/resources/assets/create/lang/unfinished/nl_nl.json b/src/generated/resources/assets/create/lang/unfinished/nl_nl.json index 374d1ccac..02707b2b4 100644 --- a/src/generated/resources/assets/create/lang/unfinished/nl_nl.json +++ b/src/generated/resources/assets/create/lang/unfinished/nl_nl.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 1937", + "_": "Missing Localizations: 1939", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "UNLOCALIZED: is not furnace fuel", "create.item_attributes.washable": "UNLOCALIZED: can be Washed", "create.item_attributes.washable.inverted": "UNLOCALIZED: cannot be Washed", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "UNLOCALIZED: can be Crushed", "create.item_attributes.crushable.inverted": "UNLOCALIZED: cannot be Crushed", "create.item_attributes.smeltable": "UNLOCALIZED: can be Smelted", diff --git a/src/generated/resources/assets/create/lang/unfinished/pl_pl.json b/src/generated/resources/assets/create/lang/unfinished/pl_pl.json index 12055f625..20dabd3e8 100644 --- a/src/generated/resources/assets/create/lang/unfinished/pl_pl.json +++ b/src/generated/resources/assets/create/lang/unfinished/pl_pl.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 372", + "_": "Missing Localizations: 374", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "nie jest paliwem dla pieca", "create.item_attributes.washable": "może zostać opłukany", "create.item_attributes.washable.inverted": "nie może zostać opłukany", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "może być rozkruszony", "create.item_attributes.crushable.inverted": "nie może być rozkruszony", "create.item_attributes.smeltable": "może zostać przepalony", diff --git a/src/generated/resources/assets/create/lang/unfinished/pt_br.json b/src/generated/resources/assets/create/lang/unfinished/pt_br.json index 7fd70972d..d8d13aeea 100644 --- a/src/generated/resources/assets/create/lang/unfinished/pt_br.json +++ b/src/generated/resources/assets/create/lang/unfinished/pt_br.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 1556", + "_": "Missing Localizations: 1558", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "UNLOCALIZED: is not furnace fuel", "create.item_attributes.washable": "UNLOCALIZED: can be Washed", "create.item_attributes.washable.inverted": "UNLOCALIZED: cannot be Washed", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "UNLOCALIZED: can be Crushed", "create.item_attributes.crushable.inverted": "UNLOCALIZED: cannot be Crushed", "create.item_attributes.smeltable": "UNLOCALIZED: can be Smelted", diff --git a/src/generated/resources/assets/create/lang/unfinished/pt_pt.json b/src/generated/resources/assets/create/lang/unfinished/pt_pt.json index d8be6aa21..89584dd14 100644 --- a/src/generated/resources/assets/create/lang/unfinished/pt_pt.json +++ b/src/generated/resources/assets/create/lang/unfinished/pt_pt.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 1556", + "_": "Missing Localizations: 1558", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "UNLOCALIZED: is not furnace fuel", "create.item_attributes.washable": "UNLOCALIZED: can be Washed", "create.item_attributes.washable.inverted": "UNLOCALIZED: cannot be Washed", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "UNLOCALIZED: can be Crushed", "create.item_attributes.crushable.inverted": "UNLOCALIZED: cannot be Crushed", "create.item_attributes.smeltable": "UNLOCALIZED: can be Smelted", diff --git a/src/generated/resources/assets/create/lang/unfinished/ru_ru.json b/src/generated/resources/assets/create/lang/unfinished/ru_ru.json index 5aa2409ef..1951fa1eb 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ru_ru.json +++ b/src/generated/resources/assets/create/lang/unfinished/ru_ru.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 377", + "_": "Missing Localizations: 379", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "не является топливом", "create.item_attributes.washable": "можно промыть", "create.item_attributes.washable.inverted": "нельзя промыть", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "можно измельчить", "create.item_attributes.crushable.inverted": "нельзя разместить", "create.item_attributes.smeltable": "можно расплавить", diff --git a/src/generated/resources/assets/create/lang/unfinished/zh_cn.json b/src/generated/resources/assets/create/lang/unfinished/zh_cn.json index 6ef9af3b8..dc11ea3bb 100644 --- a/src/generated/resources/assets/create/lang/unfinished/zh_cn.json +++ b/src/generated/resources/assets/create/lang/unfinished/zh_cn.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 3", + "_": "Missing Localizations: 5", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "不可作为燃料", "create.item_attributes.washable": "可被洗涤", "create.item_attributes.washable.inverted": "不可被洗涤", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "可被粉碎", "create.item_attributes.crushable.inverted": "不可被粉碎", "create.item_attributes.smeltable": "可被熔炉烧制", diff --git a/src/generated/resources/assets/create/lang/unfinished/zh_tw.json b/src/generated/resources/assets/create/lang/unfinished/zh_tw.json index e7373854f..1682826a4 100644 --- a/src/generated/resources/assets/create/lang/unfinished/zh_tw.json +++ b/src/generated/resources/assets/create/lang/unfinished/zh_tw.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 391", + "_": "Missing Localizations: 393", "_": "->------------------------] Game Elements [------------------------<-", @@ -1166,6 +1166,8 @@ "create.item_attributes.furnace_fuel.inverted": "不是燃料", "create.item_attributes.washable": "可被篩洗", "create.item_attributes.washable.inverted": "不可被篩洗", + "create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted", + "create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted", "create.item_attributes.crushable": "可被粉碎", "create.item_attributes.crushable.inverted": "不可被粉碎", "create.item_attributes.smeltable": "可被熔爐融煉", diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index 6f086f037..d852fac67 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -10,7 +10,7 @@ import com.google.gson.GsonBuilder; import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour; import com.simibubi.create.content.CreateItemGroup; import com.simibubi.create.content.contraptions.TorquePropagator; -import com.simibubi.create.content.contraptions.components.flywheel.engine.FurnaceEngineModifiers; +import com.simibubi.create.content.contraptions.components.flywheel.engine.FurnaceEngineInteractions; import com.simibubi.create.content.curiosities.weapons.BuiltinPotatoProjectileTypes; import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler; import com.simibubi.create.content.palettes.AllPaletteBlocks; @@ -96,8 +96,8 @@ public class Create { AllInteractionBehaviours.register(); AllWorldFeatures.register(); AllEnchantments.register(); - FurnaceEngineModifiers.register(); AllConfigs.register(modLoadingContext); + FurnaceEngineInteractions.registerDefaults(); BlockSpoutingBehaviour.register(); ForgeMod.enableMilkFluid(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java index 8e3373c0f..f64220fdd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java @@ -22,22 +22,11 @@ import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Vec3i; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; import net.minecraft.util.Mth; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.horse.Horse; -import net.minecraft.world.entity.animal.horse.SkeletonHorse; import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.monster.EnderMan; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; @@ -53,11 +42,6 @@ import net.minecraftforge.fml.DistExecutor; public class AirCurrent { - private static final DamageSource damageSourceFire = new DamageSource("create.fan_fire").setScalesWithDifficulty() - .setIsFire(); - private static final DamageSource damageSourceLava = new DamageSource("create.fan_lava").setScalesWithDifficulty() - .setIsFire(); - public final IAirCurrentSource source; public AABB bounds = new AABB(0, 0, 0, 0, 0, 0); public List segments = new ArrayList<>(); @@ -134,93 +118,17 @@ public class AirCurrent { continue; } - if (entity instanceof ItemEntity) { - InWorldProcessing.spawnParticlesForProcessing(world, entity.position(), processingType); - ItemEntity itemEntity = (ItemEntity) entity; - if (world.isClientSide) + if (entity instanceof ItemEntity itemEntity) { + if (world.isClientSide) { + processingType.spawnParticlesForProcessing(world, entity.position()); continue; + } if (InWorldProcessing.canProcess(itemEntity, processingType)) InWorldProcessing.applyProcessing(itemEntity, processingType); continue; } - if (entity instanceof Horse && world.isClientSide) { - Vec3 p = entity.getPosition(0); - Vec3 v = p.add(0, 0.5f, 0) - .add(VecHelper.offsetRandomly(Vec3.ZERO, world.random, 1) - .multiply(1, 0.2f, 1) - .normalize() - .scale(1f)); - world.addParticle(ParticleTypes.SOUL_FIRE_FLAME, v.x, v.y, v.z, 0, 0.1f, 0); - if (world.random.nextInt(3) == 0) - world.addParticle(ParticleTypes.LARGE_SMOKE, p.x, p.y + .5f, p.z, - (world.random.nextFloat() - .5f) * .5f, 0.1f, (world.random.nextFloat() - .5f) * .5f); - } - - if (world.isClientSide) - continue; - - switch (processingType) { - case BLASTING: - if (!entity.fireImmune()) { - entity.setSecondsOnFire(10); - entity.hurt(damageSourceLava, 4); - } - break; - case SMOKING: - if (!entity.fireImmune()) { - entity.setSecondsOnFire(2); - entity.hurt(damageSourceFire, 2); - } - break; - case HAUNTING: - if (entity instanceof LivingEntity livingEntity) { - livingEntity.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 30, 0, false, false)); - livingEntity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 20, 1, false, false)); - } - if (entity instanceof Horse horse) { - int progress = horse.getPersistentData() - .getInt("CreateHaunting"); - if (progress < 100) { - if (progress % 10 == 0) { - world.playSound(null, entity.blockPosition(), SoundEvents.SOUL_ESCAPE, SoundSource.NEUTRAL, - 1f, 1.5f * progress / 100f); - } - horse.getPersistentData() - .putInt("CreateHaunting", progress + 1); - continue; - } - - world.playSound(null, entity.blockPosition(), SoundEvents.GENERIC_EXTINGUISH_FIRE, - SoundSource.NEUTRAL, 1.25f, 0.65f); - - SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(world); - CompoundTag serializeNBT = horse.saveWithoutId(new CompoundTag()); - serializeNBT.remove("UUID"); - if (!horse.getArmor() - .isEmpty()) - horse.spawnAtLocation(horse.getArmor()); - - skeletonHorse.deserializeNBT(serializeNBT); - skeletonHorse.setPos(horse.getPosition(0)); - world.addFreshEntity(skeletonHorse); - horse.discard(); - } - break; - case SPLASHING: - if (entity instanceof EnderMan || entity.getType() == EntityType.SNOW_GOLEM - || entity.getType() == EntityType.BLAZE) { - entity.hurt(DamageSource.DROWN, 2); - } - if (!entity.isOnFire()) - break; - entity.clearFire(); - world.playSound(null, entity.blockPosition(), SoundEvents.GENERIC_EXTINGUISH_FIRE, SoundSource.NEUTRAL, - 0.7F, 1.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.4F); - break; - default: - break; - } + processingType.affectEntity(entity, world); } } @@ -375,10 +283,11 @@ public class AirCurrent { InWorldProcessing.Type processingType = pair.getRight(); handler.handleProcessingOnAllItems((transported) -> { - InWorldProcessing.spawnParticlesForProcessing(world, handler.getWorldPositionOf(transported), - processingType); - if (world.isClientSide) + if (world.isClientSide) { + if (world != null) + processingType.spawnParticlesForProcessing(world, handler.getWorldPositionOf(transported)); return TransportedResult.doNothing(); + } return InWorldProcessing.applyProcessing(transported, world, processingType); }); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineBlock.java index 5aae6789f..52ae1031a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineBlock.java @@ -33,7 +33,7 @@ public class FurnaceEngineBlock extends EngineBlock implements ITE + * {@code + * FurnaceEngineInteractions.registerHandler(Blocks.REDSTONE_LAMP.delegate, FurnaceEngineInteractions.InteractionHandler.of( + * s -> s.getBlock() instanceof RedstoneLampBlock && s.hasProperty(RedstoneLampBlock.LIT) ? + * (s.getValue(RedstoneLampBlock.LIT) ? HeatSource.ACTIVE : HeatSource.VALID) : HeatSource.EMPTY, s -> 1.5f)); + * } + * + */ +public class FurnaceEngineInteractions { + + private static final Map, InteractionHandler> HANDLERS = new HashMap<>(); + private static final InteractionHandler DEFAULT_HANDLER = new InteractionHandler() {}; + + public static void registerHandler(IRegistryDelegate block, InteractionHandler handler) { + HANDLERS.put(block, handler); + } + + public static InteractionHandler getHandler(IRegistryDelegate delegate) { + return HANDLERS.getOrDefault(delegate, DEFAULT_HANDLER); + } + + public static InteractionHandler getHandler(BlockState state) { + return getHandler(state.getBlock().delegate); + } + + public static void registerDefaults() { + registerHandler(Blocks.BLAST_FURNACE.delegate, InteractionHandler.ofCustomSpeedModifier(state -> 2f)); + } + + public interface InteractionHandler { + default HeatSource getHeatSource(BlockState state) { + if (state.getBlock() instanceof AbstractFurnaceBlock && state.hasProperty(AbstractFurnaceBlock.LIT)) { + if (state.getValue(AbstractFurnaceBlock.LIT)) { + return HeatSource.ACTIVE; + } else { + return HeatSource.VALID; + } + } + return HeatSource.EMPTY; + } + + default float getSpeedModifier(BlockState state) { + return 1f; + }; + + static InteractionHandler of(Function heatSourceFunc, Function speedModifierFunc) { + return new InteractionHandler() { + @Override + public HeatSource getHeatSource(BlockState state) { + return heatSourceFunc.apply(state); + } + + @Override + public float getSpeedModifier(BlockState state) { + return speedModifierFunc.apply(state); + } + }; + } + + static InteractionHandler ofCustomHeatSource(Function heatSourceFunc) { + return new InteractionHandler() { + @Override + public HeatSource getHeatSource(BlockState state) { + return heatSourceFunc.apply(state); + } + }; + } + + static InteractionHandler ofCustomSpeedModifier(Function speedModifierFunc) { + return new InteractionHandler() { + @Override + public float getSpeedModifier(BlockState state) { + return speedModifierFunc.apply(state); + } + }; + } + } + + public enum HeatSource { + EMPTY, + VALID, + ACTIVE; + + public boolean isEmpty() { + return this == EMPTY; + } + + public boolean isValid() { + return this != EMPTY; + } + + public boolean isActive() { + return this == ACTIVE; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineModifiers.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineModifiers.java deleted file mode 100644 index 016d22b77..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineModifiers.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.simibubi.create.content.contraptions.components.flywheel.engine; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - -import net.minecraft.world.level.block.AbstractFurnaceBlock; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.registries.IRegistryDelegate; - -public class FurnaceEngineModifiers { - - private final static FurnaceEngineModifiers INSTANCE = new FurnaceEngineModifiers(); - - protected FurnaceEngineModifiers() { - blockModifiers = new HashMap<>(); - blockActivators = new HashMap<>(); - } - - private final Map, Float> blockModifiers; - private final Map, Function> blockActivators; - - public void register(IRegistryDelegate block, float modifier) { - this.blockModifiers.put(block, modifier); - } - - public void register(IRegistryDelegate block, float modifier, Function engineState) { - this.blockModifiers.put(block, modifier); - this.blockActivators.put(block, engineState); - } - - private float getModifierOrDefault(BlockState state, float defaultValue) { - return blockModifiers.getOrDefault(state.getBlock().delegate, defaultValue); - } - - private Function getEngineStateOrDefault(BlockState state, Function engineState) { - return blockActivators.getOrDefault(state.getBlock().delegate, engineState); - } - - public float getModifier(BlockState state) { - return getModifierOrDefault(state, 1f); - } - - public EngineState getEngineState(BlockState state) { - return getEngineStateOrDefault(state, - s -> s.getBlock() instanceof AbstractFurnaceBlock && s.hasProperty(AbstractFurnaceBlock.LIT) ? - (s.getValue(AbstractFurnaceBlock.LIT) ? EngineState.ACTIVE : EngineState.VALID) : EngineState.EMPTY).apply(state); - } - - public static void register() { - get().register(Blocks.BLAST_FURNACE.delegate, 2f); - - /* - Example: - get().register(Blocks.REDSTONE_LAMP.delegate, 1f, - s -> s.getBlock() instanceof RedstoneLampBlock && s.hasProperty(RedstoneLampBlock.LIT) ? - (s.getValue(RedstoneLampBlock.LIT) ? EngineState.ACTIVE : EngineState.VALID) : EngineState.EMPTY); - */ - } - - public static FurnaceEngineModifiers get() { - return INSTANCE; - } - - public enum EngineState { - EMPTY, - VALID, - ACTIVE; - - public boolean isEngine() { - return this != EMPTY; - } - - public boolean isActive() { - return this == ACTIVE; - } - - public boolean isEmpty() { - return this == EMPTY; - } - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineTileEntity.java index b838b55e6..6e68f475e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineTileEntity.java @@ -1,7 +1,8 @@ package com.simibubi.create.content.contraptions.components.flywheel.engine; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.flywheel.engine.FurnaceEngineModifiers.EngineState; +import com.simibubi.create.content.contraptions.components.flywheel.engine.FurnaceEngineInteractions.HeatSource; +import com.simibubi.create.content.contraptions.components.flywheel.engine.FurnaceEngineInteractions.InteractionHandler; import com.simibubi.create.foundation.block.BlockStressValues; import net.minecraft.core.BlockPos; @@ -22,12 +23,13 @@ public class FurnaceEngineTileEntity extends EngineTileEntity { public void updateFurnace() { BlockState state = level.getBlockState(EngineBlock.getBaseBlockPos(getBlockState(), worldPosition)); - EngineState engineState = FurnaceEngineModifiers.get().getEngineState(state); - if (engineState.isEmpty()) + InteractionHandler handler = FurnaceEngineInteractions.getHandler(state); + HeatSource heatSource = handler.getHeatSource(state); + if (heatSource.isEmpty()) return; - float modifier = FurnaceEngineModifiers.get().getModifier(state); - boolean active = engineState.isActive(); + float modifier = handler.getSpeedModifier(state); + boolean active = heatSource.isActive(); float speed = active ? 16 * modifier : 0; float capacity = (float) (active ? BlockStressValues.getCapacity(AllBlocks.FURNACE_ENGINE.get()) diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/InWorldProcessing.java b/src/main/java/com/simibubi/create/content/contraptions/processing/InWorldProcessing.java index 59ca78aff..e583284c0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/InWorldProcessing.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/InWorldProcessing.java @@ -1,11 +1,19 @@ package com.simibubi.create.content.contraptions.processing; +import static com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.getHeatLevelOf; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + import com.mojang.math.Vector3f; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.content.contraptions.components.fan.HauntingRecipe; import com.simibubi.create.content.contraptions.components.fan.SplashingRecipe; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; +import com.simibubi.create.content.contraptions.processing.burner.LitBlazeBurnerBlock; import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.item.ItemHelper; @@ -17,10 +25,25 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.particles.DustParticleOptions; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; import net.minecraft.tags.BlockTags; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.animal.horse.Horse; +import net.minecraft.world.entity.animal.horse.SkeletonHorse; import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.monster.EnderMan; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.*; +import net.minecraft.world.item.crafting.BlastingRecipe; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.crafting.SmeltingRecipe; +import net.minecraft.world.item.crafting.SmokingRecipe; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; @@ -34,44 +57,16 @@ import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.wrapper.RecipeWrapper; -import javax.annotation.Nullable; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -import static com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.getHeatLevelOf; - public class InWorldProcessing { - private static final RecipeWrapper WRAPPER = new RecipeWrapper(new ItemStackHandler(1)); + private static final DamageSource FIRE_DAMAGE_SOURCE = new DamageSource("create.fan_fire").setScalesWithDifficulty() + .setIsFire(); + private static final DamageSource LAVA_DAMAGE_SOURCE = new DamageSource("create.fan_lava").setScalesWithDifficulty() + .setIsFire(); + + private static final RecipeWrapper RECIPE_WRAPPER = new RecipeWrapper(new ItemStackHandler(1)); private static final SplashingWrapper SPLASHING_WRAPPER = new SplashingWrapper(); - private static final HauntingWrapper SOUL_SMOKING_WRAPPER = new HauntingWrapper(); - - public enum Type { - SMOKING, BLASTING, SPLASHING, HAUNTING, NONE; - - public static Type byBlock(BlockGetter reader, BlockPos pos) { - BlockState blockState = reader.getBlockState(pos); - FluidState fluidState = reader.getFluidState(pos); - if (fluidState.getType() == Fluids.WATER || fluidState.getType() == Fluids.FLOWING_WATER) - return Type.SPLASHING; - Block block = blockState.getBlock(); - if (block == Blocks.SOUL_FIRE - || block == Blocks.SOUL_CAMPFIRE && blockState.getOptionalValue(CampfireBlock.LIT) - .orElse(false)) - return Type.HAUNTING; - if (block == Blocks.FIRE || AllBlocks.LIT_BLAZE_BURNER.has(blockState) - || (BlockTags.CAMPFIRES.contains(block) && blockState.getOptionalValue(CampfireBlock.LIT) - .orElse(false)) - || getHeatLevelOf(blockState) == BlazeBurnerBlock.HeatLevel.SMOULDERING) - return Type.SMOKING; - if (block == Blocks.LAVA || getHeatLevelOf(blockState).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING)) - return Type.BLASTING; - return Type.NONE; - } - } + private static final HauntingWrapper HAUNTING_WRAPPER = new HauntingWrapper(); public static boolean canProcess(ItemEntity entity, Type type) { if (entity.getPersistentData() @@ -82,7 +77,7 @@ public class InWorldProcessing { CompoundTag processing = compound.getCompound("Processing"); if (Type.valueOf(processing.getString("Type")) != type) { - boolean canProcess = canProcess(entity.getItem(), type, entity.level); + boolean canProcess = type.canProcess(entity.getItem(), entity.level); processing.putString("Type", type.name()); if (!canProcess) processing.putInt("Time", -1); @@ -93,43 +88,7 @@ public class InWorldProcessing { return false; } } - return canProcess(entity.getItem(), type, entity.level); - } - - private static boolean canProcess(ItemStack stack, Type type, Level world) { - if (type == Type.BLASTING) { - WRAPPER.setItem(0, stack); - Optional smeltingRecipe = world.getRecipeManager() - .getRecipeFor(RecipeType.SMELTING, WRAPPER, world); - - if (smeltingRecipe.isPresent()) - return true; - - WRAPPER.setItem(0, stack); - Optional blastingRecipe = world.getRecipeManager() - .getRecipeFor(RecipeType.BLASTING, WRAPPER, world); - - if (blastingRecipe.isPresent()) - return true; - - return !stack.getItem() - .isFireResistant(); - } - - if (type == Type.SMOKING) { - WRAPPER.setItem(0, stack); - Optional recipe = world.getRecipeManager() - .getRecipeFor(RecipeType.SMOKING, WRAPPER, world); - return recipe.isPresent(); - } - - if (type == Type.SPLASHING) - return isWashable(stack, world); - - if (type == Type.HAUNTING) - return isSoulSmokeable(stack, world); - - return false; + return type.canProcess(entity.getItem(), entity.level); } public static boolean isWashable(ItemStack stack, Level world) { @@ -138,9 +97,9 @@ public class InWorldProcessing { return recipe.isPresent(); } - public static boolean isSoulSmokeable(ItemStack stack, Level world) { - SOUL_SMOKING_WRAPPER.setItem(0, stack); - Optional recipe = AllRecipeTypes.HAUNTING.find(SOUL_SMOKING_WRAPPER, world); + public static boolean isHauntable(ItemStack stack, Level world) { + HAUNTING_WRAPPER.setItem(0, stack); + Optional recipe = AllRecipeTypes.HAUNTING.find(HAUNTING_WRAPPER, world); return recipe.isPresent(); } @@ -170,7 +129,7 @@ public class InWorldProcessing { int processingTime = (int) (AllConfigs.SERVER.kinetics.inWorldProcessingTime.get() * timeModifierForStackSize) + 1; transported.processingTime = processingTime; - if (!canProcess(transported.stack, type, world)) + if (!type.canProcess(transported.stack, world)) transported.processingTime = -1; return ignore; } @@ -201,29 +160,29 @@ public class InWorldProcessing { return null; } if (type == Type.HAUNTING) { - SOUL_SMOKING_WRAPPER.setItem(0, stack); - Optional recipe = AllRecipeTypes.HAUNTING.find(SOUL_SMOKING_WRAPPER, world); + HAUNTING_WRAPPER.setItem(0, stack); + Optional recipe = AllRecipeTypes.HAUNTING.find(HAUNTING_WRAPPER, world); if (recipe.isPresent()) return applyRecipeOn(stack, recipe.get()); return null; } - WRAPPER.setItem(0, stack); + RECIPE_WRAPPER.setItem(0, stack); Optional smokingRecipe = world.getRecipeManager() - .getRecipeFor(RecipeType.SMOKING, WRAPPER, world); + .getRecipeFor(RecipeType.SMOKING, RECIPE_WRAPPER, world); if (type == Type.BLASTING) { if (!smokingRecipe.isPresent()) { - WRAPPER.setItem(0, stack); + RECIPE_WRAPPER.setItem(0, stack); Optional smeltingRecipe = world.getRecipeManager() - .getRecipeFor(RecipeType.SMELTING, WRAPPER, world); + .getRecipeFor(RecipeType.SMELTING, RECIPE_WRAPPER, world); if (smeltingRecipe.isPresent()) return applyRecipeOn(stack, smeltingRecipe.get()); - WRAPPER.setItem(0, stack); + RECIPE_WRAPPER.setItem(0, stack); Optional blastingRecipe = world.getRecipeManager() - .getRecipeFor(RecipeType.BLASTING, WRAPPER, world); + .getRecipeFor(RecipeType.BLASTING, RECIPE_WRAPPER, world); if (blastingRecipe.isPresent()) return applyRecipeOn(stack, blastingRecipe.get()); @@ -313,37 +272,220 @@ public class InWorldProcessing { return stacks; } - public static void spawnParticlesForProcessing(@Nullable Level world, Vec3 vec, Type type) { - if (world == null || !world.isClientSide) - return; - if (world.random.nextInt(8) != 0) - return; + public enum Type { + SPLASHING { + @Override + public void spawnParticlesForProcessing(Level level, Vec3 pos) { + if (level.random.nextInt(8) != 0) + return; + Vector3f color = new Color(0x0055FF).asVectorF(); + level.addParticle(new DustParticleOptions(color, 1), pos.x + (level.random.nextFloat() - .5f) * .5f, + pos.y + .5f, pos.z + (level.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0); + level.addParticle(ParticleTypes.SPIT, pos.x + (level.random.nextFloat() - .5f) * .5f, pos.y + .5f, + pos.z + (level.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0); + } - switch (type) { - case BLASTING: - world.addParticle(ParticleTypes.LARGE_SMOKE, vec.x, vec.y + .25f, vec.z, 0, 1 / 16f, 0); - break; - case SMOKING: - world.addParticle(ParticleTypes.POOF, vec.x, vec.y + .25f, vec.z, 0, 1 / 16f, 0); - break; - case HAUNTING: - vec = vec.add(VecHelper.offsetRandomly(Vec3.ZERO, world.random, 1) - .multiply(1, 0.05f, 1) - .normalize() - .scale(0.15f)); - world.addParticle(ParticleTypes.SOUL_FIRE_FLAME, vec.x, vec.y + .45f, vec.z, 0, 0, 0); - if (world.random.nextInt(2) == 0) - world.addParticle(ParticleTypes.SMOKE, vec.x, vec.y + .25f, vec.z, 0, 0, 0); - break; - case SPLASHING: - Vector3f color = new Color(0x0055FF).asVectorF(); - world.addParticle(new DustParticleOptions(color, 1), vec.x + (world.random.nextFloat() - .5f) * .5f, - vec.y + .5f, vec.z + (world.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0); - world.addParticle(ParticleTypes.SPIT, vec.x + (world.random.nextFloat() - .5f) * .5f, vec.y + .5f, - vec.z + (world.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0); - break; - default: - break; + @Override + public void affectEntity(Entity entity, Level level) { + if (level.isClientSide) + return; + + if (entity instanceof EnderMan || entity.getType() == EntityType.SNOW_GOLEM + || entity.getType() == EntityType.BLAZE) { + entity.hurt(DamageSource.DROWN, 2); + } + if (entity.isOnFire()) { + entity.clearFire(); + level.playSound(null, entity.blockPosition(), SoundEvents.GENERIC_EXTINGUISH_FIRE, SoundSource.NEUTRAL, + 0.7F, 1.6F + (level.random.nextFloat() - level.random.nextFloat()) * 0.4F); + } + } + + @Override + public boolean canProcess(ItemStack stack, Level level) { + return isWashable(stack, level); + } + }, + SMOKING { + @Override + public void spawnParticlesForProcessing(Level level, Vec3 pos) { + if (level.random.nextInt(8) != 0) + return; + level.addParticle(ParticleTypes.POOF, pos.x, pos.y + .25f, pos.z, 0, 1 / 16f, 0); + } + + @Override + public void affectEntity(Entity entity, Level level) { + if (level.isClientSide) + return; + + if (!entity.fireImmune()) { + entity.setSecondsOnFire(2); + entity.hurt(FIRE_DAMAGE_SOURCE, 2); + } + } + + @Override + public boolean canProcess(ItemStack stack, Level level) { + RECIPE_WRAPPER.setItem(0, stack); + Optional recipe = level.getRecipeManager() + .getRecipeFor(RecipeType.SMOKING, RECIPE_WRAPPER, level); + return recipe.isPresent(); + } + }, + HAUNTING { + @Override + public void spawnParticlesForProcessing(Level level, Vec3 pos) { + if (level.random.nextInt(8) != 0) + return; + pos = pos.add(VecHelper.offsetRandomly(Vec3.ZERO, level.random, 1) + .multiply(1, 0.05f, 1) + .normalize() + .scale(0.15f)); + level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, pos.x, pos.y + .45f, pos.z, 0, 0, 0); + if (level.random.nextInt(2) == 0) + level.addParticle(ParticleTypes.SMOKE, pos.x, pos.y + .25f, pos.z, 0, 0, 0); + } + + @Override + public void affectEntity(Entity entity, Level level) { + if (level.isClientSide) { + if (entity instanceof Horse) { + Vec3 p = entity.getPosition(0); + Vec3 v = p.add(0, 0.5f, 0) + .add(VecHelper.offsetRandomly(Vec3.ZERO, level.random, 1) + .multiply(1, 0.2f, 1) + .normalize() + .scale(1f)); + level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, v.x, v.y, v.z, 0, 0.1f, 0); + if (level.random.nextInt(3) == 0) + level.addParticle(ParticleTypes.LARGE_SMOKE, p.x, p.y + .5f, p.z, + (level.random.nextFloat() - .5f) * .5f, 0.1f, (level.random.nextFloat() - .5f) * .5f); + } + return; + } + + if (entity instanceof LivingEntity livingEntity) { + livingEntity.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 30, 0, false, false)); + livingEntity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 20, 1, false, false)); + } + if (entity instanceof Horse horse) { + int progress = horse.getPersistentData() + .getInt("CreateHaunting"); + if (progress < 100) { + if (progress % 10 == 0) { + level.playSound(null, entity.blockPosition(), SoundEvents.SOUL_ESCAPE, SoundSource.NEUTRAL, + 1f, 1.5f * progress / 100f); + } + horse.getPersistentData() + .putInt("CreateHaunting", progress + 1); + return; + } + + level.playSound(null, entity.blockPosition(), SoundEvents.GENERIC_EXTINGUISH_FIRE, + SoundSource.NEUTRAL, 1.25f, 0.65f); + + SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(level); + CompoundTag serializeNBT = horse.saveWithoutId(new CompoundTag()); + serializeNBT.remove("UUID"); + if (!horse.getArmor() + .isEmpty()) + horse.spawnAtLocation(horse.getArmor()); + + skeletonHorse.deserializeNBT(serializeNBT); + skeletonHorse.setPos(horse.getPosition(0)); + level.addFreshEntity(skeletonHorse); + horse.discard(); + } + } + + @Override + public boolean canProcess(ItemStack stack, Level level) { + return isHauntable(stack, level); + } + }, + BLASTING { + @Override + public void spawnParticlesForProcessing(Level level, Vec3 pos) { + if (level.random.nextInt(8) != 0) + return; + level.addParticle(ParticleTypes.LARGE_SMOKE, pos.x, pos.y + .25f, pos.z, 0, 1 / 16f, 0); + } + + @Override + public void affectEntity(Entity entity, Level level) { + if (level.isClientSide) + return; + + if (!entity.fireImmune()) { + entity.setSecondsOnFire(10); + entity.hurt(LAVA_DAMAGE_SOURCE, 4); + } + } + + @Override + public boolean canProcess(ItemStack stack, Level level) { + RECIPE_WRAPPER.setItem(0, stack); + Optional smeltingRecipe = level.getRecipeManager() + .getRecipeFor(RecipeType.SMELTING, RECIPE_WRAPPER, level); + + if (smeltingRecipe.isPresent()) + return true; + + RECIPE_WRAPPER.setItem(0, stack); + Optional blastingRecipe = level.getRecipeManager() + .getRecipeFor(RecipeType.BLASTING, RECIPE_WRAPPER, level); + + if (blastingRecipe.isPresent()) + return true; + + return !stack.getItem() + .isFireResistant(); + } + }, + NONE { + @Override + public void spawnParticlesForProcessing(Level level, Vec3 pos) { + } + + @Override + public void affectEntity(Entity entity, Level level) { + } + + @Override + public boolean canProcess(ItemStack stack, Level level) { + return false; + } + }; + + public abstract boolean canProcess(ItemStack stack, Level level); + + public abstract void spawnParticlesForProcessing(Level level, Vec3 pos); + + public abstract void affectEntity(Entity entity, Level level); + + public static Type byBlock(BlockGetter reader, BlockPos pos) { + FluidState fluidState = reader.getFluidState(pos); + if (fluidState.getType() == Fluids.WATER || fluidState.getType() == Fluids.FLOWING_WATER) + return Type.SPLASHING; + BlockState blockState = reader.getBlockState(pos); + Block block = blockState.getBlock(); + if (block == Blocks.SOUL_FIRE + || block == Blocks.SOUL_CAMPFIRE && blockState.getOptionalValue(CampfireBlock.LIT) + .orElse(false) + || AllBlocks.LIT_BLAZE_BURNER.has(blockState) && blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE) + .map(flame -> flame == LitBlazeBurnerBlock.FlameType.SOUL).orElse(false)) + return Type.HAUNTING; + if (block == Blocks.FIRE + || BlockTags.CAMPFIRES.contains(block) && blockState.getOptionalValue(CampfireBlock.LIT) + .orElse(false) + || AllBlocks.LIT_BLAZE_BURNER.has(blockState) && blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE) + .map(flame -> flame == LitBlazeBurnerBlock.FlameType.REGULAR).orElse(false) + || getHeatLevelOf(blockState) == BlazeBurnerBlock.HeatLevel.SMOULDERING) + return Type.SMOKING; + if (block == Blocks.LAVA || getHeatLevelOf(blockState).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING)) + return Type.BLASTING; + return Type.NONE; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/LitBlazeBurnerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/LitBlazeBurnerBlock.java index af575c802..72efff729 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/LitBlazeBurnerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/LitBlazeBurnerBlock.java @@ -4,6 +4,7 @@ import java.util.Random; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; +import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.foundation.utility.Lang; @@ -17,6 +18,7 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ShovelItem; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; @@ -30,9 +32,12 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.ToolAction; public class LitBlazeBurnerBlock extends Block implements IWrenchable { + public static final ToolAction EXTINGUISH_FLAME_ACTION = ToolAction.get(Create.asResource("extinguish_flame").toString()); + public static final EnumProperty FLAME_TYPE = EnumProperty.create("flame_type", FlameType.class); public LitBlazeBurnerBlock(Properties properties) { @@ -51,6 +56,15 @@ public class LitBlazeBurnerBlock extends Block implements IWrenchable { BlockHitResult blockRayTraceResult) { ItemStack heldItem = player.getItemInHand(hand); + if (heldItem.getItem() instanceof ShovelItem || heldItem.getItem().canPerformAction(heldItem, EXTINGUISH_FLAME_ACTION)) { + world.playSound(player, pos, SoundEvents.GENERIC_EXTINGUISH_FIRE, SoundSource.BLOCKS, 0.5f, 2); + if (world.isClientSide) + return InteractionResult.SUCCESS; + heldItem.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(hand)); + world.setBlockAndUpdate(pos, AllBlocks.BLAZE_BURNER.getDefaultState()); + return InteractionResult.SUCCESS; + } + if (state.getValue(FLAME_TYPE) == FlameType.REGULAR) { if (heldItem.is(ItemTags.SOUL_FIRE_BASE_BLOCKS)) { world.playSound(player, pos, SoundEvents.SOUL_SAND_PLACE, SoundSource.BLOCKS, 1.0f, world.random.nextFloat() * 0.4F + 0.8F); diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java index 16a78990c..5a3f886a4 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java @@ -139,6 +139,7 @@ public interface ItemAttribute { EQUIPABLE(s -> s.getEquipmentSlot() != null), FURNACE_FUEL(AbstractFurnaceBlockEntity::isFuel), WASHABLE(InWorldProcessing::isWashable), + HAUNTABLE(InWorldProcessing::isHauntable), CRUSHABLE((s, w) -> testRecipe(s, w, AllRecipeTypes.CRUSHING.getType()) || testRecipe(s, w, AllRecipeTypes.MILLING.getType())), SMELTABLE((s, w) -> testRecipe(s, w, RecipeType.SMELTING)), diff --git a/src/main/resources/assets/create/lang/default/interface.json b/src/main/resources/assets/create/lang/default/interface.json index 8926fd8b2..4ebd988d5 100644 --- a/src/main/resources/assets/create/lang/default/interface.json +++ b/src/main/resources/assets/create/lang/default/interface.json @@ -392,6 +392,8 @@ "create.item_attributes.furnace_fuel.inverted": "is not furnace fuel", "create.item_attributes.washable": "can be Washed", "create.item_attributes.washable.inverted": "cannot be Washed", + "create.item_attributes.hauntable": "can be Haunted", + "create.item_attributes.hauntable.inverted": "cannot be Haunted", "create.item_attributes.crushable": "can be Crushed", "create.item_attributes.crushable.inverted": "cannot be Crushed", "create.item_attributes.smeltable": "can be Smelted",