Skip to content

Commit

Permalink
- new ingredient type "bucketlib:block" to specify buckets with block…
Browse files Browse the repository at this point in the history
…s in a recipe

- new ingredient type "bucketlib:entity" to specify buckets with entities in a recipe
- fixed: JEI showed vanilla bucket in recipes of specific "bucketlib:empty" ingredients
  • Loading branch information
cech12 committed Jan 31, 2024
1 parent d99b004 commit 67bbd81
Show file tree
Hide file tree
Showing 17 changed files with 670 additions and 59 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Forge Recommended Versioning](https://mcforge.readthedocs.io/en/latest/conventions/versioning/).

## [1.20.4-3.1.2.0] - 2024-01-31
### Added
- new ingredient type "bucketlib:block" to specify buckets with blocks in a recipe
- new ingredient type "bucketlib:entity" to specify buckets with entities in a recipe

### Fixed
- JEI showed vanilla bucket in recipes of specific "bucketlib:empty" ingredients (thanks to FreeFull for the report)

## [1.20.4-3.1.1.0] - 2024-01-31
### Added
- new ingredient type "bucketlib:empty" to specify an empty bucket in a recipe (thanks to FreeFull for the idea) #34
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ public InteractionResultHolder<ItemStack> use(@Nonnull Level level, @Nonnull Pla
InteractionResult interactionResult = fakeStack.useOn(new UseOnContext(player, interactionHand, blockHitResult));
player.setItemInHand(interactionHand, itemstack);
if (interactionResult.consumesAction()) {
return new InteractionResultHolder<>(interactionResult, BucketLibUtil.createEmptyResult(itemstack, player, BucketLibUtil.removeBlock(itemstack), interactionHand));
return new InteractionResultHolder<>(interactionResult, BucketLibUtil.createEmptyResult(itemstack, player, BucketLibUtil.removeBlock(itemstack, true), interactionHand));
}
}
}
Expand Down Expand Up @@ -402,8 +402,20 @@ public ItemStack getCraftingRemainingItem(ItemStack itemStack) {
if (BucketLibUtil.isAffectedByInfinityEnchantment(itemStack)) {
return itemStack.copy();
}
// AFAIK this method is only used by fluid handling. Other things like entities, blocks, etc. should not be affected by this.
return BucketLibUtil.removeFluid(itemStack);
//remove everything from bucket
ItemStack result = itemStack.copy();
boolean damaged = BucketLibUtil.containsFluid(result); //damaging is done by fluid handler
if (BucketLibUtil.containsBlock(result)) {
result = BucketLibUtil.removeBlock(result, !damaged);
damaged = true;
}
if (BucketLibUtil.containsEntityType(result)) {
result = BucketLibUtil.removeEntityType(result, !damaged);
}
if (BucketLibUtil.containsFluid(result) || BucketLibUtil.containsMilk(result)) {
result = BucketLibUtil.removeFluid(result);
}
return result;
}

private boolean getBooleanProperty(Supplier<Boolean> config, boolean defaultValue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ private ItemStack emptyBucket(@Nonnull BlockSource source, @Nonnull ItemStack st
Block placeBlock = BucketLibUtil.getBlock(stack);
if (placeBlock != null && placeBlock.asItem() instanceof DispensibleContainerItem dispensibleContainerItem) {
if (dispensibleContainerItem.emptyContents(null, level, placePosition, null)) {
return BucketLibUtil.removeBlock(stack);
return BucketLibUtil.removeBlock(stack, true);
}
}
} else if (BucketLibUtil.containsEntityType(stack)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,9 @@ public static ItemStack addBlock(ItemStack itemStack, Block block) {
return itemStack.copy();
}

public static ItemStack removeBlock(ItemStack itemStack) {
public static ItemStack removeBlock(ItemStack itemStack, boolean damage) {
if (!containsMilk(itemStack)) {
return removeContent(itemStack);
return removeContent(itemStack, damage);
}
return itemStack.copy();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ public static List<BucketEntity> getBucketEntities() {
return bucketEntities;
}

public static BucketEntity getBucketEntity(EntityType<?> entityType) {
for (BucketEntity bucketEntity : getBucketEntities()) {
if (bucketEntity.entityType() == entityType) {
return bucketEntity;
}
}
return null;
}

public record BucketBlock(Block block, SolidBucketItem bucketItem) {}

public record BucketEntity(EntityType<?> entityType, Fluid fluid, MobBucketItem bucketItem) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public static InteractionResultHolder<ItemStack> tryPlaceIntoCauldron(Level leve
player.getAbilities().instabuild = previousInstabuildValue;
player.setItemInHand(interactionHand, itemstack);
if (interactionResult.consumesAction()) {
return new InteractionResultHolder<>(interactionResult, BucketLibUtil.createEmptyResult(itemstack, player, BucketLibUtil.removeBlock(itemstack), interactionHand, true));
return new InteractionResultHolder<>(interactionResult, BucketLibUtil.createEmptyResult(itemstack, player, BucketLibUtil.removeBlock(itemstack, true), interactionHand, true));
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion forge/src/main/java/de/cech12/bucketlib/BucketLibMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import de.cech12.bucketlib.api.BucketLib;
import de.cech12.bucketlib.api.BucketLibApi;
import de.cech12.bucketlib.api.BucketLibTags;
import de.cech12.bucketlib.api.crafting.BlockIngredient;
import de.cech12.bucketlib.api.crafting.EmptyIngredient;
import de.cech12.bucketlib.api.crafting.EntityIngredient;
import de.cech12.bucketlib.api.crafting.FluidIngredient;
import de.cech12.bucketlib.api.crafting.MilkIngredient;
import de.cech12.bucketlib.api.item.UniversalBucketItem;
Expand Down Expand Up @@ -49,9 +51,11 @@ public class BucketLibMod {

static {
RECIPE_SERIALIZERS.register("bucket_dyeing", () -> BucketDyeingRecipe.Serializer.INSTANCE);
INGREDIENT_SERIALIZERS.register("block", () -> BlockIngredient.SERIALIZER);
INGREDIENT_SERIALIZERS.register("empty", () -> EmptyIngredient.SERIALIZER);
INGREDIENT_SERIALIZERS.register("entity", () -> EntityIngredient.SERIALIZER);
INGREDIENT_SERIALIZERS.register("fluid", () -> FluidIngredient.SERIALIZER);
INGREDIENT_SERIALIZERS.register("milk", () -> MilkIngredient.SERIALIZER);
INGREDIENT_SERIALIZERS.register("empty", () -> EmptyIngredient.SERIALIZER);
}

private static final Logger LOGGER = LogManager.getLogger();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package de.cech12.bucketlib.api.crafting;

import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import de.cech12.bucketlib.BucketLibMod;
import de.cech12.bucketlib.util.BucketLibUtil;
import de.cech12.bucketlib.util.RegistryUtil;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.common.crafting.ingredients.AbstractIngredient;
import net.minecraftforge.common.crafting.ingredients.IIngredientSerializer;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.tags.ITagManager;

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;

public class BlockIngredient extends AbstractIngredient {

protected final Block block;
protected final TagKey<Block> tag;
private ItemStack[] matchingStacks;

private BlockIngredient(Block block, TagKey<Block> tag) {
super(Stream.of());
this.block = block;
this.tag = tag;
}

public BlockIngredient(Optional<ResourceLocation> blockOptional, Optional<TagKey<Block>> tagOptional) {
this(blockOptional.map(ForgeRegistries.BLOCKS::getValue).orElse(null), tagOptional.orElse(null));
}

public BlockIngredient(Block block) {
this(block, null);
}

public BlockIngredient(TagKey<Block> tag) {
this(null, tag);
}

@Override
public boolean test(ItemStack itemStack) {
if (itemStack == null || itemStack.isEmpty()) {
return false;
}
Iterable<Block> blockIterator;
if (this.block != null) {
blockIterator = List.of(this.block);
} else {
blockIterator = Objects.requireNonNull(ForgeRegistries.BLOCKS.tags()).getTag(this.tag);
}
for (Block block : blockIterator) {
RegistryUtil.BucketBlock bucketBlock = RegistryUtil.getBucketBlock(block);
if (bucketBlock != null) {
if (itemStack.getItem() == bucketBlock.bucketItem()) {
return true;
}
return BucketLibUtil.getBlock(itemStack) == block;
}
}
return false;
}

@Override
@Nonnull
public ItemStack[] getItems() {
if (this.matchingStacks == null) {
ArrayList<ItemStack> stacks = new ArrayList<>();
List<Block> blocks = new ArrayList<>();
ITagManager<Block> blockTags = ForgeRegistries.BLOCKS.tags();
if (this.tag != null && blockTags != null) {
blockTags.getTag(this.tag).forEach(blocks::add);
} else if (this.block != null) {
blocks.add(this.block);
}
List<RegistryUtil.BucketBlock> bucketBlocks = RegistryUtil.getBucketBlocks().stream().filter(bucketBlock -> blocks.contains(bucketBlock.block())).toList();
//vanilla buckets
for (RegistryUtil.BucketBlock bucketBlock : bucketBlocks) {
stacks.add(new ItemStack(bucketBlock.bucketItem()));
}
//bucket lib buckets
for (RegistryUtil.BucketBlock bucketBlock : bucketBlocks) {
BucketLibMod.getRegisteredBuckets().forEach(bucket -> {
if (bucket.canHoldBlock(bucketBlock.block())) {
stacks.add(BucketLibUtil.addBlock(new ItemStack(bucket), bucketBlock.block()));
}
});
}
this.matchingStacks = stacks.toArray(new ItemStack[0]);
}
return this.matchingStacks;
}

@Override
public boolean isEmpty() {
return false;
}

@Override
public boolean isSimple() {
return false;
}

@Override
protected void invalidate() {
this.matchingStacks = null;
}

@Override
@Nonnull
public IIngredientSerializer<? extends Ingredient> serializer() {
return SERIALIZER;
}

public static final Codec<BlockIngredient> CODEC = RecordCodecBuilder.create(builder ->
builder.group(
ResourceLocation.CODEC.optionalFieldOf("block").forGetter(i -> Optional.ofNullable(ForgeRegistries.BLOCKS.getKey(i.block))),
TagKey.codec(ForgeRegistries.BLOCKS.getRegistryKey()).optionalFieldOf("tag").forGetter(i -> Optional.ofNullable(i.tag))
).apply(builder, BlockIngredient::new)
);

public static final IIngredientSerializer<BlockIngredient> SERIALIZER = new IIngredientSerializer<>() {

@Override
public Codec<? extends BlockIngredient> codec() {
return CODEC;
}

@Override
public BlockIngredient read(FriendlyByteBuf buffer) {
String block = buffer.readUtf();
String tagId = buffer.readUtf();
if (!tagId.isEmpty()) {
TagKey<Block> tag = TagKey.create(ForgeRegistries.BLOCKS.getRegistryKey(), new ResourceLocation(tagId));
return new BlockIngredient(tag);
}
if (block.isEmpty()) {
throw new IllegalArgumentException("Cannot create a block ingredient with no block or tag.");
}
return new BlockIngredient(ForgeRegistries.BLOCKS.getValue(new ResourceLocation(block)));
}

@Override
public void write(@Nonnull FriendlyByteBuf buffer, @Nonnull BlockIngredient ingredient) {
buffer.writeUtf(ingredient.block != null ? Objects.requireNonNull(ForgeRegistries.BLOCKS.getKey(ingredient.block)).toString() : "");
buffer.writeUtf(ingredient.tag != null ? ingredient.tag.location().toString() : "");
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ public boolean test(ItemStack itemStack) {
public ItemStack[] getItems() {
if (this.matchingStacks == null) {
ArrayList<ItemStack> stacks = new ArrayList<>();
stacks.add(new ItemStack(Items.BUCKET));
if (this.item == null && this.tag == null) {
stacks.add(new ItemStack(Items.BUCKET));
}
BucketLibMod.getRegisteredBuckets().forEach(universalBucketItem -> {
ItemStack universalBucketItemStack = new ItemStack(universalBucketItem);
if (this.item != null && universalBucketItem == this.item
Expand Down
Loading

0 comments on commit 67bbd81

Please sign in to comment.