Posted May 16, 20205 yr I have a problem (or problems?) with creating the Container for my custom furnace. I'm new to Minecraft modding, relatively new to Java, but not new to writing stuff for my own enjoyment, whether it's Godot, some simple C# apps, or Unity. Anyways, I'm working on a Roman styled mod, and those guys had stuff made out of bronze. I created ores and ingots for copper and tin, have them generate in the world, all is well, but I somehow need to combine them. Now, I could add a simple recipe to put two ingots next to each other and get a third, but that doesn't really make sense. I opted to create a new Alloy Furnace, which works just like the vanilla furnace, but has two slots for items instead of one. This lead to my discovery of Tile Entities, Containers, etc. I made a new block for the furnace (and a new block item as well), then I proceeded to write the functionality for it. Oops. Wasn't nearly as easy as placing a new block in the world. I tried to follow a tutorial on YouTube for 1.15, but it was about creating a new chest, then I found another one about creating a new furnace (hurray!), but for 1.12 (not hurray). I also figured out how to open vanilla Minecraft files, so I looked at the original furnace to figure out the way to do it. The end result is a Tile Entity, which is basically a vanilla furnace but with an added slot. (It has mostly the same code duplicated to a new AlloyFurnaceTileEntity file, changing some functions to be able to have two slots instead of one.) Then, I figured, I needed a Container as well. Spoiler // Alloy Furnace this.addSlot(new Slot(furnaceInventoryIn, 0, 46, 17)); this.addSlot(new Slot(furnaceInventoryIn, 1, 67, 17)); this.addSlot(new AlloyFurnaceFuelSlot(furnaceInventoryIn, 2, 56, 53)); this.addSlot(new FurnaceResultSlot(playerInventoryIn.player, furnaceInventoryIn, 3, 112, 31)); // Player Inventory for (int y = 0; y < 3; y++) { for (int x = 0; x < 3; x++) { this.addSlot(new Slot(playerInventoryIn, x + y * 9 + 9, 8 + x * 18, 84 + y * 18)); } } // Hotbar for (int x = 0; x < 9; x++) { this.addSlot(new Slot(playerInventoryIn, x, 8 + x * 18, 142)); } I made the code based on this image: Then I did all the overrides the same way AbstractFurnaceContainer.class does. The problem is, I don't know how to register it properly. I have one big RegistryHandler.java file, which handles everything that has to do with the registry. The following is a snippet from my RegistryHandler. The last line I have no idea about, it's from a video I saw. I honestly don't know how to register a ContainerType, but I can't test the furnace until I do. public static final DeferredRegister<ContainerType<?>> CONTAINER_TYPES = new DeferredRegister<>(ForgeRegistries.CONTAINERS, ImperiumRomanum.MOD_ID); public static void init() { CONTAINER_TYPES.register(FMLJavaModLoadingContext.get().getModEventBus()); } public static final RegistryObject<ContainerType<AlloyFurnaceContainer>> ALLOY_FURNACE_CONTAINER = CONTAINER_TYPES.register("alloy_furnace", () -> IForgeContainerType.create(AlloyFurnaceContainer::new); I know that AlloyFurnaceContainer::new won't work but I don't know what to put here. Here's the whole AlloyFurnaceContainer: Spoiler package com.andreasalcor.imperiumromanum.inventory.container; import com.andreasalcor.imperiumromanum.tileentity.AlloyFurnaceTileEntity; import com.andreasalcor.imperiumromanum.util.RegistryHandler; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.IRecipeHelperPopulator; import net.minecraft.inventory.Inventory; import net.minecraft.inventory.container.*; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.*; import net.minecraft.util.IIntArray; import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; public class AlloyFurnaceContainer extends RecipeBookContainer<IInventory> { private final IInventory furnaceInventory; private final IIntArray field_217064_e; private int burnTime, recipeUsed, cookTime, cookTimeTotal; protected final World world; private final IRecipeType<? extends AbstractCookingRecipe> recipeType; public AlloyFurnaceContainer(ContainerType<?> containerTypeIn, IRecipeType<? extends AbstractCookingRecipe> recipeTypeIn, int id, PlayerInventory playerInventoryIn, IInventory furnaceInventoryIn, IIntArray p_i50104_6_) { super(RegistryHandler.ALLOY_FURNACE_CONTAINER.get(), id); this.recipeType = recipeTypeIn; assertInventorySize(furnaceInventoryIn, 4); assertIntArraySize(p_i50104_6_, 5); this.furnaceInventory = furnaceInventoryIn; this.field_217064_e = p_i50104_6_; this.world = playerInventoryIn.player.world; // Alloy Furnace this.addSlot(new Slot(furnaceInventoryIn, 0, 46, 17)); this.addSlot(new Slot(furnaceInventoryIn, 1, 67, 17)); this.addSlot(new AlloyFurnaceFuelSlot(furnaceInventoryIn, 2, 56, 53)); this.addSlot(new FurnaceResultSlot(playerInventoryIn.player, furnaceInventoryIn, 3, 112, 31)); // Player Inventory for (int y = 0; y < 3; y++) { for (int x = 0; x < 3; x++) { this.addSlot(new Slot(playerInventoryIn, x + y * 9 + 9, 8 + x * 18, 84 + y * 18)); } } // Hotbar for (int x = 0; x < 9; x++) { this.addSlot(new Slot(playerInventoryIn, x, 8 + x * 18, 142)); } this.trackIntArray(p_i50104_6_); } @Override public void func_201771_a(RecipeItemHelper helper) { if (this.furnaceInventory instanceof IRecipeHelperPopulator) { ((IRecipeHelperPopulator)this.furnaceInventory).fillStackedContents(helper); } } @Override public void clear() { this.furnaceInventory.clear(); } @Override public void func_217056_a(boolean p_217056_1_, IRecipe<?> p_217056_2_, ServerPlayerEntity p_217056_3_) { (new ServerRecipePlacerFurnace(this)).place(p_217056_3_, p_217056_2_, p_217056_1_); } @Override public boolean matches(IRecipe<? super IInventory> recipeIn) { return recipeIn.matches(this.furnaceInventory, this.world); } @Override public int getOutputSlot() { return 2; } @Override public int getWidth() { return 1; } @Override public int getHeight() { return 1; } @OnlyIn(Dist.CLIENT) public int getSize() { return 3; } @Override public boolean canInteractWith(PlayerEntity playerIn) { return this.furnaceInventory.isUsableByPlayer(playerIn); } @Override public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) { ItemStack itemstack = ItemStack.EMPTY; Slot lvt_4_1_ = (Slot)this.inventorySlots.get(index); if (lvt_4_1_ != null && lvt_4_1_.getHasStack()) { ItemStack itemstack2 = lvt_4_1_.getStack(); itemstack = itemstack2.copy(); if (index == 2) { if (!this.mergeItemStack(itemstack2, 3, 39, true)) { return ItemStack.EMPTY; } lvt_4_1_.onSlotChange(itemstack2, itemstack); } else if (index != 1 && index != 0) { if (this.func_217057_a(itemstack2)) { if (!this.mergeItemStack(itemstack2, 0, 1, false)) { return ItemStack.EMPTY; } } else if (this.isFuel(itemstack2)) { if (!this.mergeItemStack(itemstack2, 1, 2, false)) { return ItemStack.EMPTY; } } else if (index >= 3 && index < 30) { if (!this.mergeItemStack(itemstack2, 30, 39, false)) { return ItemStack.EMPTY; } } else if (index >= 30 && index < 39 && !this.mergeItemStack(itemstack2, 3, 30, false)) { return ItemStack.EMPTY; } } else if (!this.mergeItemStack(itemstack2, 3, 39, false)) { return ItemStack.EMPTY; } if (itemstack2.isEmpty()) { lvt_4_1_.putStack(ItemStack.EMPTY); } else { lvt_4_1_.onSlotChanged(); } if (itemstack2.getCount() == itemstack.getCount()) { return ItemStack.EMPTY; } lvt_4_1_.onTake(playerIn, itemstack2); } return itemstack; } protected boolean func_217057_a(ItemStack p_217057_1_) { return this.world.getRecipeManager().getRecipe(this.recipeType, new Inventory(new ItemStack[]{p_217057_1_}), this.world).isPresent(); } protected boolean isFuel(ItemStack p_217058_1_) { return AlloyFurnaceTileEntity.isFuel(p_217058_1_); } @OnlyIn(Dist.CLIENT) public int getBurnLeftScaled() { int lvt_1_1_ = this.field_217064_e.get(1); if (lvt_1_1_ == 0) { lvt_1_1_ = 200; } return this.field_217064_e.get(0) * 13 / lvt_1_1_; } @OnlyIn(Dist.CLIENT) public boolean func_217061_l() { return this.field_217064_e.get(0) > 0; } } If anyone at least can point me in the right direction, I'd be the happiest person on the planet. I've been going at this single furnace for about 18-20 hours now.
May 16, 20205 yr Break it down. IForgeContainerType#create returns an instance of ContainerType based on its IContainerFactory. IContainerFactory has two create methods. One method contains three variables (the window id, the player inventory, and a packet buffer) while the other one returns the packet buffer as null. Because of this, one of your Container constructors must contain only the window id and player inventory or include the packet buffer as well. Similar to the tile entity, this is the default constructor being used to declare the type and will be updated when called correctly. For myself, I just use a new constructor instance of a container type with diamond syntax to assume the generic and then using a method reference operator on the correct class. Otherwise, you could just simply use the standard interface for your class. Edited May 16, 20205 yr by ChampionAsh5357
May 17, 20205 yr Howdy You might find this working example useful https://github.com/TheGreyGhost/MinecraftByExample/tree/master/src/main/java/minecraftbyexample/mbe31_inventory_furnace It's also for a furnace, in 1.15.2 -TGG
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.