diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/ShapedEnergyTransferRecipe.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/ShapedEnergyTransferRecipe.java index 56a45edac5..951d2e8ae9 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/ShapedEnergyTransferRecipe.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/ShapedEnergyTransferRecipe.java @@ -135,7 +135,7 @@ public void toNetwork(FriendlyByteBuf buffer, ShapedEnergyTransferRecipe recipe) for (Ingredient ingredient : recipe.getIngredients()) { ingredient.toNetwork(buffer); } - buffer.writeItem(((ShapedRecipeAccessor) this).getResult()); + buffer.writeItem(((ShapedRecipeAccessor) recipe).getResult()); } } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/ShapedFluidContainerRecipe.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/ShapedFluidContainerRecipe.java new file mode 100644 index 0000000000..6ebeac1570 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/ShapedFluidContainerRecipe.java @@ -0,0 +1,161 @@ +package com.gregtechceu.gtceu.api.recipe; + +import com.gregtechceu.gtceu.api.recipe.ingredient.FluidContainerIngredient; +import com.gregtechceu.gtceu.core.mixins.ShapedRecipeAccessor; + +import net.minecraft.core.NonNullList; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.inventory.CraftingContainer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.CraftingBookCategory; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.ShapedRecipe; + +import com.google.gson.JsonObject; +import com.mojang.datafixers.util.Pair; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +// TODO shapeless fluid container recipes +public class ShapedFluidContainerRecipe extends ShapedRecipe { + + public static final RecipeSerializer SERIALIZER = new Serializer(); + + public ShapedFluidContainerRecipe(ResourceLocation id, String group, CraftingBookCategory category, + int width, int height, + NonNullList recipeItems, ItemStack result, + boolean showNotification) { + super(id, group, category, width, height, recipeItems, result, showNotification); + } + + public ShapedFluidContainerRecipe(ResourceLocation id, String group, CraftingBookCategory category, + int width, int height, + NonNullList recipeItems, ItemStack result) { + this(id, group, category, width, height, recipeItems, result, true); + } + + @Override + public @NotNull NonNullList getRemainingItems(@NotNull CraftingContainer inv) { + NonNullList items = NonNullList.withSize(inv.getContainerSize(), ItemStack.EMPTY); + + // figure out all the fluid container ingredients' remainders. + int replacedSlot = -1; + OUTER_LOOP: + for (int x = 0; x <= inv.getWidth() - this.getWidth(); ++x) { + for (int y = 0; y <= inv.getHeight() - this.getHeight(); ++y) { + var stack = this.findFluidReplacement(inv, x, y, false); + if (stack.getFirst() != -1) { + items.set(stack.getFirst(), stack.getSecond()); + replacedSlot = stack.getFirst(); + break OUTER_LOOP; + } + + stack = this.findFluidReplacement(inv, x, y, true); + if (stack.getFirst() != -1) { + items.set(stack.getFirst(), stack.getSecond()); + replacedSlot = stack.getFirst(); + break OUTER_LOOP; + } + } + } + + for (int i = 0; i < items.size(); ++i) { + if (i == replacedSlot) { + continue; + } + ItemStack item = inv.getItem(i); + if (item.hasCraftingRemainingItem()) { + items.set(i, item.getCraftingRemainingItem()); + } + } + + return items; + } + + /** + * Checks if the region of a crafting inventory is match for the recipe. + */ + private Pair findFluidReplacement(CraftingContainer inv, int width, int height, + boolean mirrored) { + for (int x = 0; x < inv.getWidth(); ++x) { + for (int y = 0; y < inv.getHeight(); ++y) { + int offsetX = x - width; + int offsetY = y - height; + Ingredient ingredient = Ingredient.EMPTY; + if (offsetX >= 0 && offsetY >= 0 && offsetX < this.getWidth() && offsetY < this.getHeight()) { + if (mirrored) { + ingredient = this.getIngredients() + .get(this.getWidth() - offsetX - 1 + offsetY * this.getWidth()); + } else { + ingredient = this.getIngredients().get(offsetX + offsetY * this.getWidth()); + } + } + + if (ingredient instanceof FluidContainerIngredient fluidContainerIngredient) { + int slot = x + y * inv.getWidth(); + ItemStack stack = inv.getItem(slot); + if (fluidContainerIngredient.test(stack)) { + return Pair.of(slot, fluidContainerIngredient.getExtractedStack(stack)); + } + } + } + } + + return Pair.of(-1, ItemStack.EMPTY); + } + + public static class Serializer implements RecipeSerializer { + + @Override + public ShapedFluidContainerRecipe fromJson(ResourceLocation recipeId, JsonObject json) { + String group = GsonHelper.getAsString(json, "group", ""); + CraftingBookCategory category = CraftingBookCategory.CODEC + .byName(GsonHelper.getAsString(json, "category", null), CraftingBookCategory.MISC); + Map key = ShapedRecipeAccessor.callKeyFromJson(GsonHelper.getAsJsonObject(json, "key")); + String[] pattern = ShapedRecipeAccessor + .callShrink(ShapedRecipeAccessor.callPatternFromJson(GsonHelper.getAsJsonArray(json, "pattern"))); + int xSize = pattern[0].length(); + int ySize = pattern.length; + NonNullList dissolved = ShapedRecipeAccessor.callDissolvePattern(pattern, key, xSize, ySize); + ItemStack result = ShapedEnergyTransferRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, "result")); + boolean showNotification = GsonHelper.getAsBoolean(json, "show_notification", true); + return new ShapedFluidContainerRecipe(recipeId, group, category, + xSize, ySize, + dissolved, result, + showNotification); + } + + @Override + public ShapedFluidContainerRecipe fromNetwork(ResourceLocation recipeId, FriendlyByteBuf buffer) { + int xSize = buffer.readVarInt(); + int ySize = buffer.readVarInt(); + CraftingBookCategory category = buffer.readEnum(CraftingBookCategory.class); + String group = buffer.readUtf(); + NonNullList ingredients = NonNullList.withSize(xSize * ySize, Ingredient.EMPTY); + ingredients.replaceAll($ -> Ingredient.fromNetwork(buffer)); + ItemStack result = buffer.readItem(); + boolean showNotification = buffer.readBoolean(); + return new ShapedFluidContainerRecipe(recipeId, group, category, + xSize, ySize, + ingredients, result, + showNotification); + } + + @Override + public void toNetwork(FriendlyByteBuf buffer, ShapedFluidContainerRecipe recipe) { + buffer.writeVarInt(recipe.getWidth()); + buffer.writeVarInt(recipe.getHeight()); + buffer.writeEnum(recipe.category()); + buffer.writeUtf(recipe.getGroup()); + for (Ingredient ingredient : recipe.getIngredients()) { + ingredient.toNetwork(buffer); + } + buffer.writeItem(((ShapedRecipeAccessor) recipe).getResult()); + buffer.writeBoolean(recipe.showNotification()); + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/ingredient/FluidContainerIngredient.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/ingredient/FluidContainerIngredient.java new file mode 100644 index 0000000000..d7f94a70a3 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/ingredient/FluidContainerIngredient.java @@ -0,0 +1,146 @@ +package com.gregtechceu.gtceu.api.recipe.ingredient; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.data.tag.TagUtil; +import com.gregtechceu.gtceu.utils.InfiniteFluidTransfer; + +import com.lowdragmc.lowdraglib.side.fluid.*; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.material.Fluid; +import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.common.crafting.IIngredientSerializer; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.serialization.Codec; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.stream.Stream; + +import javax.annotation.Nonnull; + +public class FluidContainerIngredient extends Ingredient { + + public static final ResourceLocation TYPE = GTCEu.id("fluid_container"); + + public static final Codec CODEC = FluidIngredient.CODEC.xmap( + FluidContainerIngredient::new, FluidContainerIngredient::getFluid); + + @Getter + private final FluidIngredient fluid; + + public FluidContainerIngredient(FluidIngredient fluid) { + super(Stream.empty()); + this.fluid = fluid; + } + + public FluidContainerIngredient(FluidStack fluidStack) { + this(FluidIngredient.of(TagUtil.createFluidTag(BuiltInRegistries.FLUID.getKey(fluidStack.getFluid()).getPath()), + fluidStack.getAmount())); + } + + public FluidContainerIngredient(TagKey tag, int amount) { + this(FluidIngredient.of(tag, amount, null)); + } + + private ItemStack[] cachedStacks; + + @Nonnull + @Override + public ItemStack[] getItems() { + if (cachedStacks == null) + cachedStacks = Arrays.stream(this.fluid.getStacks()) + .map(stack -> stack.getFluid().getBucket().getDefaultInstance()) + .filter(s -> !s.isEmpty()) + .toArray(ItemStack[]::new); + return this.cachedStacks; + } + + @Override + public JsonElement toJson() { + JsonObject json = new JsonObject(); + json.addProperty("type", TYPE.toString()); + json.add("fluid", fluid.toJson()); + return json; + } + + @Override + public boolean isEmpty() { + return this.fluid.isEmpty(); + } + + @Override + public boolean test(@Nullable ItemStack stack) { + if (stack == null || stack.isEmpty()) + return false; + IFluidTransfer transfer = FluidTransferHelper.getFluidTransfer(stack); + return transfer != null && this.extractFrom(transfer, true); + } + + @Override + public boolean isSimple() { + return false; + } + + public ItemStack getExtractedStack(ItemStack input) { + FluidActionResult result = FluidTransferHelper.tryEmptyContainer(input, + new InfiniteFluidTransfer(1), + (int) this.fluid.getAmount(), + ForgeHooks.getCraftingPlayer(), + true); + if (result.success) { + return result.result; + } + return input; + } + + public boolean extractFrom(IFluidTransfer handler, boolean simulate) { + for (int tank = 0; tank < handler.getTanks(); tank++) { + FluidStack inTank = handler.getFluidInTank(tank); + if (fluid.test(inTank)) { + FluidStack toExtract = inTank.copy(fluid.getAmount()); + FluidStack extractedSim = handler.drain(toExtract, true); + if (extractedSim.getAmount() >= fluid.getAmount()) { + if (!simulate) + handler.drain(toExtract, false); + return true; + } + } + } + return false; + } + + public static FluidContainerIngredient fromJson(JsonObject json) { + return SERIALIZER.parse(json); + } + + public static final IIngredientSerializer SERIALIZER = new IIngredientSerializer<>() { + + @Override + public @NotNull FluidContainerIngredient parse(FriendlyByteBuf buffer) { + FluidIngredient fluid = FluidIngredient.fromNetwork(buffer); + return new FluidContainerIngredient(fluid); + } + + @Override + public @NotNull FluidContainerIngredient parse(JsonObject json) { + FluidIngredient fluid = FluidIngredient.fromJson(GsonHelper.getAsJsonObject(json, "fluid")); + return new FluidContainerIngredient(fluid); + } + + @Override + public void write(FriendlyByteBuf buffer, FluidContainerIngredient ingredient) { + ingredient.fluid.toNetwork(buffer); + } + }; +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java b/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java index 00355d94e1..3395a93b96 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java +++ b/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java @@ -20,6 +20,7 @@ import com.gregtechceu.gtceu.api.gui.factory.GTUIEditorFactory; import com.gregtechceu.gtceu.api.gui.factory.MachineUIFactory; import com.gregtechceu.gtceu.api.recipe.chance.logic.ChanceLogic; +import com.gregtechceu.gtceu.api.recipe.ingredient.FluidContainerIngredient; import com.gregtechceu.gtceu.api.recipe.ingredient.IntCircuitIngredient; import com.gregtechceu.gtceu.api.recipe.ingredient.IntProviderIngredient; import com.gregtechceu.gtceu.api.recipe.ingredient.SizedIngredient; @@ -53,6 +54,7 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.repository.Pack; +import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; import net.minecraftforge.common.crafting.CraftingHelper; import net.minecraftforge.event.AddPackFindersEvent; @@ -78,6 +80,8 @@ public class CommonProxy { public CommonProxy() { + ForgeMod.enableMilkFluid(); + // used for forge events (ClientProxy + CommonProxy) IEventBus eventBus = FMLJavaModLoadingContext.get().getModEventBus(); eventBus.register(this); @@ -229,6 +233,7 @@ public void commonSetup(FMLCommonSetupEvent event) { CraftingHelper.register(SizedIngredient.TYPE, SizedIngredient.SERIALIZER); CraftingHelper.register(IntCircuitIngredient.TYPE, IntCircuitIngredient.SERIALIZER); CraftingHelper.register(IntProviderIngredient.TYPE, IntProviderIngredient.SERIALIZER); + CraftingHelper.register(FluidContainerIngredient.TYPE, FluidContainerIngredient.SERIALIZER); }); } diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTFluids.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTFluids.java index 1bb842323b..54d91888ec 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTFluids.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTFluids.java @@ -9,6 +9,7 @@ import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.Fluids; +import net.minecraftforge.common.ForgeMod; import org.jetbrains.annotations.NotNull; @@ -24,6 +25,7 @@ public class GTFluids { public static void init() { handleNonMaterialFluids(GTMaterials.Water, Fluids.WATER); handleNonMaterialFluids(GTMaterials.Lava, Fluids.LAVA); + handleNonMaterialFluids(GTMaterials.Milk, ForgeMod.MILK.get()); REGISTRATE.creativeModeTab(() -> GTCreativeModeTabs.MATERIAL_FLUID); // register fluids for materials for (MaterialRegistry registry : GTCEuAPI.materialManager.getRegistries()) { diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeTypes.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeTypes.java index 84f8f6eae1..d72b5d125a 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeTypes.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeTypes.java @@ -716,16 +716,18 @@ public static void init() { ModLoader.get().postEvent(new GTCEuAPI.RegisterEvent<>(GTRegistries.RECIPE_TYPES, GTRecipeType.class)); GTRegistries.RECIPE_TYPES.freeze(); - GTRegistries.register(BuiltInRegistries.RECIPE_SERIALIZER, GTCEu.id("gt_recipe_serializer"), + GTRegistries.register(BuiltInRegistries.RECIPE_SERIALIZER, GTCEu.id("machine"), GTRecipeSerializer.SERIALIZER); - GTRegistries.register(BuiltInRegistries.RECIPE_SERIALIZER, GTCEu.id("facade_cover_serializer"), + GTRegistries.register(BuiltInRegistries.RECIPE_SERIALIZER, GTCEu.id("crafting_facade_cover"), FacadeCoverRecipe.SERIALIZER); - GTRegistries.register(BuiltInRegistries.RECIPE_SERIALIZER, GTCEu.id("strict_shaped_recipe_serializer"), + GTRegistries.register(BuiltInRegistries.RECIPE_SERIALIZER, GTCEu.id("crafting_shaped_strict"), StrictShapedRecipe.SERIALIZER); - GTRegistries.register(BuiltInRegistries.RECIPE_SERIALIZER, GTCEu.id("shaped_energy_transfer_recipe_serializer"), + GTRegistries.register(BuiltInRegistries.RECIPE_SERIALIZER, GTCEu.id("crafting_shaped_energy_transfer"), ShapedEnergyTransferRecipe.SERIALIZER); - GTRegistries.register(BuiltInRegistries.RECIPE_SERIALIZER, GTCEu.id("tool_head_replace_recipe_serializer"), + GTRegistries.register(BuiltInRegistries.RECIPE_SERIALIZER, GTCEu.id("crafting_tool_head_replace"), ToolHeadReplaceRecipe.SERIALIZER); + GTRegistries.register(BuiltInRegistries.RECIPE_SERIALIZER, GTCEu.id("crafting_shaped_fluid_container"), + ShapedFluidContainerRecipe.SERIALIZER); } public static GTRecipeType get(String name) { diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/ShapedRecipeAccessor.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/ShapedRecipeAccessor.java index b26ca317a7..474fcf0c07 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/ShapedRecipeAccessor.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/ShapedRecipeAccessor.java @@ -23,23 +23,23 @@ public interface ShapedRecipeAccessor { @Invoker static Map callKeyFromJson(JsonObject keyEntry) { - return null; + throw new AssertionError(); } @Invoker static String[] callPatternFromJson(JsonArray patternArray) { - return null; + throw new AssertionError(); } @Invoker static NonNullList callDissolvePattern(String[] pattern, Map keys, int patternWidth, int patternHeight) { - return null; + throw new AssertionError(); } @Invoker static String[] callShrink(String... toShrink) { - return null; + throw new AssertionError(); } @Accessor diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/VanillaRecipeHelper.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/VanillaRecipeHelper.java index ffabd7110a..6694452f07 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/VanillaRecipeHelper.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/VanillaRecipeHelper.java @@ -377,6 +377,95 @@ public static void addShapedEnergyTransferRecipe(Consumer provid GTCEu.id(regName), chargeIngredient, result, recipe); } + public static void addShapedFluidContainerRecipe(Consumer provider, boolean withUnificationData, + boolean isStrict, + @NotNull ResourceLocation regName, @NotNull ItemStack result, + @NotNull Object... recipe) { + var builder = new ShapedFluidContainerRecipeBuilder(regName).output(result); + builder.isStrict(isStrict); + CharSet set = new CharOpenHashSet(); + for (int i = 0; i < recipe.length; i++) { + var o = recipe[i]; + if (o instanceof String pattern) { + builder.pattern(pattern); + for (Character c : ToolHelper.getToolSymbols()) { + if (pattern.indexOf(c) >= 0) { + set.add(c.charValue()); + } + } + } + if (o instanceof String[] pattern) { + for (String s : pattern) { + builder.pattern(s); + for (Character c : ToolHelper.getToolSymbols()) { + if (s.indexOf(c) >= 0) { + set.add(c.charValue()); + } + } + } + } + if (o instanceof Character sign) { + var content = recipe[i + 1]; + i++; + if (content instanceof Ingredient ingredient) { + builder.define(sign, ingredient); + } else if (content instanceof ItemStack itemStack) { + builder.define(sign, itemStack); + } else if (content instanceof TagKey key) { + builder.define(sign, (TagKey) key); + } else if (content instanceof TagPrefix prefix) { + if (prefix.getItemParentTags().length > 0) { + builder.define(sign, prefix.getItemParentTags()[0]); + } + } else if (content instanceof ItemLike itemLike) { + builder.define(sign, itemLike); + } else if (content instanceof UnificationEntry entry) { + TagKey tag = ChemicalHelper.getTag(entry.tagPrefix, entry.material); + if (tag != null) { + builder.define(sign, tag); + } else builder.define(sign, ChemicalHelper.get(entry.tagPrefix, entry.material)); + } else if (content instanceof ItemProviderEntry entry) { + builder.define(sign, entry.asStack()); + } + } + } + for (Character c : set) { + builder.define(c, ToolHelper.getToolFromSymbol(c).itemTags.get(0)); + } + + builder.save(provider); + + if (withUnificationData) { + ChemicalHelper.registerMaterialInfo(result.getItem(), getRecyclingIngredients(result.getCount(), recipe)); + } + } + + public static void addShapedFluidContainerRecipe(Consumer provider, boolean withUnificationData, + @NotNull String regName, @NotNull ItemStack result, + @NotNull Object... recipe) { + addShapedFluidContainerRecipe(provider, withUnificationData, GTCEu.id(regName), result, recipe); + } + + public static void addShapedFluidContainerRecipe(Consumer provider, boolean withUnificationData, + @NotNull ResourceLocation regName, @NotNull ItemStack result, + + @NotNull Object... recipe) { + addShapedFluidContainerRecipe(provider, withUnificationData, false, regName, result, recipe); + } + + public static void addShapedFluidContainerRecipe(Consumer provider, @NotNull String regName, + @NotNull ItemStack result, + @NotNull Object... recipe) { + addShapedFluidContainerRecipe(provider, GTCEu.id(regName), result, recipe); + } + + public static void addShapedFluidContainerRecipe(Consumer provider, + @NotNull ResourceLocation regName, + @NotNull ItemStack result, + @NotNull Object... recipe) { + addShapedFluidContainerRecipe(provider, false, regName, result, recipe); + } + /** * Adds a shapeless recipe which clears the nbt of the outputs * diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/ShapedFluidContainerRecipeBuilder.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/ShapedFluidContainerRecipeBuilder.java new file mode 100644 index 0000000000..f74f871570 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/ShapedFluidContainerRecipeBuilder.java @@ -0,0 +1,52 @@ +package com.gregtechceu.gtceu.data.recipe.builder; + +import com.gregtechceu.gtceu.api.recipe.ShapedFluidContainerRecipe; + +import net.minecraft.data.recipes.FinishedRecipe; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.crafting.RecipeSerializer; + +import com.google.gson.JsonObject; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Consumer; + +public class ShapedFluidContainerRecipeBuilder extends ShapedRecipeBuilder { + + public ShapedFluidContainerRecipeBuilder(@Nullable ResourceLocation id) { + super(id); + } + + public void save(Consumer consumer) { + consumer.accept(new FinishedRecipe() { + + @Override + public void serializeRecipeData(JsonObject pJson) { + toJson(pJson); + } + + @Override + public ResourceLocation getId() { + var ID = id == null ? defaultId() : id; + return new ResourceLocation(ID.getNamespace(), "shaped_fluid_container/" + ID.getPath()); + } + + @Override + public RecipeSerializer getType() { + return ShapedFluidContainerRecipe.SERIALIZER; + } + + @Nullable + @Override + public JsonObject serializeAdvancement() { + return null; + } + + @Nullable + @Override + public ResourceLocation getAdvancementId() { + return null; + } + }); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/configurable/RecipeAddition.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/configurable/RecipeAddition.java index 53d5071413..cd4dba1860 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/configurable/RecipeAddition.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/configurable/RecipeAddition.java @@ -5,6 +5,7 @@ import com.gregtechceu.gtceu.api.data.chemical.material.Material; import com.gregtechceu.gtceu.api.data.chemical.material.stack.UnificationEntry; import com.gregtechceu.gtceu.api.data.tag.TagPrefix; +import com.gregtechceu.gtceu.api.recipe.ingredient.FluidContainerIngredient; import com.gregtechceu.gtceu.common.data.*; import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.data.recipe.VanillaRecipeHelper; @@ -95,10 +96,11 @@ private static void disableManualCompression(Consumer provider) private static void harderBrickRecipes(Consumer provider) { if (ConfigHolder.INSTANCE.recipes.harderBrickRecipes) { - VanillaRecipeHelper.addShapedRecipe(provider, "brick_from_water", new ItemStack(Blocks.BRICKS, 2), "BBB", + VanillaRecipeHelper.addShapedFluidContainerRecipe(provider, "brick_from_water", + new ItemStack(Blocks.BRICKS, 2), "BBB", "BWB", "BBB", 'B', new ItemStack(Items.BRICK), - 'W', new ItemStack(Items.WATER_BUCKET)); + 'W', new FluidContainerIngredient(Water.getFluidTag(), 1000)); VanillaRecipeHelper.addShapedRecipe(provider, "bucket_of_concrete", new ItemStack(Concrete.getBucket()), "CBS", "CWQ", " L ", @@ -109,12 +111,12 @@ private static void harderBrickRecipes(Consumer provider) { 'L', new UnificationEntry(dust, Clay), 'B', new ItemStack(Items.BUCKET)); - VanillaRecipeHelper.addShapedRecipe(provider, "casing_primitive_bricks", + VanillaRecipeHelper.addShapedFluidContainerRecipe(provider, "casing_primitive_bricks", GTBlocks.CASING_PRIMITIVE_BRICKS.asStack(), "BGB", "BCB", "BGB", 'B', GTItems.FIRECLAY_BRICK.asStack(), 'G', new UnificationEntry(dust, Gypsum), - 'C', new ItemStack(Concrete.getBucket())); + 'C', new FluidContainerIngredient(Concrete.getFluidTag(), 1000)); VanillaRecipeHelper.addShapelessRecipe(provider, "compressed_clay", COMPRESSED_CLAY.asStack(), WOODEN_FORM_BRICK.asStack(), new ItemStack(Items.CLAY_BALL)); diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CraftingRecipeLoader.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CraftingRecipeLoader.java index c3e07eb44b..b70d6bf9e3 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CraftingRecipeLoader.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CraftingRecipeLoader.java @@ -3,6 +3,7 @@ import com.gregtechceu.gtceu.api.data.chemical.ChemicalHelper; import com.gregtechceu.gtceu.api.data.chemical.material.stack.UnificationEntry; import com.gregtechceu.gtceu.api.recipe.FacadeCoverRecipe; +import com.gregtechceu.gtceu.api.recipe.ingredient.FluidContainerIngredient; import com.gregtechceu.gtceu.common.data.GTBlocks; import com.gregtechceu.gtceu.common.data.GTItems; import com.gregtechceu.gtceu.data.recipe.CustomTags; @@ -94,8 +95,10 @@ public static void init(Consumer provider) { // Items.PAPER, 'R', new UnificationEntry(springSmall, Iron), 'B', new UnificationEntry(bolt, Iron), 'S', new // UnificationEntry(screw, Iron), 'W', new UnificationEntry(plate, Wood)); - VanillaRecipeHelper.addShapedRecipe(provider, "treated_wood_planks", GTBlocks.TREATED_WOOD_PLANK.asStack(8), - "PPP", "PBP", "PPP", 'P', ItemTags.PLANKS, 'B', Creosote.getBucket()); + VanillaRecipeHelper.addShapedFluidContainerRecipe(provider, "treated_wood_planks", + GTBlocks.TREATED_WOOD_PLANK.asStack(8), + "PPP", "PBP", "PPP", 'P', ItemTags.PLANKS, 'B', + new FluidContainerIngredient(Creosote.getFluidTag(), 1000)); VanillaRecipeHelper.addShapedRecipe(provider, "rubber_ring", ChemicalHelper.get(ring, Rubber), "k", "X", 'X', new UnificationEntry(plate, Rubber)); @@ -234,6 +237,7 @@ public static void init(Consumer provider) { /////////////////////////////////////////////////// // Credits // /////////////////////////////////////////////////// + // TODO shapeless fluid container recipes VanillaRecipeHelper.addShapelessRecipe(provider, "coin_chocolate", COIN_CHOCOLATE.asStack(), new UnificationEntry(dust, Cocoa), new UnificationEntry(foil, Gold), new ItemStack(Items.MILK_BUCKET), new UnificationEntry(dust, Sugar)); diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/VanillaStandardRecipes.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/VanillaStandardRecipes.java index ffe961831d..ad4f29c714 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/VanillaStandardRecipes.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/VanillaStandardRecipes.java @@ -3,6 +3,7 @@ import com.gregtechceu.gtceu.api.data.chemical.ChemicalHelper; import com.gregtechceu.gtceu.api.data.chemical.material.stack.UnificationEntry; import com.gregtechceu.gtceu.api.data.tag.TagPrefix; +import com.gregtechceu.gtceu.api.recipe.ingredient.FluidContainerIngredient; import com.gregtechceu.gtceu.common.data.GTMaterials; import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.data.recipe.CustomTags; @@ -459,7 +460,8 @@ private static void woodRecipes(Consumer provider) { VanillaRecipeHelper.addShapedRecipe(provider, "torch_coke_dust", new ItemStack(Blocks.TORCH, 8), "C", "S", 'C', new UnificationEntry(dust, Coke), 'S', new ItemStack(Items.STICK)); VanillaRecipeHelper.addShapedRecipe(provider, "torch_creosote", new ItemStack(Blocks.TORCH, 16), "WB", "S ", - 'W', ItemTags.WOOL, 'S', new ItemStack(Items.STICK), 'B', Creosote.getBucket()); + 'W', ItemTags.WOOL, 'S', new ItemStack(Items.STICK), 'B', + new FluidContainerIngredient(Creosote.getFluidTag(), 1000)); VanillaRecipeHelper.addShapedRecipe(provider, "soul_torch", new ItemStack(Blocks.SOUL_TORCH, 1), "WB", 'W', ItemTags.SOUL_FIRE_BASE_BLOCKS, 'B', new ItemStack(Blocks.TORCH)); diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/WoodMachineRecipes.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/WoodMachineRecipes.java index 654b938704..36fcb1e7c7 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/WoodMachineRecipes.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/WoodMachineRecipes.java @@ -14,8 +14,6 @@ import com.gregtechceu.gtceu.data.recipe.VanillaRecipeHelper; import com.gregtechceu.gtceu.data.recipe.WoodTypeEntry; -import com.lowdragmc.lowdraglib.side.fluid.forge.FluidHelperImpl; - import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; @@ -24,7 +22,6 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraftforge.common.Tags; -import net.minecraftforge.fluids.FluidUtil; import org.jetbrains.annotations.NotNull; @@ -807,12 +804,6 @@ public static void registerWoodTypeRecipe(Consumer provider, @No * Standard recipes for GT woods */ private static void registerGTWoodRecipes(Consumer provider) { - VanillaRecipeHelper.addShapedRecipe(provider, "treated_wood_planks", - GTBlocks.TREATED_WOOD_PLANK.asStack(8), - "PPP", "PBP", "PPP", - 'P', ItemTags.PLANKS, - 'B', FluidUtil.getFilledBucket(FluidHelperImpl.toFluidStack(Creosote.getFluid(1000)))); - VanillaRecipeHelper.addShapedRecipe(provider, "treated_wood_stick", ChemicalHelper.get(rod, TreatedWood, ConfigHolder.INSTANCE.recipes.nerfWoodCrafting ? 2 : 4), "L", "L", diff --git a/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java b/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java index ad4a2d14c0..4921fb4965 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java @@ -13,8 +13,6 @@ import com.lowdragmc.lowdraglib.LDLib; import com.lowdragmc.lowdraglib.side.fluid.FluidHelper; import com.lowdragmc.lowdraglib.side.fluid.FluidStack; -import com.lowdragmc.lowdraglib.side.fluid.FluidTransferHelper; -import com.lowdragmc.lowdraglib.side.fluid.IFluidTransfer; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; @@ -409,24 +407,6 @@ public static Fluid getMoltenFluid(@NotNull Material material) { return null; } - /** - * Get fluidstack from a container. - * - * @param ingredient the fluidstack or fluid container item - * @return the fluidstack in container - */ - @Nullable - public static FluidStack getFluidFromContainer(Object ingredient) { - if (ingredient instanceof FluidStack) { - return (FluidStack) ingredient; - } else if (ingredient instanceof ItemStack itemStack) { - IFluidTransfer fluidHandler = FluidTransferHelper.getFluidTransfer(itemStack); - if (fluidHandler != null) - return fluidHandler.drain(Integer.MAX_VALUE, false); - } - return null; - } - public static boolean canSeeSunClearly(Level world, BlockPos blockPos) { if (!world.canSeeSky(blockPos.above())) { return false; diff --git a/src/main/java/com/gregtechceu/gtceu/utils/InfiniteFluidTransfer.java b/src/main/java/com/gregtechceu/gtceu/utils/InfiniteFluidTransfer.java new file mode 100644 index 0000000000..f61f4508f7 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/utils/InfiniteFluidTransfer.java @@ -0,0 +1,64 @@ +package com.gregtechceu.gtceu.utils; + +import com.lowdragmc.lowdraglib.side.fluid.FluidStack; +import com.lowdragmc.lowdraglib.side.fluid.IFluidTransfer; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; + +@RequiredArgsConstructor +public class InfiniteFluidTransfer implements IFluidTransfer { + + @Getter + private final int tanks; + + @NotNull + @Override + public FluidStack getFluidInTank(int tank) { + return FluidStack.empty(); + } + + @Override + public void setFluidInTank(int tank, @NotNull FluidStack fluidStack) {} + + @Override + public long getTankCapacity(int tank) { + return Long.MAX_VALUE; + } + + @Override + public boolean isFluidValid(int tank, @NotNull FluidStack stack) { + return true; + } + + @Override + public long fill(int tank, FluidStack resource, boolean simulate, boolean notifyChanges) { + return resource.getAmount(); + } + + @Override + public boolean supportsFill(int tank) { + return true; + } + + @NotNull + @Override + public FluidStack drain(int tank, FluidStack resource, boolean simulate, boolean notifyChanges) { + return resource.copy(); + } + + @Override + public boolean supportsDrain(int tank) { + return true; + } + + @NotNull + @Override + public Object createSnapshot() { + return new Object(); + } + + @Override + public void restoreFromSnapshot(Object snapshot) {} +}