Skip to content

[API] Item Filling & Emptying Registries #8177

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: mc1.20.1/dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

64 changes: 64 additions & 0 deletions src/main/java/com/simibubi/create/AllItemEmptyings.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.simibubi.create;

import java.util.Collection;
import java.util.function.Consumer;

import org.jetbrains.annotations.Unmodifiable;

import com.simibubi.create.api.fluids.transfer.ItemEmptying;
import com.simibubi.create.content.fluids.potion.PotionFluidHandler;
import com.simibubi.create.content.fluids.transfer.EmptyingRecipe;
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder;
import com.simibubi.create.foundation.fluid.FluidIngredient;

import net.createmod.catnip.data.Pair;
import net.createmod.catnip.platform.CatnipServices;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.Potion;
import net.minecraft.world.item.alchemy.PotionUtils;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.Level;

import net.minecraftforge.fluids.FluidStack;

public class AllItemEmptyings {
static void registerDefaults() {
ItemEmptying.REGISTRY.add(Items.POTION, new PotionEmptying(Items.POTION));
ItemEmptying.REGISTRY.add(Items.SPLASH_POTION, new PotionEmptying(Items.SPLASH_POTION));
ItemEmptying.REGISTRY.add(Items.LINGERING_POTION, new PotionEmptying(Items.LINGERING_POTION));
}

record PotionEmptying(Item potion) implements ItemEmptying {
@Override
public Pair<FluidStack, ItemStack> emptyItem(Level world, ItemStack stack, boolean simulate) {
return PotionFluidHandler.emptyPotion(stack, simulate);
}

@Override
public void provideRecipes(Consumer<EmptyingRecipe> consumer, @Unmodifiable Collection<ItemStack> itemIngredients, @Unmodifiable Collection<FluidStack> fluidIngredients) {
itemIngredients
.stream()
.filter(stack -> stack.is(this.potion))
.map(stack -> {
Potion potion = PotionUtils.getPotion(stack);
ResourceLocation potionId = CatnipServices.REGISTRIES.getKeyOrThrow(potion);
ResourceLocation id = new ResourceLocation(
potionId.getNamespace(),
"emptying/" +
CatnipServices.REGISTRIES.getKeyOrThrow(stack.getItem()).getPath() +
"_of_" +
potionId.getPath()
);
return new ProcessingRecipeBuilder<>(EmptyingRecipe::new, id)
.require(Ingredient.of(stack))
.output(PotionFluidHandler.getFluidFromPotionItem(stack))
.output(Items.GLASS_BOTTLE)
.build();
})
.forEach(consumer);
}
}
}
115 changes: 115 additions & 0 deletions src/main/java/com/simibubi/create/AllItemFillings.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.simibubi.create;

import java.util.Collection;
import java.util.function.Consumer;

import org.jetbrains.annotations.ApiStatus.Internal;
import org.jetbrains.annotations.Unmodifiable;

import com.simibubi.create.AllTags.AllFluidTags;
import com.simibubi.create.api.fluids.transfer.ItemFilling;
import com.simibubi.create.content.fluids.potion.PotionFluidHandler;
import com.simibubi.create.content.fluids.transfer.FillingRecipe;
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder;
import com.simibubi.create.foundation.data.recipe.Mods;
import com.simibubi.create.foundation.fluid.FluidIngredient;

import net.createmod.catnip.platform.CatnipServices;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.PotionUtils;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.material.Fluids;

import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;

public class AllItemFillings {
private static final RegistryObject<Item> FD_MILK_BOTTLE = RegistryObject
.create(Mods.FD.asResource("milk_bottle"), ForgeRegistries.ITEMS);
private static final RegistryObject<Item> NEA_MILK_BOTTLE = RegistryObject
.create(Mods.NEA.asResource("milk_bottle"), ForgeRegistries.ITEMS);
private static final RegistryObject<Item> AM_LAVA_BOTTLE = RegistryObject
.create(Mods.AM.asResource("lava_bottle"), ForgeRegistries.ITEMS);

static void registerDefaults() {
ItemFilling.registerSimple(
Create.asResource("filling/honey_bottle"),
Items.GLASS_BOTTLE,
FluidIngredient.fromTag(AllFluidTags.HONEY.tag, 250),
Items.HONEY_BOTTLE.getDefaultInstance()
);
ItemFilling.registerSimple(
Create.asResource("filling/builders_tea"),
Items.GLASS_BOTTLE,
FluidIngredient.fromFluid(AllFluids.TEA.get(), 250),
AllItems.BUILDERS_TEA.asStack()
);
AM_LAVA_BOTTLE.ifPresent(item -> ItemFilling.registerSimple(
Create.asResource("filling/" + Mods.AM.recipeId("lava_bottle")),
Items.GLASS_BOTTLE,
FluidIngredient.fromFluid(Fluids.LAVA, 250),
item.getDefaultInstance()
));
if (ForgeMod.MILK.isPresent()) {
FD_MILK_BOTTLE.ifPresent(item -> ItemFilling.registerSimple(
Create.asResource("filling/" + Mods.FD.recipeId("milk_bottle")),
Items.GLASS_BOTTLE,
FluidIngredient.fromFluid(ForgeMod.MILK.get(), 250),
item.getDefaultInstance()
));
NEA_MILK_BOTTLE.ifPresent(item -> ItemFilling.registerSimple(
Create.asResource("filling/" + Mods.NEA.recipeId("milk_bottle")),
Items.GLASS_BOTTLE,
FluidIngredient.fromFluid(ForgeMod.MILK.get(), 250),
item.getDefaultInstance()
));
}
ItemFilling.REGISTRY.add(Items.GLASS_BOTTLE, new PotionFilling());
}

@Internal
static class PotionFilling implements ItemFilling {
@Override
public int getRequiredAmountForItem(Level world, ItemStack stack, FluidStack availableFluid) {
if (availableFluid.getFluid().isSame(AllFluids.POTION.get()))
return PotionFluidHandler.getRequiredAmountForFilledBottle(stack, availableFluid);
return -1;
}

@Override
public ItemStack fillItem(Level world, ItemStack stack, FluidStack availableFluid) {
return PotionFluidHandler.fillBottle(stack, availableFluid);
}

@Override
public void provideRecipes(Consumer<FillingRecipe> consumer, @Unmodifiable Collection<ItemStack> itemIngredients, @Unmodifiable Collection<FluidStack> fluidIngredients) {
itemIngredients
.stream()
.filter(PotionFluidHandler::isPotionItem)
.map(stack -> {
FluidStack fluidFromPotionItem = PotionFluidHandler.getFluidFromPotionItem(stack);
Ingredient bottle = Ingredient.of(Items.GLASS_BOTTLE);
ResourceLocation potionId = CatnipServices.REGISTRIES.getKeyOrThrow(PotionUtils.getPotion(stack));
ResourceLocation id = new ResourceLocation(
potionId.getNamespace(),
"filling/" +
CatnipServices.REGISTRIES.getKeyOrThrow(stack.getItem()).getPath() +
"_of_" +
potionId.getPath()
);
return new ProcessingRecipeBuilder<>(FillingRecipe::new, id)
.require(bottle)
.require(FluidIngredient.fromFluidStack(fluidFromPotionItem))
.withSingleItemOutput(stack)
.build();
})
.forEach(consumer);
}
}
}
2 changes: 2 additions & 0 deletions src/main/java/com/simibubi/create/Create.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ public static void init(final FMLCommonSetupEvent event) {
AllMountedDispenseItemBehaviors.registerDefaults();
AllUnpackingHandlers.registerDefaults();
AllInventoryIdentifiers.registerDefaults();
AllItemFillings.registerDefaults();
AllItemEmptyings.registerDefaults();
// --

AllAdvancements.register();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.simibubi.create.api.fluids.transfer;

import java.util.Collection;
import java.util.function.Consumer;

import org.jetbrains.annotations.Unmodifiable;

import com.simibubi.create.api.registry.SimpleRegistry;
import com.simibubi.create.content.fluids.transfer.EmptyingRecipe;
import com.simibubi.create.content.fluids.transfer.FillingRecipe;
import com.simibubi.create.content.fluids.transfer.GenericItemEmptying;

import net.createmod.catnip.data.Pair;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;

import net.minecraftforge.fluids.FluidStack;

/**
* Interface defining generic emptying behaviour for container-like items
* that needs special handling or to be populated on runtime (e.g. Potions).
* <p>
* For plain cases, create and use {@link FillingRecipe} instead.
* @see GenericItemEmptying
*/
public interface ItemEmptying {
SimpleRegistry.Multi<Item, ItemEmptying> REGISTRY = SimpleRegistry.Multi.create();

/**
* Checks if the item can be emptied.
* @implNote The item check is already guarded by registry,
* overrides only needs to perform stack-sensitive checks.
* @return If the item can be emptied.
*/
default boolean canItemBeEmptied(Level world, ItemStack stack) {
return true;
}

/**
* Empty the item and return the result fluid and container.
* @return The result fluid and container.
* @implNote Unlike {@link ItemFilling#fillItem(Level, ItemStack, FluidStack)},
* overrides should handle the consumption of the item on their own and respect the {@code simulate} parameter.
*/
Pair<FluidStack, ItemStack> emptyItem(Level world, ItemStack stack, boolean simulate);

/**
* Provide the {@link EmptyingRecipe recipe} representation of the filling behaviour for recipe viewers like JEI.
* @param consumer the consumer of the recipes
* @param itemIngredients the known item ingredients for providing recipes
* @param fluidIngredients the known fluid ingredients for providing recipes
*/
default void provideRecipes(Consumer<EmptyingRecipe> consumer, @Unmodifiable Collection<ItemStack> itemIngredients, @Unmodifiable Collection<FluidStack> fluidIngredients) {}
}
Loading