Posted February 1, 20214 yr i just creat a block which is called smelting furnace it should be a faster furnace for the default smelting recipes (like stone, clay, etc.). At the moment the block has the normal furnace container and the normal recipes and i try to creat custom (container and recipe), but now im stuck. 1. registration of container: - i creat a container which extends the vanilla AbstractFurnaceContainer public static final DeferredRegister<ContainerType<?>> CONTAINERS = DeferredRegister.create(ForgeRegistries.CONTAINERS, Cave.Mod_Id); public static final RegistryObject<ContainerType<?>> SMELTING_CONTAINER = CONTAINERS.register("smelting_container", () -> IForgeContainerType.create(SmeltingContainer::new)); but i cant register the container/ why doesn't work that way 2. registration of recipe serializer - how to register a custom AbstractCookingRecipe and how to create form that a IRecipeType which i need for the container public static final DeferredRegister<IRecipeSerializer<?>> RECIPE_SERIALIZERS = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, Cave.Mod_Id); public static final RegistryObject<IRecipeSerializer<?>> SMELTING_RECIPE = RECIPE_SERIALIZERS.register("smelting_recipe", null); what i have to set at "null"
February 1, 20214 yr Author 17 minutes ago, diesieben07 said: If you want it to use the normal furnace recipes, why are you making a custom serializer i not want to use the normal recipes that already work but minecraft has the blast furnace which smelt ores and the smoker which "cook" food. i want to creat a furnace which process / smelt the other recipes faster (like cobblestone to stone in 5 seconds instead of 10 seconds) Edited February 1, 20214 yr by Luis_ST
February 1, 20214 yr Author 27 minutes ago, diesieben07 said: So you want it to use the normal furnace recipes, not the smoker recipes for example - yes? normal furnace - No. I think you don't understand exactly what I want, so simplified I want recipes for a custom furnace with the same gui like the vanilla furnace Short: I want custom recipes that only work in my furnace Edited February 1, 20214 yr by Luis_ST
February 1, 20214 yr Author But back to my questions 3 hours ago, Luis_ST said: 1. registration of container: - i creat a container which extends the vanilla AbstractFurnaceContainer 3 hours ago, Luis_ST said: 2. registration of recipe serializer - how to register a custom AbstractCookingRecipe and how to create form that a IRecipeType which i need for the container Edited February 1, 20214 yr by Luis_ST
February 1, 20214 yr Author 15 minutes ago, diesieben07 said: You can register your own IRecipeType in the same way vanilla does (look at IRecipeType). To use your custom recipe type, you need to also implement IRecipeSerializer and return recipes that use your custom IRecipeType. Okay thanks, but the more important question is how to properly register the container and recipe because that's the reason why i ask? public static final DeferredRegister<ContainerType<?>> CONTAINERS = DeferredRegister.create(ForgeRegistries.CONTAINERS, Cave.Mod_Id); public static final RegistryObject<ContainerType<?>> SMELTING_CONTAINER = CONTAINERS.register("smelting_container", () -> IForgeContainerType.create(null)); and public static final DeferredRegister<IRecipeSerializer<?>> RECIPE_SERIALIZERS = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, Cave.Mod_Id); public static final RegistryObject<IRecipeSerializer<?>> SMELTING_RECIPE = RECIPE_SERIALIZERS.register("smelting_recipe", null);
February 2, 20214 yr Author 15 hours ago, diesieben07 said: What is your question? 18 hours ago, Luis_ST said: 1. registration of container: - i creat a container which extends the vanilla AbstractFurnaceContainer but i cant register the container/ why doesn't work that way and 18 hours ago, Luis_ST said: how to register a custom AbstractCookingRecipe for more information just read my post at the beginning
February 2, 20214 yr Author 32 minutes ago, diesieben07 said: Why can't you? What is your issue? my IDE show this error: "The type SmeltingContainer does not define SmeltingContainer(int, PlayerInventory, PacketBuffer) that is applicable here" this is my container class: https://github.com/Luis-st/Forge-1.16.5-36.0.1-mdk/blob/main/forge-1.16.5-36.0.1-mdk/src/main/java/net/luis/cave/blocks/container/SmeltingContainer.java 38 minutes ago, diesieben07 said: Recipes do not need to be registered. You register a recipe type and a recipe serializer. i mean the recipe serializer this is my registration class: https://github.com/Luis-st/Forge-1.16.5-36.0.1-mdk/blob/main/forge-1.16.5-36.0.1-mdk/src/main/java/net/luis/cave/init/CaveRecipe.java and my recipe serializer class: https://github.com/Luis-st/Forge-1.16.5-36.0.1-mdk/blob/b55bad37a4e156a1cbc7979697809e027e3a4589/forge-1.16.5-36.0.1-mdk/src/main/java/net/luis/cave/blocks/recipes/SmeltingRecipe.java#L12 41 minutes ago, diesieben07 said: Your recipe serializer... like this: public static final RegistryObject<IRecipeSerializer<?>> SMELTING_RECIPE = RECIPE_SERIALIZERS.register("smelting_recipe", SmeltingRecipe::new); but i get the same error: "The type SmeltingRecipe does not define SmeltingRecipe() that is applicable here" So what am I doing wrong / where is the mistake
February 2, 20214 yr Author 1 hour ago, diesieben07 said: You need to provide a method reference or lambda with the correct signature (look at IForgeContainerType.create to find out what is needed). I found. I had to add a Packetbuffer i don't know what i need it for but the container works. 1 hour ago, diesieben07 said: You need to specify your serializer. Your recipe class constructor is not useful here. but how to get the serializer
February 2, 20214 yr Author 23 minutes ago, diesieben07 said: You make a class for it... So do I have to create another class for the serializer even if I already have a recipe class? https://github.com/Luis-st/Forge-1.16.5-36.0.1-mdk/blob/main/forge-1.16.5-36.0.1-mdk/src/main/java/net/luis/cave/blocks/recipes/SmeltingRecipe.java and from which class extends the Serializer? Edited February 2, 20214 yr by Luis_ST
February 2, 20214 yr Author 50 minutes ago, diesieben07 said: Yes you need an IRecipeSerializer. Look at the vanilla examples. have I to implement / extend IRecipeSerializer? now i creat this package net.luis.cave.init; import net.luis.cave.blocks.recipes.SmeltingRecipe; import net.minecraft.item.crafting.CookingRecipeSerializer; import net.minecraft.item.crafting.IRecipeSerializer; public class CaveRecipeSerializer { CookingRecipeSerializer<SmeltingRecipe> CAVE_SMELTING = IRecipeSerializer.register("cave_smelting", new CookingRecipeSerializer<>(SmeltingRecipe::new, 100)); } but i got an error: "The type CookingRecipeSerializer.IFactory<SmeltingRecipe> from the descriptor computed for the target context is not visible here."
February 3, 20214 yr Author 16 hours ago, diesieben07 said: You cannot use CookingRecipeSerialier, because it requires use of a private inner class (IFactory). I found out that I need to create a serializer class in my recipe, but I don't understand what to do in the class, is there a forge documentation or can i copy the read and write methods from the CookingRecipeSerializer when i return my SmeltingRecipe Edited February 3, 20214 yr by Luis_ST
February 3, 20214 yr Author 1 minute ago, diesieben07 said: You can take a look at vanilla for examples. Basically your serializer needs to take the JSON and return the correct recipe instance for it. It also needs to handle serializing to and from PacketBuffer to manage syncing to the client. i currently creat this: 1. is this correct? 2. i have to set the cookingTime but it's a private field so can i create a own one or should i use ObfuscationReflectionHelper to get the field public static class Serializer extends ForgeRegistryEntry<IRecipeSerializer<?>> implements IRecipeSerializer<SmeltingRecipe> { @Override @SuppressWarnings("deprecation") public SmeltingRecipe read(ResourceLocation recipeId, JsonObject json) { String s = JSONUtils.getString(json, "group", ""); JsonElement jsonelement = (JsonElement) (JSONUtils.isJsonArray(json, "ingredient") ? JSONUtils.getJsonArray(json, "ingredient") : JSONUtils.getJsonObject(json, "ingredient")); Ingredient ingredient = Ingredient.deserialize(jsonelement); ItemStack itemstack; if (!json.has("result")) { throw new JsonSyntaxException("Missing result, expected to find a string or object"); } if (json.get("result").isJsonObject()) { itemstack = ShapedRecipe.deserializeItem(JSONUtils.getJsonObject(json, "result")); } else { String s1 = JSONUtils.getString(json, "result"); ResourceLocation resourcelocation = new ResourceLocation(s1); itemstack = new ItemStack(Registry.ITEM.getOptional(resourcelocation).orElseThrow(() -> { return new IllegalStateException("Item: " + s1 + " does not exist"); })); } float f = JSONUtils.getFloat(json, "experience", 0.0F); // int i = JSONUtils.getInt(json, "cookingtime", cookingTime); return new SmeltingRecipe(recipeId, s, ingredient, itemstack, f, 0); } @Override public SmeltingRecipe read(ResourceLocation recipeId, PacketBuffer buffer) { String s = buffer.readString(32767); Ingredient ingredient = Ingredient.read(buffer); ItemStack itemstack = buffer.readItemStack(); float f = buffer.readFloat(); int i = buffer.readVarInt(); return new SmeltingRecipe(recipeId, s, ingredient, itemstack, f, i); } @Override public void write(PacketBuffer buffer, SmeltingRecipe recipe) { buffer.writeString(recipe.group); recipe.ingredient.write(buffer); buffer.writeItemStack(recipe.result); buffer.writeFloat(recipe.experience); buffer.writeVarInt(recipe.cookTime); } }
February 3, 20214 yr Author 39 minutes ago, diesieben07 said: AbstractCookingRecipe#cookTime is protected, however it's also final. But it's set via the constructor, just pass your desired cooking time into the constructor... i just edit the recipe class / serializer class now is this correct? package net.luis.cave.blocks.recipes; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; import net.luis.cave.init.CaveRecipe; import net.luis.cave.init.blocks.CaveBlocks; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.AbstractCookingRecipe; import net.minecraft.item.crafting.IRecipeSerializer; import net.minecraft.item.crafting.IRecipeType; import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.ShapedRecipe; import net.minecraft.network.PacketBuffer; import net.minecraft.util.JSONUtils; import net.minecraft.util.ResourceLocation; import net.minecraft.util.registry.Registry; import net.minecraftforge.registries.ForgeRegistryEntry; public class SmeltingRecipe extends AbstractCookingRecipe { public static int time; @SuppressWarnings("static-access") public SmeltingRecipe(ResourceLocation idIn, String groupIn, Ingredient ingredientIn, ItemStack resultIn, float experienceIn, int cookTimeIn) { super(IRecipeType.register("cave_smelting"), idIn, groupIn, ingredientIn, resultIn, experienceIn, cookTimeIn); this.time = cookTimeIn; } @Override public ItemStack getIcon() { return new ItemStack(CaveBlocks.SMELTING_FURNACE.get()); } @Override public IRecipeSerializer<?> getSerializer() { return CaveRecipe.SMELTING_RECIPE.get(); } public static class Serializer extends ForgeRegistryEntry<IRecipeSerializer<?>> implements IRecipeSerializer<SmeltingRecipe> { @Override @SuppressWarnings("deprecation") public SmeltingRecipe read(ResourceLocation recipeId, JsonObject json) { String s = JSONUtils.getString(json, "group", ""); JsonElement jsonelement = (JsonElement) (JSONUtils.isJsonArray(json, "ingredient") ? JSONUtils.getJsonArray(json, "ingredient") : JSONUtils.getJsonObject(json, "ingredient")); Ingredient ingredient = Ingredient.deserialize(jsonelement); ItemStack itemstack; if (!json.has("result")) { throw new JsonSyntaxException("Missing result, expected to find a string or object"); } if (json.get("result").isJsonObject()) { itemstack = ShapedRecipe.deserializeItem(JSONUtils.getJsonObject(json, "result")); } else { String s1 = JSONUtils.getString(json, "result"); ResourceLocation resourcelocation = new ResourceLocation(s1); itemstack = new ItemStack(Registry.ITEM.getOptional(resourcelocation).orElseThrow(() -> { return new IllegalStateException("Item: " + s1 + " does not exist"); })); } float f = JSONUtils.getFloat(json, "experience", 0.0F); int i = JSONUtils.getInt(json, "cookingtime", SmeltingRecipe.time); return new SmeltingRecipe(recipeId, s, ingredient, itemstack, f, i); } @Override public SmeltingRecipe read(ResourceLocation recipeId, PacketBuffer buffer) { String s = buffer.readString(32767); Ingredient ingredient = Ingredient.read(buffer); ItemStack itemstack = buffer.readItemStack(); float f = buffer.readFloat(); int i = buffer.readVarInt(); return new SmeltingRecipe(recipeId, s, ingredient, itemstack, f, i); } @Override public void write(PacketBuffer buffer, SmeltingRecipe recipe) { buffer.writeString(recipe.group); recipe.ingredient.write(buffer); buffer.writeItemStack(recipe.result); buffer.writeFloat(recipe.experience); buffer.writeVarInt(recipe.cookTime); } } }
February 3, 20214 yr Author 27 minutes ago, diesieben07 said: Looks okay. another question about my container. i can't open it on rightclicked my block but why? Block: https://github.com/Luis-st/Forge-1.16.5-36.0.1-mdk/blob/main/forge-1.16.5-36.0.1-mdk/src/main/java/net/luis/cave/blocks/SmeltingFurnace.java the tile Entity: https://github.com/Luis-st/Forge-1.16.5-36.0.1-mdk/blob/main/forge-1.16.5-36.0.1-mdk/src/main/java/net/luis/cave/blocks/tileentity/SmeltingFurnaceTileEntity.java and my container: https://github.com/Luis-st/Forge-1.16.5-36.0.1-mdk/blob/main/forge-1.16.5-36.0.1-mdk/src/main/java/net/luis/cave/blocks/container/SmeltingContainer.java
February 3, 20214 yr Author 29 minutes ago, diesieben07 said: Use NetworkHooks.openGui. in the tileEntity? I've never used that before a few more information would be helpful Edited February 3, 20214 yr by Luis_ST
February 3, 20214 yr Author 1 hour ago, diesieben07 said: When opening the GUI in your Block. so like this: @Override protected void interactWith(World worldIn, BlockPos pos, PlayerEntity player) { TileEntity tileentity = worldIn.getTileEntity(pos); if (player instanceof ServerPlayerEntity && tileentity instanceof SmeltingFurnaceTileEntity) { NetworkHooks.openGui((ServerPlayerEntity) player, (INamedContainerProvider) tileentity, pos); } }
February 4, 20214 yr Author 14 hours ago, diesieben07 said: Yes I've tested it with the NetworkHooks and the gui still won't open
February 4, 20214 yr Author 1 hour ago, diesieben07 said: You never register your ContainerType, you get a giant error in the console from it, did you not read it? I already registered it but forgot to add the registration to my mod constructor I tested it again and it still doesn't work and the consol show this: [10:19:50] [Render thread/WARN] [minecraft/ScreenManager]: Failed to create screen for menu type: cave:smelting_container I know where the error is coming from I still have to create a screen but where do I have to register / pass the container Edited February 4, 20214 yr by Luis_ST
February 4, 20214 yr Author 49 minutes ago, diesieben07 said: You need to register a screen factory for your container type using ScreenManager.registerFactory in FMLClientSetupEvent with enqueueWork. event.enqueueWork(() -> ScreenManager.registerFactory(CaveContainer.SMELTING_CONTAINER.get(), SmeltingScreen::new)); why does it not work that way (at SmeltingSreen::new) my screen extends the vanilla Furnace screen and the constructor looks like the vanilla one: package net.luis.cave.blocks.container; import net.minecraft.client.gui.screen.inventory.AbstractFurnaceScreen; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @OnlyIn(Dist.CLIENT) public class SmeltingScreen extends AbstractFurnaceScreen<SmeltingContainer> { private static final ResourceLocation FURNACE_GUI_TEXTURES = new ResourceLocation("textures/gui/container/furnace.png"); public SmeltingScreen(SmeltingContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) { super(screenContainer, null, inv, titleIn, FURNACE_GUI_TEXTURES); } } this is the factory: create(T p_create_1_, PlayerInventory p_create_2_, ITextComponent p_create_3_); so i dont understand why my IDE show me an error ("The type SmeltingScreen does not define SmeltingScreen(M, PlayerInventory, ITextComponent) that is applicable here") Edited February 4, 20214 yr by Luis_ST
February 4, 20214 yr Author 14 minutes ago, diesieben07 said: The solution is to declare the type of CaveContainer.SMELTING_CONTAINER properly. What do you mean by "declare correctly" should I replace my container (SmeltingContainer) with generally all Containers (Container class). So what do i have to do. I understand the problem but don't know how to fix it
February 4, 20214 yr Author 2 hours ago, diesieben07 said: Properly means don't use ?, use your container class. okay thanks but now i got an error when i place the block. beacuse i not init my Recipe Serializer so now my question is there a special way to register the serializer or can I use DeferredRegister <IRecipeSerializer <?>>
February 4, 20214 yr Author 1 hour ago, diesieben07 said: IRecipeSerializer extends IForgeRegistryEntry, that means you can use it with DeferredRegister. Everything that implements IForgeRegistryEntry is a normal registry entry and the registration process is the same. i hope these are my last two questions on this topic. So first of all a question about the custom IRecipeType do I have to register this? And secondly how do I tell the recipe book to show my recipes?
February 5, 20214 yr Author 12 hours ago, diesieben07 said: Same as vanilla does. 12 hours ago, diesieben07 said: I don't know. okay thanks unfortunately i still have two problems: 1. when I put items in the slots, close the gui and open it again, the items disappear 2. I added a custom recipe. I can transfer the item into the slot using shift, which means that the recipe works but the smelting process does not start
February 5, 20214 yr Author 1 hour ago, diesieben07 said: Your SmeltingContainer always uses the AbstractFurnaceContainer that is designed for the client side and which will create a temporary inventory. You need to use the constructor that actually takes in the furnace inventory on the server. is the correct one the other constructor from the AbstractFurnaceContainer class? Edited February 5, 20214 yr by Luis_ST
February 5, 20214 yr Author 3 hours ago, diesieben07 said: Yes, the one that takes an inventory. okay i change the constructor but now i have a costructor with: public SmeltingContainer(int id, PlayerInventory playerInventory, IInventory inventory, IIntArray array) { super(ModContainer.SMELTING_CONTAINER.get(), ModRecipeType.SMELTING_RECIPE, RecipeBookCategory.FURNACE, id, playerInventory, inventory, array); } but now i cant register my container type because my constructor contains worng things (IInventory and the IIntArray) so what i have to set there/ did i get this things from the PacketBuffer which i need in the constructor
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.