Posted August 4, 20223 yr Hi guys) I have a custom furnace, and an idea that is impossible to implement if it is possible to move items from there to somewhere using a hopper (automatic farm or something), so I need to prevent the item from exiting to third-party objects (ie, not the player)
August 4, 20223 yr Author 2 minutes ago, diesieben07 said: Hoppers will use getCapability with ITEM_HANDLER_CAPABILITY to interact with your BlockEntity. Make sure you return an IItemHandler that represents your intended interactino with hoppers (or do not expose the capability at all if you do not want them to interact). Make sure your BE does not inherit from Container (legacy vanilla code). very fast answer dude, thank you, i will try it Edited August 4, 20223 yr by vntlyy007
August 4, 20223 yr Author 3 hours ago, diesieben07 said: Hoppers will use getCapability with ITEM_HANDLER_CAPABILITY to interact with your BlockEntity. Make sure you return an IItemHandler that represents your intended interactino with hoppers (or do not expose the capability at all if you do not want them to interact). Make sure your BE does not inherit from Container (legacy vanilla code). I found this code in my custom block entity: public class CleaningTableBlockEntity extends BlockEntity implements MenuProvider { @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @javax.annotation.Nullable Direction side) { if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { return lazyItemHandler.cast(); } return super.getCapability(cap, side); } } but actually idk what should i do about this?) i tried deleted it(but slots dont load) Or what do you mean by "do not expose the capability at all"? Also, I have another thing I'm trying to do is be able to put in the slot only items with a special tag (like furnace fuel) Edited August 4, 20223 yr by vntlyy007
August 4, 20223 yr Author HOWEVER, actualy there are more things My furnace more like crafting table, but with time - cleaning of fossil ores with special item with durability everything is in order: 1)to prevent items from the output slot from moving into the hopper 2)to be able to put in the slot only items with a special tag (like furnace fuel) 3)remove the ability to discard a finished smelting item back to output slot through use quick move 4) add the ability to add smelting time in json recipe(it's the easier) GITHub There is my project, if somebody want/can, I will be grateful for your help < 3 Edited August 4, 20223 yr by vntlyy007
August 5, 20223 yr 11 hours ago, vntlyy007 said: to be able to put in the slot only items with a special tag (like furnace fuel) Override #mayPlace in your Slot class you can take a look at how vanilla done this (e.g. AbstractFurnaceMenu). 11 hours ago, vntlyy007 said: remove the ability to discard a finished smelting item back to output slot through use quick move Should you be able to place Items in the result slot? Yes -> You need to handle this is #quickMoveStack of your Menu No -> Override #mayPlace in your result Slot class and return false 11 hours ago, vntlyy007 said: add the ability to add smelting time in json recipe(it's the easier) Take a look how vanilla done this, basically you need to add a property for the cooking time to the recipe, when you get the recipe for the current item in the input slot(s) you need to set the cooking time. Btw you need to register your Recipe Serializer you can not create it in a static initializer, the highly recommended way is to use DeferredRegister.
August 5, 20223 yr Author 6 hours ago, Luis_ST said: Перевизначте #mayPlace у вашому класі Slot, ви можете подивитися, як vanilla це зробила (наприклад, AbstractFurnaceMenu). Чи можна розміщувати предмети в слоті результатів? Так -> Вам потрібно обробити це #quickMoveStack вашого меню Ні -> Замінити #mayPlace у вашому класі результатів Slot і повернути false Подивіться, як Vanilla це зробила, загалом, вам потрібно додати властивість для часу приготування до рецепту, коли ви отримаєте рецепт для поточного елемента у вхідних слотах, вам потрібно встановити час приготування. До речі, вам потрібно зареєструвати свій серіалізатор рецептів, ви не можете створити його в статичному ініціалізаторі, настійно рекомендованим способом є використання DeferredRegister. I have completed two tasks, it remains to add the time in json. But I still have a problem with Hopper. It takes items from input slots (I still haven't figured out what I was advised to do with getCapabilities) I tried all my ideas to reproduce it, so I still will be grateful for help BlockEntity: Spoiler public class CleaningTableBlockEntity extends BlockEntity implements MenuProvider { private final ItemStackHandler itemHandler = new ItemStackHandler(3){ @Override protected void onContentsChanged(int Slot){ setChanged(); } }; private LazyOptional<IItemHandler> lazyItemHandler = LazyOptional.empty(); protected final ContainerData data; private int progress = 0; private int maxProgress = 26; public CleaningTableBlockEntity(BlockPos p_155229_, BlockState p_155230_) { super(ModBlockEntities.CLEANING_TABLE_BLOCK_ENTITY.get(), p_155229_, p_155230_); this.data = new ContainerData() { public int get(int index) { switch (index) { case 0: return CleaningTableBlockEntity.this.progress; case 1: return CleaningTableBlockEntity.this.maxProgress; default: return 0; } } public void set(int index, int value) { switch(index) { case 0: CleaningTableBlockEntity.this.progress = value; break; case 1: CleaningTableBlockEntity.this.maxProgress = value; break; } } public int getCount() { return 2; } }; } @Override public Component getDisplayName() { return new TextComponent("Cleaning Table"); } @Nullable @Override public AbstractContainerMenu createMenu(int pContainerId, Inventory pInventory, Player pPlayer) { return new CleaningTableMenu(pContainerId, pInventory, this, this.data); } @Nonnull @Override public void onLoad() { super.onLoad(); lazyItemHandler = LazyOptional.of(() -> itemHandler); } @Override public void invalidateCaps() { super.invalidateCaps(); lazyItemHandler.invalidate(); } @Override protected void saveAdditional(@NotNull CompoundTag tag) { tag.put("inventory", itemHandler.serializeNBT()); tag.putInt("cleaning.progress", progress); super.saveAdditional(tag); } @Override public void load(CompoundTag nbt) { super.load(nbt); itemHandler.deserializeNBT(nbt.getCompound("inventory")); progress = nbt.getInt("cleaning.progress"); } public void drops() { SimpleContainer inventory = new SimpleContainer(itemHandler.getSlots()); for (int i = 0; i < itemHandler.getSlots(); i++) { inventory.setItem(i, itemHandler.getStackInSlot(i)); } Containers.dropContents(this.level, this.worldPosition, inventory); } public static void serverTick(Level pLevel, BlockPos pPos, BlockState pState, CleaningTableBlockEntity pBlockEntity) { if(hasRecipe(pBlockEntity)) { pBlockEntity.progress++; setChanged(pLevel, pPos, pState); if(pBlockEntity.progress > pBlockEntity.maxProgress) { craftItem(pBlockEntity); } } else { pBlockEntity.resetProgress(); setChanged(pLevel, pPos, pState); } } private static boolean hasRecipe(@NotNull CleaningTableBlockEntity entity) { Level level = entity.level; SimpleContainer inventory = new SimpleContainer(entity.itemHandler.getSlots()); for (int i = 0; i < entity.itemHandler.getSlots(); i++) { inventory.setItem(i, entity.itemHandler.getStackInSlot(i)); } Optional<CleaningTableRecipe> match = level.getRecipeManager() .getRecipeFor(CleaningTableRecipe.Type.INSTANCE, inventory, level); return match.isPresent() && canInsertAmountIntoOutputSlot(inventory) && canInsertItemIntoOutputSlot(inventory, match.get().getResultItem()) && hasToolsInToolSlot(entity); } private static boolean hasToolsInToolSlot(CleaningTableBlockEntity entity) { return !entity.itemHandler.getStackInSlot(1).isEmpty(); } @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @javax.annotation.Nullable Direction side) { if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { return lazyItemHandler.cast(); } return super.getCapability(cap, side); } private static void craftItem(CleaningTableBlockEntity entity) { Level level = entity.level; SimpleContainer inventory = new SimpleContainer(entity.itemHandler.getSlots()); for (int i = 0; i < entity.itemHandler.getSlots(); i++) { inventory.setItem(i, entity.itemHandler.getStackInSlot(i)); } Optional<CleaningTableRecipe> match = level.getRecipeManager() .getRecipeFor(CleaningTableRecipe.Type.INSTANCE, inventory, level); if(match.isPresent()) { entity.itemHandler.extractItem(0,1, false); if(entity.itemHandler.getStackInSlot(1).hurt(1, new Random(), null)) { entity.itemHandler.extractItem(1, 1, false); } entity.itemHandler.setStackInSlot(2, new ItemStack(match.get().getResultItem().getItem(), entity.itemHandler.getStackInSlot(2).getCount() + 1)); entity.resetProgress(); } } private void resetProgress() { this.progress = 0; } private static boolean canInsertItemIntoOutputSlot(SimpleContainer inventory, ItemStack output) { return inventory.getItem(2).getItem() == output.getItem() || inventory.getItem(2).isEmpty(); } private static boolean canInsertAmountIntoOutputSlot(SimpleContainer inventory) { return inventory.getItem(2).getMaxStackSize() > inventory.getItem(2).getCount(); } Edited August 5, 20223 yr by vntlyy007
August 6, 20223 yr Author Hopper takes items from input slot, i tried to clone the code of vanilla containers, but it doesn't work BlockEntity: Spoiler public class CleaningTableBlockEntity extends BlockEntity implements MenuProvider { private final ItemStackHandler itemHandler = new ItemStackHandler(3){ @Override protected void onContentsChanged(int Slot){ setChanged(); } }; private LazyOptional<IItemHandler> lazyItemHandler = LazyOptional.empty(); protected final ContainerData data; private int progress = 0; private int maxProgress = 26; public CleaningTableBlockEntity(BlockPos p_155229_, BlockState p_155230_) { super(ModBlockEntities.CLEANING_TABLE_BLOCK_ENTITY.get(), p_155229_, p_155230_); this.data = new ContainerData() { public int get(int index) { switch (index) { case 0: return CleaningTableBlockEntity.this.progress; case 1: return CleaningTableBlockEntity.this.maxProgress; default: return 0; } } public void set(int index, int value) { switch(index) { case 0: CleaningTableBlockEntity.this.progress = value; break; case 1: CleaningTableBlockEntity.this.maxProgress = value; break; } } public int getCount() { return 2; } }; } @Override public Component getDisplayName() { return new TextComponent("Cleaning Table"); } @Nullable @Override public AbstractContainerMenu createMenu(int pContainerId, Inventory pInventory, Player pPlayer) { return new CleaningTableMenu(pContainerId, pInventory, this, this.data); } @Nonnull @Override public void onLoad() { super.onLoad(); lazyItemHandler = LazyOptional.of(() -> itemHandler); } @Override public void invalidateCaps() { super.invalidateCaps(); lazyItemHandler.invalidate(); } @Override protected void saveAdditional(@NotNull CompoundTag tag) { tag.put("inventory", itemHandler.serializeNBT()); tag.putInt("cleaning.progress", progress); super.saveAdditional(tag); } @Override public void load(CompoundTag nbt) { super.load(nbt); itemHandler.deserializeNBT(nbt.getCompound("inventory")); progress = nbt.getInt("cleaning.progress"); } public void drops() { SimpleContainer inventory = new SimpleContainer(itemHandler.getSlots()); for (int i = 0; i < itemHandler.getSlots(); i++) { inventory.setItem(i, itemHandler.getStackInSlot(i)); } Containers.dropContents(this.level, this.worldPosition, inventory); } public static void serverTick(Level pLevel, BlockPos pPos, BlockState pState, CleaningTableBlockEntity pBlockEntity) { if(hasRecipe(pBlockEntity)) { pBlockEntity.progress++; setChanged(pLevel, pPos, pState); if(pBlockEntity.progress > pBlockEntity.maxProgress) { craftItem(pBlockEntity); } } else { pBlockEntity.resetProgress(); setChanged(pLevel, pPos, pState); } } private static boolean hasRecipe(@NotNull CleaningTableBlockEntity entity) { Level level = entity.level; SimpleContainer inventory = new SimpleContainer(entity.itemHandler.getSlots()); for (int i = 0; i < entity.itemHandler.getSlots(); i++) { inventory.setItem(i, entity.itemHandler.getStackInSlot(i)); } Optional<CleaningTableRecipe> match = level.getRecipeManager() .getRecipeFor(CleaningTableRecipe.Type.INSTANCE, inventory, level); return match.isPresent() && canInsertAmountIntoOutputSlot(inventory) && canInsertItemIntoOutputSlot(inventory, match.get().getResultItem()) && hasToolsInToolSlot(entity); } private static boolean hasToolsInToolSlot(CleaningTableBlockEntity entity) { return !entity.itemHandler.getStackInSlot(1).isEmpty(); } @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @javax.annotation.Nullable Direction side) { if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { return lazyItemHandler.cast(); } return super.getCapability(cap, side); } private static void craftItem(CleaningTableBlockEntity entity) { Level level = entity.level; SimpleContainer inventory = new SimpleContainer(entity.itemHandler.getSlots()); for (int i = 0; i < entity.itemHandler.getSlots(); i++) { inventory.setItem(i, entity.itemHandler.getStackInSlot(i)); } Optional<CleaningTableRecipe> match = level.getRecipeManager() .getRecipeFor(CleaningTableRecipe.Type.INSTANCE, inventory, level); if(match.isPresent()) { entity.itemHandler.extractItem(0,1, false); if(entity.itemHandler.getStackInSlot(1).hurt(1, new Random(), null)) { entity.itemHandler.extractItem(1, 1, false); } entity.itemHandler.setStackInSlot(2, new ItemStack(match.get().getResultItem().getItem(), entity.itemHandler.getStackInSlot(2).getCount() + 1)); entity.resetProgress(); } } private void resetProgress() { this.progress = 0; } private static boolean canInsertItemIntoOutputSlot(SimpleContainer inventory, ItemStack output) { return inventory.getItem(2).getItem() == output.getItem() || inventory.getItem(2).isEmpty(); } private static boolean canInsertAmountIntoOutputSlot(SimpleContainer inventory) { return inventory.getItem(2).getMaxStackSize() > inventory.getItem(2).getCount(); }
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.