diff --git a/logs/latest.log b/logs/latest.log new file mode 100644 index 000000000..e69de29bb diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 44ee6b84e..9a774dc8e 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -5067,6 +5067,13 @@ a5d23be4cc959eb47d84b210190abaafcf41f022 data/create/recipes/smelting/zinc_ingot 4e622fc77e2a630af1b4115e0c60d55682baff72 data/create/recipes/smelting/zinc_ingot_from_ore.json 4060cc921ea26b36cf5a505048f4a812f0569ae0 data/create/recipes/smelting/zinc_ingot_from_raw_ore.json ce7c3c6e1da9d6684c9537d1a558423925d89f33 data/create/recipes/smoking/bread.json +48e174e7f7347661985f4a488e939a785d7b9d2a data/create/recipes/soul_smoking/blackstone.json +bcb8362ef040fef36809a3980eb61ced8874aa5a data/create/recipes/soul_smoking/crimson_fungus.json +8070b6b69fb709e82a335873a0bddf67937069ba data/create/recipes/soul_smoking/crimson_nylium.json +4edd9fee0f61498209d0fd47701fd14a7188b2f9 data/create/recipes/soul_smoking/soul_sand.json +36e1d970622843713789f8fa25c7de09236bc39f data/create/recipes/soul_smoking/soul_soil.json +a7f50385d27c6c8ecdb813eb32f0ceb5336ba972 data/create/recipes/soul_smoking/warped_fungus.json +979bfbb98af35cfe7a8129e2c4cffa95923ce4b9 data/create/recipes/soul_smoking/warped_nylium.json 6b1d2483fe717657f7188f6490eab2da715609e8 data/create/recipes/splashing/black_concrete_powder.json 1aedfde11712827604bbef34e992c411c0b02876 data/create/recipes/splashing/blue_concrete_powder.json 6e11d592dc9b19c4cd9bf2df2aa46b7ec4d9a331 data/create/recipes/splashing/brown_concrete_powder.json diff --git a/src/generated/resources/data/create/recipes/soul_smoking/blackstone.json b/src/generated/resources/data/create/recipes/soul_smoking/blackstone.json new file mode 100644 index 000000000..edc3155f0 --- /dev/null +++ b/src/generated/resources/data/create/recipes/soul_smoking/blackstone.json @@ -0,0 +1,13 @@ +{ + "type": "create:soul_smoking", + "ingredients": [ + { + "item": "minecraft:cobblestone" + } + ], + "results": [ + { + "item": "minecraft:blackstone" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/soul_smoking/crimson_fungus.json b/src/generated/resources/data/create/recipes/soul_smoking/crimson_fungus.json new file mode 100644 index 000000000..deaef1311 --- /dev/null +++ b/src/generated/resources/data/create/recipes/soul_smoking/crimson_fungus.json @@ -0,0 +1,13 @@ +{ + "type": "create:soul_smoking", + "ingredients": [ + { + "item": "minecraft:red_mushroom" + } + ], + "results": [ + { + "item": "minecraft:crimson_fungus" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/soul_smoking/crimson_nylium.json b/src/generated/resources/data/create/recipes/soul_smoking/crimson_nylium.json new file mode 100644 index 000000000..6501e9fd8 --- /dev/null +++ b/src/generated/resources/data/create/recipes/soul_smoking/crimson_nylium.json @@ -0,0 +1,13 @@ +{ + "type": "create:soul_smoking", + "ingredients": [ + { + "item": "minecraft:mycelium" + } + ], + "results": [ + { + "item": "minecraft:crimson_nylium" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/soul_smoking/soul_sand.json b/src/generated/resources/data/create/recipes/soul_smoking/soul_sand.json new file mode 100644 index 000000000..9715b0002 --- /dev/null +++ b/src/generated/resources/data/create/recipes/soul_smoking/soul_sand.json @@ -0,0 +1,18 @@ +{ + "type": "create:soul_smoking", + "ingredients": [ + [ + { + "item": "minecraft:sand" + }, + { + "item": "minecraft:red_sand" + } + ] + ], + "results": [ + { + "item": "minecraft:soul_sand" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/soul_smoking/soul_soil.json b/src/generated/resources/data/create/recipes/soul_smoking/soul_soil.json new file mode 100644 index 000000000..4a562d7fd --- /dev/null +++ b/src/generated/resources/data/create/recipes/soul_smoking/soul_soil.json @@ -0,0 +1,21 @@ +{ + "type": "create:soul_smoking", + "ingredients": [ + [ + { + "item": "minecraft:dirt" + }, + { + "item": "minecraft:coarse_dirt" + }, + { + "item": "minecraft:rooted_dirt" + } + ] + ], + "results": [ + { + "item": "minecraft:soul_soil" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/soul_smoking/warped_fungus.json b/src/generated/resources/data/create/recipes/soul_smoking/warped_fungus.json new file mode 100644 index 000000000..e0e871821 --- /dev/null +++ b/src/generated/resources/data/create/recipes/soul_smoking/warped_fungus.json @@ -0,0 +1,13 @@ +{ + "type": "create:soul_smoking", + "ingredients": [ + { + "item": "minecraft:brown_mushroom" + } + ], + "results": [ + { + "item": "minecraft:warped_fungus" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/soul_smoking/warped_nylium.json b/src/generated/resources/data/create/recipes/soul_smoking/warped_nylium.json new file mode 100644 index 000000000..abf714bd1 --- /dev/null +++ b/src/generated/resources/data/create/recipes/soul_smoking/warped_nylium.json @@ -0,0 +1,13 @@ +{ + "type": "create:soul_smoking", + "ingredients": [ + { + "item": "minecraft:podzol" + } + ], + "results": [ + { + "item": "minecraft:warped_nylium" + } + ] +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/AllRecipeTypes.java b/src/main/java/com/simibubi/create/AllRecipeTypes.java index 911e62da7..4f1fdb180 100644 --- a/src/main/java/com/simibubi/create/AllRecipeTypes.java +++ b/src/main/java/com/simibubi/create/AllRecipeTypes.java @@ -7,6 +7,7 @@ import com.simibubi.create.compat.jei.ConversionRecipe; import com.simibubi.create.content.contraptions.components.crafter.MechanicalCraftingRecipe; import com.simibubi.create.content.contraptions.components.crusher.CrushingRecipe; import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe; +import com.simibubi.create.content.contraptions.components.fan.SoulSmokingRecipe; import com.simibubi.create.content.contraptions.components.fan.SplashingRecipe; import com.simibubi.create.content.contraptions.components.millstone.MillingRecipe; import com.simibubi.create.content.contraptions.components.mixer.CompactingRecipe; @@ -47,6 +48,7 @@ public enum AllRecipeTypes implements IRecipeTypeInfo { PRESSING(PressingRecipe::new), SANDPAPER_POLISHING(SandPaperPolishingRecipe::new), SPLASHING(SplashingRecipe::new), + SOUL_SMOKING(SoulSmokingRecipe::new), DEPLOYING(DeployerApplicationRecipe::new), FILLING(FillingRecipe::new), EMPTYING(EmptyingRecipe::new), diff --git a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java index 58abac194..0b7719c58 100644 --- a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java +++ b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java @@ -1,41 +1,9 @@ package com.simibubi.create.compat.jei; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import javax.annotation.Nonnull; - import com.google.common.base.Predicates; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllFluids; -import com.simibubi.create.AllItems; -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.Create; -import com.simibubi.create.compat.jei.category.BlockCuttingCategory; +import com.simibubi.create.*; +import com.simibubi.create.compat.jei.category.*; import com.simibubi.create.compat.jei.category.BlockCuttingCategory.CondensedBlockCuttingRecipe; -import com.simibubi.create.compat.jei.category.CreateRecipeCategory; -import com.simibubi.create.compat.jei.category.CrushingCategory; -import com.simibubi.create.compat.jei.category.DeployingCategory; -import com.simibubi.create.compat.jei.category.FanBlastingCategory; -import com.simibubi.create.compat.jei.category.FanSmokingCategory; -import com.simibubi.create.compat.jei.category.FanWashingCategory; -import com.simibubi.create.compat.jei.category.ItemDrainCategory; -import com.simibubi.create.compat.jei.category.MechanicalCraftingCategory; -import com.simibubi.create.compat.jei.category.MillingCategory; -import com.simibubi.create.compat.jei.category.MixingCategory; -import com.simibubi.create.compat.jei.category.MysteriousItemConversionCategory; -import com.simibubi.create.compat.jei.category.PackingCategory; -import com.simibubi.create.compat.jei.category.PolishingCategory; -import com.simibubi.create.compat.jei.category.PressingCategory; -import com.simibubi.create.compat.jei.category.ProcessingViaFanCategory; -import com.simibubi.create.compat.jei.category.SawingCategory; -import com.simibubi.create.compat.jei.category.SequencedAssemblyCategory; -import com.simibubi.create.compat.jei.category.SpoutCategory; import com.simibubi.create.content.contraptions.components.crafter.MechanicalCraftingRecipe; import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe; import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity; @@ -55,25 +23,26 @@ import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo; import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; import mezz.jei.api.constants.VanillaRecipeCategoryUid; -import mezz.jei.api.registration.IGuiHandlerRegistration; -import mezz.jei.api.registration.IRecipeCatalystRegistration; -import mezz.jei.api.registration.IRecipeCategoryRegistration; -import mezz.jei.api.registration.IRecipeRegistration; -import mezz.jei.api.registration.IRecipeTransferRegistration; -import mezz.jei.api.registration.ISubtypeRegistration; +import mezz.jei.api.registration.*; import mezz.jei.api.runtime.IIngredientManager; import net.minecraft.client.Minecraft; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.CraftingRecipe; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.item.crafting.ShapedRecipe; +import net.minecraft.world.item.crafting.*; import net.minecraft.world.level.ItemLike; import net.minecraftforge.fml.ModList; +import javax.annotation.Nonnull; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Collectors; + @JeiPlugin @SuppressWarnings("unused") public class CreateJEI implements IModPlugin { @@ -84,139 +53,142 @@ public class CreateJEI implements IModPlugin { private final List> allCategories = new ArrayList<>(); private final CreateRecipeCategory - milling = register("milling", MillingCategory::new).recipes(AllRecipeTypes.MILLING) - .catalyst(AllBlocks.MILLSTONE::get) - .build(), + milling = register("milling", MillingCategory::new).recipes(AllRecipeTypes.MILLING) + .catalyst(AllBlocks.MILLSTONE::get) + .build(), - crushing = register("crushing", CrushingCategory::new).recipes(AllRecipeTypes.CRUSHING) + crushing = register("crushing", CrushingCategory::new).recipes(AllRecipeTypes.CRUSHING) .recipesExcluding(AllRecipeTypes.MILLING::getType, AllRecipeTypes.CRUSHING::getType) .catalyst(AllBlocks.CRUSHING_WHEEL::get) .build(), - pressing = register("pressing", PressingCategory::new).recipes(AllRecipeTypes.PRESSING) + pressing = register("pressing", PressingCategory::new).recipes(AllRecipeTypes.PRESSING) .catalyst(AllBlocks.MECHANICAL_PRESS::get) .build(), - washing = register("fan_washing", FanWashingCategory::new).recipes(AllRecipeTypes.SPLASHING) + washing = register("fan_washing", FanWashingCategory::new).recipes(AllRecipeTypes.SPLASHING) .catalystStack(ProcessingViaFanCategory.getFan("fan_washing")) .build(), - smoking = register("fan_smoking", FanSmokingCategory::new).recipes(() -> RecipeType.SMOKING) + smoking = register("fan_smoking", FanSmokingCategory::new).recipes(() -> RecipeType.SMOKING) .catalystStack(ProcessingViaFanCategory.getFan("fan_smoking")) .build(), - blasting = register("fan_blasting", FanBlastingCategory::new) + soul_smoking = register("fan_soul_smoking", FanSoulSmokingCategory::new).recipes(AllRecipeTypes.SOUL_SMOKING) + .catalystStack(ProcessingViaFanCategory.getFan("fan_soul_smoking")).build(), + + blasting = register("fan_blasting", FanBlastingCategory::new) .recipesExcluding(() -> RecipeType.SMELTING, () -> RecipeType.BLASTING) .recipes(() -> RecipeType.BLASTING) .removeRecipes(() -> RecipeType.SMOKING) .catalystStack(ProcessingViaFanCategory.getFan("fan_blasting")) .build(), - mixing = register("mixing", MixingCategory::standard).recipes(AllRecipeTypes.MIXING::getType) + mixing = register("mixing", MixingCategory::standard).recipes(AllRecipeTypes.MIXING::getType) .catalyst(AllBlocks.MECHANICAL_MIXER::get) .catalyst(AllBlocks.BASIN::get) .build(), - seqAssembly = register("sequenced_assembly", SequencedAssemblyCategory::new) + seqAssembly = register("sequenced_assembly", SequencedAssemblyCategory::new) .recipes(AllRecipeTypes.SEQUENCED_ASSEMBLY::getType) .build(), - autoShapeless = register("automatic_shapeless", MixingCategory::autoShapeless) + autoShapeless = register("automatic_shapeless", MixingCategory::autoShapeless) .recipes(r -> r.getSerializer() == RecipeSerializer.SHAPELESS_RECIPE && r.getIngredients() - .size() > 1 && !MechanicalPressTileEntity.canCompress(r) && !AllRecipeTypes.isManualRecipe(r), - BasinRecipe::convertShapeless) + .size() > 1 && !MechanicalPressTileEntity.canCompress(r) && !AllRecipeTypes.isManualRecipe(r), + BasinRecipe::convertShapeless) .catalyst(AllBlocks.MECHANICAL_MIXER::get) .catalyst(AllBlocks.BASIN::get) .enableWhen(c -> c.allowShapelessInMixer) .build(), - brewing = register("automatic_brewing", MixingCategory::autoBrewing) + brewing = register("automatic_brewing", MixingCategory::autoBrewing) .recipeList(PotionMixingRecipeManager::getAllBrewingRecipes) .catalyst(AllBlocks.MECHANICAL_MIXER::get) .catalyst(AllBlocks.BASIN::get) .build(), - sawing = register("sawing", SawingCategory::new).recipes(AllRecipeTypes.CUTTING) + sawing = register("sawing", SawingCategory::new).recipes(AllRecipeTypes.CUTTING) .catalyst(AllBlocks.MECHANICAL_SAW::get) .build(), - blockCutting = register("block_cutting", () -> new BlockCuttingCategory(Items.STONE_BRICK_STAIRS)) + blockCutting = register("block_cutting", () -> new BlockCuttingCategory(Items.STONE_BRICK_STAIRS)) .recipeList(() -> CondensedBlockCuttingRecipe.condenseRecipes(findRecipes( - recipe -> recipe.getType() == RecipeType.STONECUTTING && !AllRecipeTypes.isManualRecipe(recipe)))) + recipe -> recipe.getType() == RecipeType.STONECUTTING && !AllRecipeTypes.isManualRecipe(recipe)))) .catalyst(AllBlocks.MECHANICAL_SAW::get) .enableWhen(c -> c.allowStonecuttingOnSaw) .build(), - woodCutting = register("wood_cutting", () -> new BlockCuttingCategory(Items.OAK_STAIRS)) + woodCutting = register("wood_cutting", () -> new BlockCuttingCategory(Items.OAK_STAIRS)) .recipeList(() -> CondensedBlockCuttingRecipe - .condenseRecipes(findRecipes(recipe -> recipe.getType() == SawTileEntity.woodcuttingRecipeType.get() - && !AllRecipeTypes.isManualRecipe(recipe)))) + .condenseRecipes(findRecipes(recipe -> recipe.getType() == SawTileEntity.woodcuttingRecipeType.get() + && !AllRecipeTypes.isManualRecipe(recipe)))) .catalyst(AllBlocks.MECHANICAL_SAW::get) .enableWhenBool(c -> c.allowWoodcuttingOnSaw.get() && ModList.get() - .isLoaded("druidcraft")) + .isLoaded("druidcraft")) .build(), - packing = register("packing", PackingCategory::standard).recipes(AllRecipeTypes.COMPACTING) + packing = register("packing", PackingCategory::standard).recipes(AllRecipeTypes.COMPACTING) .catalyst(AllBlocks.MECHANICAL_PRESS::get) .catalyst(AllBlocks.BASIN::get) .build(), - autoSquare = register("automatic_packing", PackingCategory::autoSquare) + autoSquare = register("automatic_packing", PackingCategory::autoSquare) .recipes( - r -> (r instanceof CraftingRecipe) && !(r instanceof MechanicalCraftingRecipe) - && MechanicalPressTileEntity.canCompress(r) && !AllRecipeTypes.isManualRecipe(r), - BasinRecipe::convertShapeless) + r -> (r instanceof CraftingRecipe) && !(r instanceof MechanicalCraftingRecipe) + && MechanicalPressTileEntity.canCompress(r) && !AllRecipeTypes.isManualRecipe(r), + BasinRecipe::convertShapeless) .catalyst(AllBlocks.MECHANICAL_PRESS::get) .catalyst(AllBlocks.BASIN::get) .enableWhen(c -> c.allowShapedSquareInPress) .build(), - polishing = register("sandpaper_polishing", PolishingCategory::new).recipes(AllRecipeTypes.SANDPAPER_POLISHING) + polishing = register("sandpaper_polishing", PolishingCategory::new).recipes(AllRecipeTypes.SANDPAPER_POLISHING) .catalyst(AllItems.SAND_PAPER::get) .catalyst(AllItems.RED_SAND_PAPER::get) .build(), - deploying = register("deploying", DeployingCategory::new) + deploying = register("deploying", DeployingCategory::new) .recipeList(() -> DeployerApplicationRecipe - .convert(findRecipesByType(AllRecipeTypes.SANDPAPER_POLISHING.getType()))) + .convert(findRecipesByType(AllRecipeTypes.SANDPAPER_POLISHING.getType()))) .recipes(AllRecipeTypes.DEPLOYING) .catalyst(AllBlocks.DEPLOYER::get) .catalyst(AllBlocks.DEPOT::get) .catalyst(AllItems.BELT_CONNECTOR::get) .build(), - mysteryConversion = register("mystery_conversion", MysteriousItemConversionCategory::new) + mysteryConversion = register("mystery_conversion", MysteriousItemConversionCategory::new) .recipeList(MysteriousItemConversionCategory::getRecipes) .build(), - spoutFilling = register("spout_filling", SpoutCategory::new).recipes(AllRecipeTypes.FILLING) + spoutFilling = register("spout_filling", SpoutCategory::new).recipes(AllRecipeTypes.FILLING) .recipeList(() -> SpoutCategory.getRecipes(ingredientManager)) .catalyst(AllBlocks.SPOUT::get) .build(), - draining = register("draining", ItemDrainCategory::new) + draining = register("draining", ItemDrainCategory::new) .recipeList(() -> ItemDrainCategory.getRecipes(ingredientManager)) .recipes(AllRecipeTypes.EMPTYING) .catalyst(AllBlocks.ITEM_DRAIN::get) .build(), - autoShaped = register("automatic_shaped", MechanicalCraftingCategory::new) + autoShaped = register("automatic_shaped", MechanicalCraftingCategory::new) .recipes(r -> r.getSerializer() == RecipeSerializer.SHAPELESS_RECIPE && r.getIngredients() - .size() == 1) + .size() == 1) .recipes(r -> (r.getType() == RecipeType.CRAFTING - && r.getType() != AllRecipeTypes.MECHANICAL_CRAFTING.getType()) && (r instanceof ShapedRecipe) - && !AllRecipeTypes.isManualRecipe(r)) + && r.getType() != AllRecipeTypes.MECHANICAL_CRAFTING.getType()) && (r instanceof ShapedRecipe) + && !AllRecipeTypes.isManualRecipe(r)) .catalyst(AllBlocks.MECHANICAL_CRAFTER::get) .enableWhen(c -> c.allowRegularCraftingInCrafter) .build(), - mechanicalCrafting = + mechanicalCrafting = register("mechanical_crafting", MechanicalCraftingCategory::new).recipes(AllRecipeTypes.MECHANICAL_CRAFTING) - .catalyst(AllBlocks.MECHANICAL_CRAFTER::get) - .build(); + .catalyst(AllBlocks.MECHANICAL_CRAFTER::get) + .build(); private > CategoryBuilder register(String name, - Supplier> supplier) { + Supplier> supplier) { return new CategoryBuilder(name, supplier); } @@ -250,7 +222,7 @@ public class CreateJEI implements IModPlugin { allCategories.forEach(c -> c.recipes.forEach(s -> registration.addRecipes(s.get(), c.getUid()))); registration.addRecipes(ToolboxColoringRecipeMaker.createRecipes() - .collect(Collectors.toList()), VanillaRecipeCategoryUid.CRAFTING); + .collect(Collectors.toList()), VanillaRecipeCategoryUid.CRAFTING); } @Override @@ -258,7 +230,7 @@ public class CreateJEI implements IModPlugin { allCategories.forEach(c -> c.recipeCatalysts.forEach(s -> registration.addRecipeCatalyst(s.get(), c.getUid()))); } - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) @Override public void registerGuiHandlers(IGuiHandlerRegistration registration) { registration.addGenericGuiContainerHandler(AbstractSimiContainerScreen.class, new SlotMover()); @@ -289,8 +261,8 @@ public class CreateJEI implements IModPlugin { public CategoryBuilder recipes(ResourceLocation serializer) { return recipes(r -> r.getSerializer() - .getRegistryName() - .equals(serializer)); + .getRegistryName() + .equals(serializer)); } public CategoryBuilder recipes(Predicate> pred) { @@ -306,20 +278,20 @@ public class CreateJEI implements IModPlugin { } public CategoryBuilder recipeList(Supplier>> list, - Function, T> converter) { + Function, T> converter) { recipeListConsumers.add(recipes -> { List> toAdd = list.get(); if (converter != null) toAdd = toAdd.stream() - .map(converter) - .collect(Collectors.toList()); + .map(converter) + .collect(Collectors.toList()); recipes.addAll(toAdd); }); return this; } public CategoryBuilder recipesExcluding(Supplier> recipeType, - Supplier> excluded) { + Supplier> excluded) { recipeListConsumers.add(recipes -> { recipes.addAll(findRecipesByTypeExcluding(recipeType.get(), excluded.get())); }); @@ -335,7 +307,7 @@ public class CreateJEI implements IModPlugin { public CategoryBuilder catalyst(Supplier supplier) { return catalystStack(() -> new ItemStack(supplier.get() - .asItem())); + .asItem())); } public CategoryBuilder catalystStack(Supplier supplier) { @@ -345,7 +317,7 @@ public class CreateJEI implements IModPlugin { public CategoryBuilder enableWhen(Function configValue) { pred = c -> configValue.apply(c) - .get(); + .get(); return this; } @@ -370,10 +342,10 @@ public class CreateJEI implements IModPlugin { public static List> findRecipes(Predicate> predicate) { return Minecraft.getInstance().level.getRecipeManager() - .getRecipes() - .stream() - .filter(predicate) - .collect(Collectors.toList()); + .getRecipes() + .stream() + .filter(predicate) + .collect(Collectors.toList()); } public static List> findRecipesByType(RecipeType type) { @@ -405,13 +377,13 @@ public class CreateJEI implements IModPlugin { public static boolean doInputsMatch(Recipe recipe1, Recipe recipe2) { ItemStack[] matchingStacks = recipe1.getIngredients() - .get(0) - .getItems(); + .get(0) + .getItems(); if (matchingStacks.length == 0) return true; if (recipe2.getIngredients() - .get(0) - .test(matchingStacks[0])) + .get(0) + .test(matchingStacks[0])) return true; return false; } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/FanSoulSmokingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/FanSoulSmokingCategory.java new file mode 100644 index 000000000..cee43bcd6 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/category/FanSoulSmokingCategory.java @@ -0,0 +1,107 @@ +package com.simibubi.create.compat.jei.category; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllItems; +import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; +import com.simibubi.create.content.contraptions.components.fan.SoulSmokingRecipe; +import com.simibubi.create.content.contraptions.components.fan.SplashingRecipe; +import com.simibubi.create.content.contraptions.processing.ProcessingOutput; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.element.GuiGameElement; + +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; +import mezz.jei.api.ingredients.IIngredients; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.material.Fluids; + +import java.util.Arrays; +import java.util.List; + +public class FanSoulSmokingCategory extends ProcessingViaFanCategory { + + public FanSoulSmokingCategory() { + super(185, doubleItemIcon(AllItems.PROPELLER.get(), Items.SOUL_CAMPFIRE)); + } + + @Override + public Class getRecipeClass() { + return SoulSmokingRecipe.class; + } + + @Override + public void setIngredients(SoulSmokingRecipe recipe, IIngredients ingredients) { + ingredients.setInputIngredients(recipe.getIngredients()); + ingredients.setOutputs(VanillaTypes.ITEM, recipe.getRollableResultsAsItemStacks()); + } + + @Override + public void setRecipe(IRecipeLayout recipeLayout, SoulSmokingRecipe recipe, IIngredients ingredients) { + IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); + List results = recipe.getRollableResults(); + int xOffsetGlobal = 8 * (3 - Math.min(3, results.size())); + + itemStacks.init(0, true, xOffsetGlobal + 12, 47); + itemStacks.set(0, Arrays.asList(recipe.getIngredients() + .get(0) + .getItems())); + + boolean single = results.size() == 1; + boolean excessive = results.size() > 9; + for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { + int xOffset = (outputIndex % 3) * 19; + int yOffset = (outputIndex / 3) * -19; + + itemStacks.init(outputIndex + 1, false, xOffsetGlobal + (single ? 126 : 126 + xOffset), + 47 + yOffset + (excessive ? 8 : 0)); + itemStacks.set(outputIndex + 1, results.get(outputIndex) + .getStack()); + } + + addStochasticTooltip(itemStacks, results); + } + + @Override + protected void renderWidgets(PoseStack matrixStack, SoulSmokingRecipe recipe, double mouseX, double mouseY) { + int size = recipe.getRollableResultsAsItemStacks() + .size(); + int xOffsetGlobal = 8 * (3 - Math.min(3, size)); + + AllGuiTextures.JEI_SLOT.render(matrixStack, xOffsetGlobal + 12, 47); + AllGuiTextures.JEI_SHADOW.render(matrixStack, 47 + 4, 29); + AllGuiTextures.JEI_SHADOW.render(matrixStack, 66 + 4, 39); + AllGuiTextures.JEI_LONG_ARROW.render(matrixStack, xOffsetGlobal + 42, 51); + + if (size == 1) { + getRenderedSlot(recipe, 0).render(matrixStack, xOffsetGlobal + 126, 47); + return; + } + + for (int i = 0; i < size; i++) { + int xOffset = (i % 3) * 19; + int yOffset = (i / 3) * -19 + (size > 9 ? 8 : 0); + getRenderedSlot(recipe, i).render(matrixStack, xOffsetGlobal + 126 + xOffset, 47 + yOffset); + } + } + + @Override + protected void translateFan(PoseStack ms) { + ms.translate(56 + 4, 33, 0); + } + + @Override + public void renderAttachedBlock(PoseStack matrixStack) { + matrixStack.pushPose(); + + GuiGameElement.of(Blocks.SOUL_FIRE.defaultBlockState()) + .scale(24) + .atLocal(0, 0, 2) + .lighting(AnimatedKinetics.DEFAULT_LIGHTING) + .render(matrixStack); + + matrixStack.popPose(); + } + +} 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 560cdd5ea..df7b6617a 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 @@ -1,11 +1,5 @@ package com.simibubi.create.content.contraptions.components.fan; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.lang3.tuple.Pair; - import com.simibubi.create.AllTags; import com.simibubi.create.content.contraptions.particle.AirFlowParticleData; import com.simibubi.create.content.contraptions.processing.InWorldProcessing; @@ -27,8 +21,11 @@ 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.item.ItemEntity; import net.minecraft.world.entity.monster.EnderMan; import net.minecraft.world.entity.player.Player; @@ -44,12 +41,18 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + public class AirCurrent { private static final DamageSource damageSourceFire = new DamageSource("create.fan_fire").setScalesWithDifficulty() - .setIsFire(); + .setIsFire(); private static final DamageSource damageSourceLava = new DamageSource("create.fan_lava").setScalesWithDifficulty() - .setIsFire(); + .setIsFire(); public final IAirCurrentSource source; public AABB bounds = new AABB(0, 0, 0, 0, 0, 0); @@ -59,7 +62,7 @@ public class AirCurrent { public float maxDistance; protected List> affectedItemHandlers = - new ArrayList<>(); + new ArrayList<>(); protected List caughtEntities = new ArrayList<>(); static boolean isClientPlayerInAirCurrent; @@ -76,8 +79,8 @@ public class AirCurrent { if (world != null && world.isClientSide) { float offset = pushing ? 0.5f : maxDistance + .5f; Vec3 pos = VecHelper.getCenterOf(source.getAirCurrentPos()) - .add(Vec3.atLowerCornerOf(facing.getNormal()) - .scale(offset)); + .add(Vec3.atLowerCornerOf(facing.getNormal()) + .scale(offset)); if (world.random.nextFloat() < AllConfigs.CLIENT.fanParticleDensity.get()) world.addParticle(new AirFlowParticleData(source.getAirCurrentPos()), pos.x, pos.y, pos.z, 0, 0, 0); } @@ -87,7 +90,7 @@ public class AirCurrent { } protected void tickAffectedEntities(Level world, Direction facing) { - for (Iterator iterator = caughtEntities.iterator(); iterator.hasNext();) { + for (Iterator iterator = caughtEntities.iterator(); iterator.hasNext(); ) { Entity entity = iterator.next(); if (!entity.isAlive() || !entity.getBoundingBox().intersects(bounds) || isPlayerCreativeFlying(entity)) { iterator.remove(); @@ -100,22 +103,22 @@ public class AirCurrent { float sneakModifier = entity.isShiftKeyDown() ? 4096f : 512f; float speed = Math.abs(source.getSpeed()); double entityDistance = entity.position() - .distanceTo(center); + .distanceTo(center); float acceleration = (float) (speed / sneakModifier / (entityDistance / maxDistance)); Vec3 previousMotion = entity.getDeltaMovement(); float maxAcceleration = 5; double xIn = - Mth.clamp(flow.getX() * acceleration - previousMotion.x, -maxAcceleration, maxAcceleration); + Mth.clamp(flow.getX() * acceleration - previousMotion.x, -maxAcceleration, maxAcceleration); double yIn = - Mth.clamp(flow.getY() * acceleration - previousMotion.y, -maxAcceleration, maxAcceleration); + Mth.clamp(flow.getY() * acceleration - previousMotion.y, -maxAcceleration, maxAcceleration); double zIn = - Mth.clamp(flow.getZ() * acceleration - previousMotion.z, -maxAcceleration, maxAcceleration); + Mth.clamp(flow.getZ() * acceleration - previousMotion.z, -maxAcceleration, maxAcceleration); entity.setDeltaMovement(previousMotion.add(new Vec3(xIn, yIn, zIn).scale(1 / 8f))); entity.fallDistance = 0; DistExecutor.unsafeRunWhenOn(Dist.CLIENT, - () -> () -> enableClientPlayerSound(entity, Mth.clamp(speed / 128f * .4f, 0.01f, .4f))); + () -> () -> enableClientPlayerSound(entity, Mth.clamp(speed / 128f * .4f, 0.01f, .4f))); if (entity instanceof ServerPlayer) ((ServerPlayer) entity).connection.aboveGroundTickCount = 0; @@ -124,7 +127,7 @@ public class AirCurrent { InWorldProcessing.Type processingType = getSegmentAt((float) entityDistance); if (entity instanceof ServerPlayer) AllTriggers.triggerFor(AllTriggers.FAN_PROCESSING.constructTriggerFor(processingType), - (Player) entity); + (Player) entity); if (processingType == null || processingType == Type.NONE) { continue; @@ -144,31 +147,40 @@ public class AirCurrent { 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 SPLASHING: - if (entity instanceof EnderMan || entity.getType() == EntityType.SNOW_GOLEM - || entity.getType() == EntityType.BLAZE) { - entity.hurt(DamageSource.DROWN, 2); - } - if (!entity.isOnFire()) + 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 SOUL_SMOKING: //TODO maybe I should use new damage source instead of the regular smoke one? + if (entity instanceof LivingEntity livingEntity) { + livingEntity.addEffect(new MobEffectInstance(MobEffects.GLOWING, 400)); + } + if (!entity.fireImmune()) { + entity.setSecondsOnFire(10); + entity.hurt(damageSourceFire, 4); + } + 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; - 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; } } @@ -231,7 +243,7 @@ public class AirCurrent { bounds = new AABB(start.relative(direction)).expandTowards(scale); else { bounds = new AABB(start.relative(direction)).contract(scale.x, scale.y, scale.z) - .move(scale); + .move(scale); } } findAffectedHandlers(); @@ -243,15 +255,16 @@ public class AirCurrent { // 4 Rays test for holes in the shapes blocking the flow float offsetDistance = .25f; - Vec3[] offsets = new Vec3[] { planeVec.multiply(offsetDistance, offsetDistance, offsetDistance), - planeVec.multiply(-offsetDistance, -offsetDistance, offsetDistance), - planeVec.multiply(offsetDistance, -offsetDistance, -offsetDistance), - planeVec.multiply(-offsetDistance, offsetDistance, -offsetDistance), }; + Vec3[] offsets = new Vec3[]{planeVec.multiply(offsetDistance, offsetDistance, offsetDistance), + planeVec.multiply(-offsetDistance, -offsetDistance, offsetDistance), + planeVec.multiply(offsetDistance, -offsetDistance, -offsetDistance), + planeVec.multiply(-offsetDistance, offsetDistance, -offsetDistance),}; float limitedDistance = 0; // Determine the distance of the air flow - Outer: for (int i = 1; i <= max; i++) { + Outer: + for (int i = 1; i <= max; i++) { BlockPos currentPos = start.relative(facing, i); if (!world.isLoaded(currentPos)) break; @@ -268,16 +281,16 @@ public class AirCurrent { for (Vec3 offset : offsets) { Vec3 rayStart = VecHelper.getCenterOf(currentPos) - .subtract(directionVec.scale(.5f + 1 / 32f)) - .add(offset); + .subtract(directionVec.scale(.5f + 1 / 32f)) + .add(offset); Vec3 rayEnd = rayStart.add(directionVec.scale(1 + 1 / 32f)); BlockHitResult blockraytraceresult = - world.clipWithInteractionOverride(rayStart, rayEnd, currentPos, voxelshape, state); + world.clipWithInteractionOverride(rayStart, rayEnd, currentPos, voxelshape, state); if (blockraytraceresult == null) continue Outer; double distance = i - 1 + blockraytraceresult.getLocation() - .distanceTo(rayStart); + .distanceTo(rayStart); if (limitedDistance < distance) limitedDistance = (float) distance; } @@ -291,7 +304,7 @@ public class AirCurrent { public void findEntities() { caughtEntities.clear(); caughtEntities = source.getAirCurrentWorld() - .getEntities(null, bounds); + .getEntities(null, bounds); } public void findAffectedHandlers() { @@ -305,13 +318,13 @@ public class AirCurrent { for (int offset : Iterate.zeroAndOne) { BlockPos pos = start.relative(direction, i) - .below(offset); + .below(offset); TransportedItemStackHandlerBehaviour behaviour = - TileEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE); + TileEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE); if (behaviour != null) affectedItemHandlers.add(Pair.of(behaviour, type)); if (direction.getAxis() - .isVertical()) + .isVertical()) break; } } @@ -325,7 +338,7 @@ public class AirCurrent { handler.handleProcessingOnAllItems((transported) -> { InWorldProcessing.spawnParticlesForProcessing(world, handler.getWorldPositionOf(transported), - processingType); + processingType); if (world.isClientSide) return TransportedResult.doNothing(); return InWorldProcessing.applyProcessing(transported, world, processingType); @@ -360,19 +373,19 @@ public class AirCurrent { @OnlyIn(Dist.CLIENT) private static void enableClientPlayerSound(Entity e, float maxVolume) { if (e != Minecraft.getInstance() - .getCameraEntity()) + .getCameraEntity()) return; isClientPlayerInAirCurrent = true; float pitch = (float) Mth.clamp(e.getDeltaMovement() - .length() * .5f, .5f, 2f); + .length() * .5f, .5f, 2f); if (flyingSound == null || flyingSound.isStopped()) { flyingSound = new AirCurrentSound(SoundEvents.ELYTRA_FLYING, pitch); Minecraft.getInstance() - .getSoundManager() - .play(flyingSound); + .getSoundManager() + .play(flyingSound); } flyingSound.setPitch(pitch); flyingSound.fadeIn(maxVolume); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/SoulSmokingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/SoulSmokingRecipe.java new file mode 100644 index 000000000..e53566471 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/SoulSmokingRecipe.java @@ -0,0 +1,38 @@ +package com.simibubi.create.content.contraptions.components.fan; + +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing.SplashingWrapper; +import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; +import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; + +import net.minecraft.world.level.Level; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +public class SoulSmokingRecipe extends ProcessingRecipe { + + public SoulSmokingRecipe(ProcessingRecipeParams params) { + super(AllRecipeTypes.SOUL_SMOKING, params); + } + + @Override + public boolean matches(InWorldProcessing.SoulSmokingWrapper inv, Level worldIn) { + if (inv.isEmpty()) + return false; + return ingredients.get(0) + .test(inv.getItem(0)); + } + + @Override + protected int getMaxInputCount() { + return 1; + } + + @Override + protected int getMaxOutputCount() { + return 12; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java b/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java index 10245683b..bd2c403f4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java @@ -1,7 +1,5 @@ package com.simibubi.create.content.contraptions.particle; -import javax.annotation.Nonnull; - import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.components.fan.IAirCurrentSource; import com.simibubi.create.content.contraptions.processing.InWorldProcessing; @@ -9,11 +7,7 @@ import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.particle.ParticleRenderType; -import net.minecraft.client.particle.SimpleAnimatedParticle; -import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.particle.*; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.BlockParticleOption; @@ -23,6 +17,8 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.phys.Vec3; +import javax.annotation.Nonnull; + public class AirFlowParticle extends SimpleAnimatedParticle { private final IAirCurrentSource source; @@ -97,7 +93,7 @@ public class AirFlowParticle extends SimpleAnimatedParticle { } public void morphType(double distance) { - if(source.getAirCurrent() == null) + if (source.getAirCurrent() == null) return; InWorldProcessing.Type type = source.getAirCurrent().getSegmentAt((float) distance); @@ -125,6 +121,18 @@ public class AirFlowParticle extends SimpleAnimatedParticle { zd * .125f); } + if (type == InWorldProcessing.Type.SOUL_SMOKING) {//TODO soul smoking special particle? + setColor(Color.mixColors(0x0, 0x555555, level.random.nextFloat())); + setAlpha(1f); + selectSprite(level.random.nextInt(3)); + if (level.random.nextFloat() < 1 / 32f) + level.addParticle(ParticleTypes.SMOKE, x, y, z, xd * .125f, yd * .125f, + zd * .125f); + if (level.random.nextFloat() < 1 / 32f) + level.addParticle(ParticleTypes.LARGE_SMOKE, x, y, z, xd * .125f, yd * .125f, + zd * .125f); + } + if (type == InWorldProcessing.Type.BLASTING) { setColor(Color.mixColors(0xFF4400, 0xFF8855, level.random.nextFloat())); setAlpha(.5f); @@ -165,7 +173,7 @@ public class AirFlowParticle extends SimpleAnimatedParticle { } public Particle createParticle(AirFlowParticleData data, ClientLevel worldIn, double x, double y, double z, - double xSpeed, double ySpeed, double zSpeed) { + double xSpeed, double ySpeed, double zSpeed) { BlockEntity te = worldIn.getBlockEntity(new BlockPos(data.posX, data.posY, data.posZ)); if (!(te instanceof IAirCurrentSource)) te = null; 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 c865d406a..a6fa7594a 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,17 +1,9 @@ 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 javax.annotation.Nullable; - import com.mojang.math.Vector3f; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.contraptions.components.fan.SoulSmokingRecipe; import com.simibubi.create.content.contraptions.components.fan.SplashingRecipe; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; @@ -27,11 +19,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.tags.BlockTags; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; -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.item.crafting.*; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; @@ -45,15 +33,23 @@ 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 SplashingWrapper SPLASHING_WRAPPER = new SplashingWrapper(); + private static final SoulSmokingWrapper SOUL_SMOKING_WRAPPER = new SoulSmokingWrapper(); public enum Type { - SMOKING, BLASTING, SPLASHING, NONE - - ; + SMOKING, BLASTING, SPLASHING, SOUL_SMOKING, NONE; public static Type byBlock(BlockGetter reader, BlockPos pos) { BlockState blockState = reader.getBlockState(pos); @@ -61,10 +57,12 @@ public class InWorldProcessing { 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.SOUL_SMOKING; if (block == Blocks.FIRE || AllBlocks.LIT_BLAZE_BURNER.has(blockState) - || (BlockTags.CAMPFIRES.contains(block) && blockState.getOptionalValue(CampfireBlock.LIT) + || (BlockTags.CAMPFIRES.contains(block) && blockState.getOptionalValue(CampfireBlock.LIT) .orElse(false)) - || getHeatLevelOf(blockState) == BlazeBurnerBlock.HeatLevel.SMOULDERING) + || getHeatLevelOf(blockState) == BlazeBurnerBlock.HeatLevel.SMOULDERING) return Type.SMOKING; if (block == Blocks.LAVA || getHeatLevelOf(blockState).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING)) return Type.BLASTING; @@ -74,9 +72,9 @@ public class InWorldProcessing { public static boolean canProcess(ItemEntity entity, Type type) { if (entity.getPersistentData() - .contains("CreateData")) { + .contains("CreateData")) { CompoundTag compound = entity.getPersistentData() - .getCompound("CreateData"); + .getCompound("CreateData"); if (compound.contains("Processing")) { CompoundTag processing = compound.getCompound("Processing"); @@ -99,32 +97,35 @@ public class InWorldProcessing { if (type == Type.BLASTING) { WRAPPER.setItem(0, stack); Optional smeltingRecipe = world.getRecipeManager() - .getRecipeFor(RecipeType.SMELTING, WRAPPER, world); + .getRecipeFor(RecipeType.SMELTING, WRAPPER, world); if (smeltingRecipe.isPresent()) return true; WRAPPER.setItem(0, stack); Optional blastingRecipe = world.getRecipeManager() - .getRecipeFor(RecipeType.BLASTING, WRAPPER, world); + .getRecipeFor(RecipeType.BLASTING, WRAPPER, world); if (blastingRecipe.isPresent()) return true; return !stack.getItem() - .isFireResistant(); + .isFireResistant(); } if (type == Type.SMOKING) { WRAPPER.setItem(0, stack); Optional recipe = world.getRecipeManager() - .getRecipeFor(RecipeType.SMOKING, WRAPPER, world); + .getRecipeFor(RecipeType.SMOKING, WRAPPER, world); return recipe.isPresent(); } if (type == Type.SPLASHING) return isWashable(stack, world); + if (type == Type.SOUL_SMOKING) + return isSoulSmokeable(stack, world); + return false; } @@ -134,6 +135,12 @@ public class InWorldProcessing { return recipe.isPresent(); } + public static boolean isSoulSmokeable(ItemStack stack, Level world) { + SOUL_SMOKING_WRAPPER.setItem(0, stack); + Optional recipe = AllRecipeTypes.SOUL_SMOKING.find(SOUL_SMOKING_WRAPPER, world); + return recipe.isPresent(); + } + public static void applyProcessing(ItemEntity entity, Type type) { if (decrementProcessingTime(entity, type) != 0) return; @@ -158,7 +165,7 @@ public class InWorldProcessing { transported.processedBy = type; int timeModifierForStackSize = ((transported.stack.getCount() - 1) / 16) + 1; int processingTime = - (int) (AllConfigs.SERVER.kinetics.inWorldProcessingTime.get() * timeModifierForStackSize) + 1; + (int) (AllConfigs.SERVER.kinetics.inWorldProcessingTime.get() * timeModifierForStackSize) + 1; transported.processingTime = processingTime; if (!canProcess(transported.stack, type, world)) transported.processingTime = -1; @@ -190,23 +197,30 @@ public class InWorldProcessing { return applyRecipeOn(stack, recipe.get()); return null; } + if (type == Type.SOUL_SMOKING){ + SOUL_SMOKING_WRAPPER.setItem(0, stack); + Optional recipe = AllRecipeTypes.SOUL_SMOKING.find(SOUL_SMOKING_WRAPPER, world); + if (recipe.isPresent()) + return applyRecipeOn(stack, recipe.get()); + return null; + } WRAPPER.setItem(0, stack); Optional smokingRecipe = world.getRecipeManager() - .getRecipeFor(RecipeType.SMOKING, WRAPPER, world); + .getRecipeFor(RecipeType.SMOKING, WRAPPER, world); if (type == Type.BLASTING) { if (!smokingRecipe.isPresent()) { WRAPPER.setItem(0, stack); Optional smeltingRecipe = world.getRecipeManager() - .getRecipeFor(RecipeType.SMELTING, WRAPPER, world); + .getRecipeFor(RecipeType.SMELTING, WRAPPER, world); if (smeltingRecipe.isPresent()) return applyRecipeOn(stack, smeltingRecipe.get()); WRAPPER.setItem(0, stack); Optional blastingRecipe = world.getRecipeManager() - .getRecipeFor(RecipeType.BLASTING, WRAPPER, world); + .getRecipeFor(RecipeType.BLASTING, WRAPPER, world); if (blastingRecipe.isPresent()) return applyRecipeOn(stack, blastingRecipe.get()); @@ -235,9 +249,9 @@ public class InWorldProcessing { if (!processing.contains("Type") || Type.valueOf(processing.getString("Type")) != type) { processing.putString("Type", type.name()); int timeModifierForStackSize = ((entity.getItem() - .getCount() - 1) / 16) + 1; + .getCount() - 1) / 16) + 1; int processingTime = - (int) (AllConfigs.SERVER.kinetics.inWorldProcessingTime.get() * timeModifierForStackSize) + 1; + (int) (AllConfigs.SERVER.kinetics.inWorldProcessingTime.get() * timeModifierForStackSize) + 1; processing.putInt("Time", processingTime); } @@ -276,7 +290,7 @@ public class InWorldProcessing { if (!ItemHandlerHelper.canItemStacksStack(stack, previouslyRolled)) continue; int amount = Math.min(previouslyRolled.getMaxStackSize() - previouslyRolled.getCount(), - stack.getCount()); + stack.getCount()); previouslyRolled.grow(amount); stack.shrink(amount); } @@ -289,7 +303,7 @@ public class InWorldProcessing { } } else { ItemStack out = recipe.getResultItem() - .copy(); + .copy(); stacks = ItemHelper.multipliedOutput(stackIn, out); } @@ -303,21 +317,22 @@ public class InWorldProcessing { return; 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 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; + case BLASTING: + world.addParticle(ParticleTypes.LARGE_SMOKE, vec.x, vec.y + .25f, vec.z, 0, 1 / 16f, 0); + break; + case SMOKING: + case SOUL_SMOKING: // TODO add special soul smoking particle + world.addParticle(ParticleTypes.POOF, vec.x, vec.y + .25f, vec.z, 0, 1 / 16f, 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; } } @@ -327,4 +342,10 @@ public class InWorldProcessing { } } + public static class SoulSmokingWrapper extends RecipeWrapper { + public SoulSmokingWrapper() { + super(new ItemStackHandler(1)); + } + } + } diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java index 3dbec49a9..eca03b2b7 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java @@ -38,6 +38,7 @@ public abstract class ProcessingRecipeGen extends CreateRecipeProvider { GENERATORS.add(new PressingRecipeGen(gen)); GENERATORS.add(new FillingRecipeGen(gen)); GENERATORS.add(new EmptyingRecipeGen(gen)); + GENERATORS.add(new SoulSmokingRecipeGen(gen)); gen.addProvider(new DataProvider() { diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/SoulSmokingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/SoulSmokingRecipeGen.java new file mode 100644 index 000000000..739b54030 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/SoulSmokingRecipeGen.java @@ -0,0 +1,48 @@ +package com.simibubi.create.foundation.data.recipe; + +import com.simibubi.create.AllItems; +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.components.fan.SoulSmokingRecipe; +import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; +import com.simibubi.create.content.contraptions.processing.ProcessingRecipeSerializer; + +import net.minecraft.data.DataGenerator; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; + +public class SoulSmokingRecipeGen extends ProcessingRecipeGen { + + GeneratedRecipe + + SOUL_SAND = convert(Blocks.SOUL_SAND, Blocks.SAND, Blocks.RED_SAND), + SOUL_DIRT = convert(Blocks.SOUL_SOIL, Blocks.DIRT, Blocks.COARSE_DIRT, Blocks.ROOTED_DIRT), + BLACK_STONE = convert(Blocks.BLACKSTONE, Blocks.COBBLESTONE), + CRIMSON_FUNGUS = convert(Items.CRIMSON_FUNGUS, Items.RED_MUSHROOM), + WARPED_FUNGUS = convert(Items.WARPED_FUNGUS, Items.BROWN_MUSHROOM), + CRIMSON_NYLIUM = convert(Blocks.CRIMSON_NYLIUM, Blocks.MYCELIUM), + WARPED_NYLIUM = convert(Blocks.WARPED_NYLIUM, Blocks.PODZOL); + + public GeneratedRecipe convert(ItemLike result, ItemLike... input) { + ProcessingRecipeSerializer serializer = getSerializer(); + GeneratedRecipe generatedRecipe = c -> new ProcessingRecipeBuilder<>(serializer.getFactory(), + new ResourceLocation(Create.ID, result.asItem().getRegistryName().getPath())) + .withItemIngredients(Ingredient.of(input)).output(result).build(c); + all.add(generatedRecipe); + return generatedRecipe; + } + + public SoulSmokingRecipeGen(DataGenerator p_i48262_1_) { + super(p_i48262_1_); + } + + @Override + protected AllRecipeTypes getRecipeType() { + return AllRecipeTypes.SOUL_SMOKING; + } + +} diff --git a/src/main/resources/assets/create/lang/default/interface.json b/src/main/resources/assets/create/lang/default/interface.json index 4f2885b3d..46b88fe9e 100644 --- a/src/main/resources/assets/create/lang/default/interface.json +++ b/src/main/resources/assets/create/lang/default/interface.json @@ -34,6 +34,8 @@ "create.recipe.fan_washing.fan": "Fan behind Flowing Water", "create.recipe.fan_smoking": "Bulk Smoking", "create.recipe.fan_smoking.fan": "Fan behind Fire", + "create.recipe.fan_soul_smoking": "Bulk Soul Smoking", + "create.recipe.fan_soul_smoking.fan": "Fan behind Soul Fire", "create.recipe.fan_blasting": "Bulk Blasting", "create.recipe.fan_blasting.fan": "Fan behind Lava", "create.recipe.pressing": "Pressing", @@ -106,7 +108,7 @@ "create.gui.toolmenu.focusKey": "Hold [%1$s] to Focus", "create.gui.toolmenu.cycle": "[SCROLL] to Cycle", - + "create.toolbox.unequip": "Unequip: %1$s", "create.toolbox.outOfRange": "Toolbox of held item not in Range", "create.toolbox.detach": "Stop tracking and keep item", @@ -508,7 +510,7 @@ "create.tooltip.chute.fans_pull_up": "Fans pull from Above", "create.tooltip.chute.fans_pull_down": "Fans pull from Below", "create.tooltip.chute.contains": "Contains: %1$s x%2$s", - + "create.tooltip.brass_tunnel.contains": "Currently distributing:", "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", "create.tooltip.brass_tunnel.retrieve": "Right-Click to retrieve",