Posted August 13, 20196 yr Forge version 1.14.4-28.0.45 Context: I'm trying to implement an override for the new vanilla block "Blast Furnace" to make it produce 2 ingots for every supplied ore block. For now I'm trying it out on a separate block but it will in the future override the vanilla block. So far the json file for the recipe has been created: Spoiler { "type": "bettervanilla:blasting", "ingredient": { "item": "minecraft:iron_ore" }, "result": "minecraft:iron_ingot", "count": 2, "experience": 0.7, "cookingtime": 100 } Diff between this and the regular blasting recipe is the type of "bettervanilla:blasting" as well as "count". As far as I've read through the code of vanilla this requires adding a new IRecipeType as one is needed when overriding AbstractCookingRecipe (as the vanilla BlastingRecipe does): Spoiler public AbstractCookingRecipe(IRecipeType<?> typeIn, ResourceLocation idIn, String groupIn, Ingredient ingredientIn, ItemStack resultIn, float experienceIn, int cookTimeIn) { ///... } Issue: I can't seem to figure out how to register a new IRecipeType as I can't subscribe to RegistryEvent<IRecipeType<?>> Spoiler // issue on IRecipeType<?> // "Error:(48, 76) java: type argument net.minecraft.item.crafting.IRecipeType<?> is not within bounds of type-variable T" @SubscribeEvent public static void onRecipeTypeRegistry(final RegistryEvent<IRecipeType<?>> RecipeTypeRegistry) { RecipeTypeRegistry.getRegistry().registerAll( ); } My guess for this issue is that "ForgeRegistries" does not have an "IForgeRegistry<IRecipeType<?>>" variable defined, but I really shouldn't be guessing on this. I messed around with adding a registry for IRecipeType but gave up quickly as I just didn't know what I was doing. It might just be that I'm doing it all backwards. Any help is greatly appreciated, even if it's just a quick slap in the right direction. Thanks! (Will provide more information as quickly as I can if/when asked for.)
August 13, 20196 yr 4 hours ago, DiscardedMarrow said: I can't seem to figure out how to register a new IRecipeType as I can't subscribe to RegistryEvent<IRecipeType<?>> It's not an IRecipeType you need to register it's an IRecipeSerializer. VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 13, 20196 yr Here's an example: https://github.com/Draco18s/ReasonableRealism/blob/1.14.4/src/main/java/com/draco18s/hardlib/api/recipe/RecipeTagOutput.java#L180 https://github.com/Draco18s/ReasonableRealism/blob/1.14.4/src/main/java/com/draco18s/hardlib/EasyRegistry.java#L182 Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
August 13, 20196 yr Author I registered a RecipeSerializer before posting, which in hindsight i should've mentioned. Spoiler //setRegistryName("bettervanilla","blasting"); is called within the constructor for BlastingRecipeSerializer public static final IRecipeSerializer<BlastingRecipe> BETTERBLASTINGRECIPE = new BlastingRecipeSerializer<>(BlastingRecipe::new,100); @SubscribeEvent public static void onRecipeSerializerRegistry(final RegistryEvent.Register<IRecipeSerializer<?>> RecipesSerializerRegistry) { RecipesSerializerRegistry.getRegistry().registerAll( BETTERBLASTINGRECIPE ); } I also wasn't fully clear on that I'm trying to EXTEND AbstractCookingRecipe which requires an IRecipeType to be sent from the new constructor (in BlastingRecipe) via the super constructor for AbstractCookingRecipe. Spoiler public class BlastingRecipe extends AbstractCookingRecipe { ///... public BlastingRecipe(ResourceLocation idIn, String groupIn, Ingredient ingredientIn, ItemStack resultIn, float experienceIn, int cookTimeIn, int countIn) { super( /*IRecipeType<?> typeIn*/ , idIn, groupIn, ingredientIn, resultIn, experienceIn, cookTimeIn); ///... } So what I'm reading from your responses is basically that there's no point to extending AbstractCookingRecipe and instead, BlastingRecipe should just implement "IRecipe<IInventory>"?
August 13, 20196 yr 14 hours ago, DiscardedMarrow said: I'm trying to implement an override for the new vanilla block "Blast Furnace" to make it produce 2 ingots for every supplied ore block. If this is your end goal. Just create an IRecipeSerializer that outputs a BlastingRecipe and register it. Then using its registry name in a recipe file(json) make the recipe you want iron_ore --> iron_ingotx2. And I think you'll want it to be data.minecraft.recipes.iron_ingot_from_blasting.json VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 13, 20196 yr Author 5 minutes ago, Animefan8888 said: Just create an IRecipeSerializer that outputs a BlastingRecipe and register it. That's what I've done yes, which isn't the issue. The issue is: 14 minutes ago, DiscardedMarrow said: I'm trying to EXTEND AbstractCookingRecipe which requires an IRecipeType to be sent from the new constructor (in BlastingRecipe) via the super constructor for AbstractCookingRecipe. And there doesn't seem to be a way to create new instances or extended instances of IRecipeType. Basically if I can't send the super I can't create an instance of BlastingRecipe which in turn means I can't instanciate BlastingRecipeSerializer. This is just telling me to avoid extending AbstractCookingRecipe so I'll try that and see where it takes me.
August 13, 20196 yr 8 minutes ago, DiscardedMarrow said: This is just telling me to avoid extending AbstractCookingRecipe so I'll try that and see where it takes me. You don't need to do this at all. 9 minutes ago, DiscardedMarrow said: I can't instanciate BlastingRecipeSerializer. Why would you want to do that in the first place. Make your own serializer and copy the relevant code. 10 minutes ago, DiscardedMarrow said: I can't create an instance of BlastingRecipe The BlastingRecipe constructor is public you can instantiate one. new BlastingRecipe(...) VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 13, 20196 yr Author 9 minutes ago, Animefan8888 said: 21 minutes ago, DiscardedMarrow said: This is just telling me to avoid extending AbstractCookingRecipe so I'll try that and see where it takes me. You don't need to do this at all. I don't know what you're referring to. I don't need to avoid extending it?? 10 minutes ago, Animefan8888 said: 21 minutes ago, DiscardedMarrow said: I can't instanciate BlastingRecipeSerializer. Why would you want to do that in the first place. Make your own serializer and copy the relevant code So I can register it?? Spoiler 36 minutes ago, DiscardedMarrow said: I registered a RecipeSerializer before posting, which in hindsight i should've mentioned. Reveal hidden contents //setRegistryName("bettervanilla","blasting"); is called within the constructor for BlastingRecipeSerializer public static final IRecipeSerializer<BlastingRecipe> BETTERBLASTINGRECIPE = new BlastingRecipeSerializer<>(BlastingRecipe::new,100); @SubscribeEvent public static void onRecipeSerializerRegistry(final RegistryEvent.Register<IRecipeSerializer<?>> RecipesSerializerRegistry) { RecipesSerializerRegistry.getRegistry().registerAll( BETTERBLASTINGRECIPE ); } I also wasn't fully clear on that I'm trying to EXTEND AbstractCookingRecipe which requires an IRecipeType to be sent from the new constructor (in BlastingRecipe) via the super constructor for AbstractCookingRecipe. Reveal hidden contents public class BlastingRecipe extends AbstractCookingRecipe { ///... public BlastingRecipe(ResourceLocation idIn, String groupIn, Ingredient ingredientIn, ItemStack resultIn, float experienceIn, int cookTimeIn, int countIn) { super( /*IRecipeType<?> typeIn*/ , idIn, groupIn, ingredientIn, resultIn, experienceIn, cookTimeIn); ///... } So what I'm reading from your responses is basically that there's no point to extending AbstractCookingRecipe and instead, BlastingRecipe should just implement "IRecipe<IInventory>"?
August 13, 20196 yr Author Let me make it clear (because it's not obvious) that the BlastingRecipe class I'm referring to does NOT belong to vanilla, it is custom. I'm trying to create a replacement for the vanilla BlastingRecipe class.
August 13, 20196 yr Author Instead of extending AbstractCookingRecipe I now implement IRecipe<IInventory> but I still need to send back an IRecipeType<?> due to the implemented method "IRecipeType<?> getType()" Spoiler ///... /** Should look like {@link net.minecraft.item.crafting.AbstractCookingRecipe} **/ public class BlastingRecipe implements IRecipe<IInventory> { public final ResourceLocation id; public final String group; public final Ingredient ingredient; public final ItemStack result; public final float experience; public final int cookTime; public final int count; public BlastingRecipe(ResourceLocation idIn, String groupIn, Ingredient ingredientIn, ItemStack resultIn, float experienceIn, int cookTimeIn, int countIn) { this.id = idIn; this.group = groupIn; this.ingredient = ingredientIn; this.result = resultIn; this.experience = experienceIn; this.cookTime = cookTimeIn; this.count = countIn; } public boolean matches(IInventory inv, World worldIn) { return this.ingredient.test(inv.getStackInSlot(0)); } public ItemStack getCraftingResult(IInventory inv) { return this.result.copy(); } /** * Used to determine if this recipe can fit in a grid of the given width/height */ public boolean canFit(int width, int height) { return true; } public NonNullList<Ingredient> getIngredients() { NonNullList<Ingredient> nonnulllist = NonNullList.create(); nonnulllist.add(this.ingredient); return nonnulllist; } /** * Gets the experience of this recipe */ public float getExperience() { return this.experience; } /** * Get the result of this recipe, usually for display purposes (e.g. recipe book). If your recipe has more than one * possible result (e.g. it's dynamic and depends on its inputs), then return an empty stack. */ public ItemStack getRecipeOutput() { return this.result; } /** * Recipes with equal group are combined into one button in the recipe book */ public String getGroup() { return this.group; } /** * Gets the cook time in ticks */ public int getCookTime() { return this.cookTime; } public ResourceLocation getId() { return this.id; } public int getCount() { return count; } @Override public IRecipeSerializer<?> getSerializer() { return MiscInit.BETTERBLASTINGRECIPE; } //This is passed as null for now since I don't know what to pass which obviously gives me a NullPointerException public IRecipeType<?> getType() { return null; } } I get a NullPointerException as I don't know what to pass through getType() (using any of the vanilla recipe types obv wouldnt work so i should pass a type for my recipe) but what it says is kind of interesting: Caused by: java.lang.NullPointerException: null key in entry: null={bettervanilla:iron_ingot_from_blasting=chokemonster.bettervanilla.recipes.BlastingRecipe@37d5d3647} It seems to be understanding that the recipe is there at least but I don't know what else to make out of this error. Here's my code for the BlastingRecipeSerializer if it helps shed some light on the situation: Spoiler ///... public class BlastingRecipeSerializer<T extends BlastingRecipe> extends net.minecraftforge.registries.ForgeRegistryEntry<IRecipeSerializer<?>> implements IRecipeSerializer<T> { private final int cookingTime; private final BlastingRecipeSerializer.IFactory<T> iBlastRecipeFactory; public BlastingRecipeSerializer(BlastingRecipeSerializer.IFactory<T> factoryIn, int cookingTimeIn) { this.cookingTime = cookingTimeIn; this.iBlastRecipeFactory = factoryIn; setRegistryName("bettervanilla","betterblasting"); } //The reads and writes will be cleaned up when I'm done with this issue public T 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); //Forge: Check if primitive string to keep vanilla or a object which can contain a count field. if (!json.has("result")) throw new com.google.gson.JsonSyntaxException("Missing result, expected to find a string or object"); ItemStack itemstack; 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(ForgeRegistries.ITEMS.getValue(resourcelocation)); } float experience = JSONUtils.getFloat(json, "experience", 0.0F); int cookingTime = JSONUtils.getInt(json, "cookingtime", this.cookingTime); int count = JSONUtils.getInt(json, "count", 1); return this.iBlastRecipeFactory.create(recipeId, s, ingredient, itemstack, experience, cookingTime, count); } public T 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(); int count = buffer.readVarInt(); return this.iBlastRecipeFactory.create(recipeId, s, ingredient, itemstack, f, i, count); } public void write(PacketBuffer buffer, T recipe) { buffer.writeString(recipe.group); recipe.ingredient.write(buffer); buffer.writeItemStack(recipe.result); buffer.writeFloat(recipe.experience); buffer.writeVarInt(recipe.cookTime); buffer.writeVarInt(recipe.count); } public interface IFactory<T extends BlastingRecipe> { T create(ResourceLocation resourceLocation, String s, Ingredient ingredient, ItemStack itemStack, float experience, int cookingTime, int count); } } I've also read through the Docs for 1.13 regarding the _factories file hoping it might be necessary in some way I haven't understood yet so if it might be linked to the issue I would love to know how, or even get a clear description on how or where it should be used. Thanks.
August 13, 20196 yr Look at existing usages? ICraftingRecipe is as far back as you should really go, which returns IRecipeType.CRAFTING from getType, distinguishing it from SMELTING, BLASTING, SMOKING, CAMPFIRE_COOKING, and STONECUTTING. Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
August 13, 20196 yr Author 4 minutes ago, Draco18s said: Look at existing usages? Yeah I've looked around a lot and even tried just outright returning IRecipeType.CRAFTING from my recipe just to see if I got any errors that would feed me some information but no luck. I'll look around some more though, specifically at ICraftingRecipe, and see if anything clicks. Thanks Draco.
August 14, 20196 yr 2 hours ago, DiscardedMarrow said: Yeah I've looked around a lot and even tried just outright returning IRecipeType.CRAFTING from my recipe just to see if I got any errors that would feed me some information but no luck. I'll look around some more though, specifically at ICraftingRecipe, and see if anything clicks. Thanks Draco. If you want it to be for the Blast Furnace you probably need to return the BLASTING type instead of the CRAFTING type. VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 14, 20196 yr Author So. I made it work using IRecipeType.BLASTING and I wish I could explain it better but it's 03:23 AM and I need rest. However, I have a public git repo if anyone finds this and is curious how I did it (or wants to yell at me for doing it wrong). https://github.com/kimcodekill/BetterVanilla Thanks for your help @Draco18s & @Animefan8888
August 14, 20196 yr 3 minutes ago, DiscardedMarrow said: (or wants to yell at me for doing it wrong). This is my time to shine lol. It would make more sense for the result to be a Json Object and also contain the count tag. Why does this class even exist? You can access all the fields in the BlastingRecipe vanilla provides with its getters. That's all I really have to say. But i could also ask why you are using an IFactory to create your BlastingRecipes instead of just calling the constructor, but it seems Vanilla has them too. VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 14, 20196 yr Author 4 minutes ago, Animefan8888 said: It would make more sense for the result to be a Json Object and also contain the count tag. Very true, I'll do this for next version. 4 minutes ago, Animefan8888 said: Why does this class even exist? You can access all the fields in the BlastingRecipe vanilla provides with its getters. I used the count in this class earlier, so I agree. It's obsolete and I'll look at it for next version. 6 minutes ago, Animefan8888 said: But i could also ask why you are using an IFactory to create your BlastingRecipes instead of just calling the constructor, but it seems Vanilla has them too. Yeah I felt safer doing it like this for now because vanilla does it and I saw another post on the forums where they used an IFactory. I agree though it would be a lot simpler if I just used 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.