Jump to content

[Solved] [1.12] Disable recipes by config (causing crash)?


Recommended Posts

Posted (edited)

I'd like to add some configuration options to my Totem Essentials mod. Specifically, configurable durabilities for my items and the ability to enable or disable each item's crafting recipes as desired. The durability options are working fine, however the recipe toggling is causing the game to crash whenever I open a crafting table. I know I can do this with a recipe factory, but the mod adds quite a few items and I'd rather avoid having to modify *all* their recipe .json files if possible.

 

So, in order to take advantage of iteration (and the fact that I used a standard naming convention for my items and assets from the start), I've been trying to simply iterate over ForgeRegistries.RECIPES and store all my mod's recipes into a map, then remove the registry entries which are disabled by my config (and re-register the ones which have been re-enabled but aren't in the registry anymore, by pulling the IRecipe from the map).

 

Here's the configuration class I was attempting to use:

 

package com.icemetalpunk.totemessentials.config;

import java.util.HashMap;
import java.util.Map.Entry;

import com.icemetalpunk.totemessentials.TotemEssentials;

import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.config.Config;
import net.minecraftforge.common.config.ConfigManager;
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.registries.IForgeRegistryModifiable;

@Config(modid = TotemEssentials.MODID)
@Config.LangKey("totemessentials.config.title")
public class TEConfig {

	private static HashMap<ResourceLocation, IRecipe> recipeMap = new HashMap<>();

	@Config.Name("Recipes")
	@Config.LangKey("totemessentials.config.recipes")
	public static HashMap<String, Boolean> recipeList = new HashMap<>();

	@Config.Name("Normal Durabilities")
	@Config.LangKey("totemessentials.config.durabilityOne")
	public static HashMap<String, Integer> durabilityOneList = new HashMap<>();

	@Config.Name("Ensouled Durabilities")
	@Config.LangKey("totemessentials.config.durabilityTwo")
	public static HashMap<String, Integer> durabilityEnsouledList = new HashMap<>();

	static {
		recipeList.put("Aggression Totem", true);
		recipeList.put("Aiming Totem", true);
		recipeList.put("Curing Totem", true);
		recipeList.put("Daunting Totem", true);
		recipeList.put("Exchange Totem", true);
		recipeList.put("Featherfoot Totem", true);
		recipeList.put("Fireglaze Totem", true);
		recipeList.put("Flamebody Totem", true);
		recipeList.put("Gluttony Totem", true);
		recipeList.put("Phasing Totem", true);
		recipeList.put("Reaping Totem", true);
		recipeList.put("Replication Totem", true);
		recipeList.put("Storage Totem", true);
		recipeList.put("Traveling Totem", true);
		recipeList.put("Vampire Totem", true);
		recipeList.put("Wisdom Totem", true);

		durabilityOneList.put("Aggression Totem", 50);
		durabilityOneList.put("Aiming Totem", 100);
		durabilityOneList.put("Curing Totem", 10);
		durabilityOneList.put("Daunting Totem", 35);
		durabilityOneList.put("Exchange Totem", 25);
		durabilityOneList.put("Featherfoot Totem", 100);
		durabilityOneList.put("Fireglaze Totem", 2);
		durabilityOneList.put("Flamebody Totem", 100);
		durabilityOneList.put("Gluttony Totem", 100);
		durabilityOneList.put("Phasing Totem", 600);
		durabilityOneList.put("Reaping Totem", 8);
		durabilityOneList.put("Replication Totem", 50);
		durabilityOneList.put("Traveling Totem", 250);
		durabilityOneList.put("Vampire Totem", 40);
		durabilityOneList.put("Wisdom Totem", 750);

		durabilityEnsouledList.put("Ensouled Aggression Totem", 150);
		durabilityEnsouledList.put("Ensouled Aiming Totem", 200);
		durabilityEnsouledList.put("Ensouled Curing Totem", 30);
		durabilityEnsouledList.put("Ensouled Daunting Totem", 75);
		durabilityEnsouledList.put("Ensouled Exchange Totem", 50);
		durabilityEnsouledList.put("Ensouled Featherfoot Totem", 200);
		durabilityEnsouledList.put("Ensouled Fireglaze Totem", 60000);
		durabilityEnsouledList.put("Ensouled Flamebody Totem", 200);
		durabilityEnsouledList.put("Ensouled Gluttony Totem", 500);
		durabilityEnsouledList.put("Ensouled Phasing Totem", 1200);
		durabilityEnsouledList.put("Ensouled Reaping Totem", 40);
		durabilityEnsouledList.put("Ensouled Replication Totem", 75);
		durabilityEnsouledList.put("Ensouled Traveling Totem", 500);
		durabilityEnsouledList.put("Ensouled Undying Totem", 10);
		durabilityEnsouledList.put("Ensouled Vampire Totem", 40);
		durabilityEnsouledList.put("Ensouled Wisdom Totem", 1500);

	}

	@Mod.EventBusSubscriber(modid = TotemEssentials.MODID)
	private static class ConfigEventHandler {
		@SubscribeEvent
		public static void onConfigChanged(final ConfigChangedEvent.OnConfigChangedEvent ev) {
			if (ev.getModID().equals(TotemEssentials.MODID)) {
				ConfigManager.sync(TotemEssentials.MODID, Config.Type.INSTANCE);
				UpdateDurabilities();
				UpdateRecipesEnabled();
			}
		}
	}

	public static void PopulateRecipeMap() {
		recipeMap.clear();
		IForgeRegistryModifiable<IRecipe> reg = (IForgeRegistryModifiable<IRecipe>) ForgeRegistries.RECIPES;
		for (Entry<ResourceLocation, IRecipe> entry : reg.getEntries()) {
			ResourceLocation loc = entry.getKey();
			if (loc.getResourceDomain().equals(TotemEssentials.MODID)) {
				recipeMap.put(loc, entry.getValue());
			}
		}
	}

	public static void UpdateRecipesEnabled() {
		IForgeRegistryModifiable<IRecipe> reg = (IForgeRegistryModifiable<IRecipe>) ForgeRegistries.RECIPES;
		for (Entry<String, Boolean> entry : recipeList.entrySet()) {
			String name = entry.getKey();
			name = name.toLowerCase().replaceAll(" ", "_");
			ResourceLocation loc = new ResourceLocation(TotemEssentials.MODID, name);
			if (reg.containsKey(loc) && !entry.getValue()) {
				reg.remove(loc);
			} else if (!reg.containsKey(loc) && entry.getValue()) {
				IRecipe fromMap = recipeMap.get(loc);
				reg.register(fromMap);
			}
		}
	}

	public static void UpdateDurabilities() {
		String key = "";
		int val = 0;
		for (Entry<String, Integer> entry : durabilityOneList.entrySet()) {
			key = entry.getKey();
			val = entry.getValue();
			TotemEssentials.proxy.items.get(key.toLowerCase().replaceAll(" ", "_")).setMaxDamage(val);
		}
		for (Entry<String, Integer> entry : durabilityEnsouledList.entrySet()) {
			key = entry.getKey();
			val = entry.getValue();
			TotemEssentials.proxy.items.get(key.toLowerCase().replaceAll(" ", "_")).setMaxDamage(val);
		}
	}
}

 

I'm calling PopulateRecipeMap(), UpdateDurabilities(), and UpdateRecipesEnabled() from my common proxy's Init event handler (in that order).

Whenever I open a crafting table, the game crashes, reporting an NPE; basically, it's saying that GuiButtonRecipe's recipe list is null when it tries to draw it.

The crash occurs only if the game was loaded with a recipe disabled. If it was loaded with all recipes enabled, then it can open the crafting table and recipe book just fine. And if I then disable a recipe, it works perfectly and is removed from the recipe book as expected. If I load the game with a recipe disabled and then re-enable it, opening the crafting table still causes a crash.

In other words: regardless of whether any recipes are currently disabled or not, if the game was loaded with a recipe disabled, opening a crafting table crashes the game; if it wasn't loaded with a recipe disabled, then it works perfectly even when a recipe is disabled later.

I've tried moving the initial PopulateRecipeMap(), etc. calls from the Init event to the Post-Init event, suspecting some sort of race condition with the default recipe loader, but it didn't change anything.

So how can I go about making my recipes able to be disabled and re-enabled via config, without changing all the recipe files?

Edited by IceMetalPunk

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted

*Sigh* So I guess I will have to go ahead and change all my recipe .json files, then? Welp, time to automate this insertion xD I'll post here about how it goes. Thank.

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted (edited)

Okay, so I've gone ahead and made the recipe factory, wrote a little script to insert the condition into all my recipe files, etc. It almost works. If the game loads with a recipe disabled, it'll be disabled just fine. If the game loads with a recipe enabled, it'll be enabled just fine. The problem is that if the player changes the config in-game, the recipe status won't change until the game is reloaded.

 

Is there a way to re-check the conditions when the config changes? (I think I could call CraftingHelper.loadRecipes() again, maybe, but even if I can, that loads the recipes for all mods, and that feels very dangerous to do.)

Edited by IceMetalPunk

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted

Oh. Well, okay, then... I guess I'll just let people know they need to restart the game after changing those config options. Thanks for your help.

Would it be okay if I asked for your help in another topic, related to this one (about config setup)? I don't want to link to another topic of mine if that's not considered acceptable around here.

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted
Just now, diesieben07 said:

I am not sure I understand. Feel free to open another topic if you have another question.

I already opened the other topic, but it's gone a week with no replies. I was asking if it's okay to link to that here and ask you (and anyone reading this) to take a look? I know in some communities, that's considered bumping/self-promotion/rude, but in others it's okay, so that's why I wanted to ask before I link to it here.

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted

Thank you; I'll update that topic now (is it okay to bump it, or should I leave on the N'th page and just edit the first post?).

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted

Thank you. I've been around some communities where if you post anything in a topic past a certain time, it's considered "necroposting" and bumping, regardless of the content. Glad to know things are a little more lenient around these parts :) Thanks for all your help :)

Whatever Minecraft needs, it is most likely not yet another tool tier.

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.