Just Enough Items (JEI)

Just Enough Items (JEI)

464M Downloads

[Bug]: JEI Assumes All Potion Types Have One Recipe

voidsong-dragonfly opened this issue ยท 1 comments

commented

Steps to Reproduce the Bug

  1. Clone Natural Philosophy (found here)
  2. Run ./gradlew runClient
  3. Check JEI for recipes for the Water Breathing potion, only Pufferfish will be shown as an ingredient.

Expected Behavior

The recipe using Red Algae from Natural Philosophy to craft Water Breathing potions should also be shown in JEI, alongside the Pufferfish recipe.

Actual Behavior

Only one (the first registered) ingredient for a potion type will be shown in JEI, instead of all reagents for a specific potion type.

Mod Pack URL (Optional)

No response

Mod Pack Version (Optional)

No response

Extra Notes (Optional)

Bug is present in both 19.21.0.247 and 19.21.2.313 versions of JEI on NeoForge.

latest.log

https://gist.github.com/voidsong-dragonfly/a653d59384638563374fc91cf514e9b4

commented

I believe this is caused by an assumption in BrewingRecipeMakerCommon::getNewPotions's construction of the uid passed into createBrewingRecipe. It appears to be an issue in both 1.21.1 and 1.21.7's code bases, and presumably all versions between them. Likewise, it also seems to appear in the 1.20.1 branch.

Simply put:

String inputPathId = PotionSubtypeInterpreter.INSTANCE.getStringName(potionInput);
...
String outputPathId = PotionSubtypeInterpreter.INSTANCE.getStringName(potionOutput);
String outputModId = outputResourceLocation.getNamespace();
String uidPath = ResourceLocationUtil.sanitizePath(inputPathId + ".to." + outputPathId);

The inputPathId and outputPathId are combined on BrewingRecipeMakerCommon::150 (around 129 in 1.21.1) to create a resource location which is later used by (at least on 1.21.1) JeiBrewingRecipe as the hash code for the recipe.

This means that adding additional recipes for Vanilla potions, or additional reagents, will properly construct those recipes but with a hash that only considers the input item and the output item, not any of the ingredients.

The !recipes.contains(recipe) check at BrewRecipeMakerCommon::152 then fails, which means the recipe is then discarded.

Interestingly enough, at least with JeiBrewingRecipe on 1.21.1, this would be properly handled if the uid was not passed in to the createBrewingRecipe, which would result in a null uid:

		if (uid != null) {
			this.hashCode = uid.hashCode();
		} else {
			this.hashCode = Objects.hash(
				ingredients.stream().map(ItemStack::getItem).toList(),
				potionInputs.stream().map(ItemStack::getItem).toList(),
				potionOutput.getItem()
			);
		}

Potential fix

A potential solution for this would be to modify line BrewingRecipeMakerCommon::145 to include the ingredient as an determiner in the uidPath:

String ingredientResourceLocation = itemStackHelper.getResourceLocation(potionReagent);
String uidPath = ResourceLocationUtil.sanitizePath(
	inputPathId + 
	".to." + 
	outputPathId + 
	".with." +
	ResourceLocationUtil.sanitizePath(ingredientResourceLocation)
);

This would allow JEI to automatically show all recipes which use the same inputs and outputs but different ingredients to create potions.

I'm not sure what the ordering is like, but it might also be theoretically possible for certain modded recipes to supplant Vanilla recipes with the current code, if they are processed first and then the Vanilla recipe conflicts at a later point in processing knownPotions.

Alternately, it might make more sense to detect the pre-existing recipe and merge the ingredients from that along with the ingredients from the "duplicate" into a new recipe. I'm not sure of the best approach for a PR.

EDIT: Further consideration would need to be made for any mods that have explicitly encountered this bug and manually added their own recipes via a plug-in.