KubeJS

KubeJS

61M Downloads

Values conversion problem from RecipeComponents

pietro-lopes opened this issue ยท 4 comments

commented

Minecraft Version

1.20.1

KubeJS Version

latest

Rhino Version

latest

Architectury Version

latest

Forge/Fabric Version

Forge 47.1.3

Describe your issue

When we set an optional value to a RecipeKey and attach an alwaysWrite() at some point the conversion from Double (Rhino?) to float fails

Here is a minimal setup for debugging purposes
at startup_scripts:

// priority: 0

const $RecipeSchema = Java.loadClass("dev.latvian.mods.kubejs.recipe.schema.RecipeSchema")
const $CookingRecipeSchema = Java.loadClass("dev.latvian.mods.kubejs.recipe.schema.minecraft.CookingRecipeSchema")
const $NumberComponent = Java.loadClass("dev.latvian.mods.kubejs.recipe.component.NumberComponent")

StartupEvents.recipeSchemaRegistry((event) => {

  const XP = $NumberComponent.FLOAT.key("experience").optional(0.1).preferred("xp").alwaysWrite();

  const buggedCookingSchema = new $RecipeSchema($CookingRecipeSchema.RESULT, $CookingRecipeSchema.INGREDIENT, XP, $CookingRecipeSchema.COOKING_TIME).uniqueOutputId($CookingRecipeSchema.RESULT)
  event.namespace("minecraft").register("campfire_cooking", buggedCookingSchema)
})

at server_scripts:

// priority: 0

ServerEvents.recipes(event => {
  event.recipes.minecraft.campfire_cooking("cooked_beef", "rabbit").id("minecraft:bugged_schema")
  // event.recipes.minecraft.campfire_cooking("cooked_beef", "rabbit", 0.1).id("minecraft:bugged_schema") // <- this works without any issue
})
[05:06:37] [WARN] Error parsing recipe minecraft:bugged_schema[minecraft:campfire_cooking]: {"type":"unknown","result":{"item":"minecraft:cooked_beef","count":1},"ingredient":{"item":"minecraft:rabbit"}}: java.lang.ClassCastException: class java.lang.Double cannot be cast to class java.lang.Float (java.lang.Double and java.lang.Float are in module java.base of loader 'bootstrap')

Crash report/logs

No response

commented

Is using this from scripts even a supported usecase ๐Ÿค”

commented

Is using this from scripts even a supported usecase ๐Ÿค”

Now you got me lol
99dad81 - does this commit means something about support being intended? looks like a problem with typewrapping, so ๐Ÿค”

Anyway, so far I'm accomplishing a lot using scripting only.
I wish we had a real component builder that I could define better the behavior of the components, like read/write/class/how to replaceInputOutput etc...

I also found a problem where I use replaceInput/Output, it successfully changes the value of a children component, but it fails to check changes because it compares value by reference (it has a workaround for builderMap with a flag hasChanged but the logic components (or/and) do not have that
So when it fails to check changes, it doesn't call the .write() function and it doesn't update.

commented

Fixed ๐Ÿ™

v.value = UtilsJS.cast(v.key.optional.getDefaultValue(type.schemaType));

- v.value = UtilsJS.cast(v.key.optional.getDefaultValue(type.schemaType));
+ v.value = UtilsJS.cast(v.key.component.read(this, UtilsJS.cast(v.key.optional.getDefaultValue(type.schemaType))));
commented

I also found a problem where I use replaceInput/Output, it successfully changes the value of a children component, but it fails to check changes because it compares value by reference (it has a workaround for builderMap with a flag hasChanged but the logic components (or/and) do not have that So when it fails to check changes, it doesn't call the .write() function and it doesn't update.

Managed to fix this too here
https://github.com/KubeJS-Mods/KubeJS/blob/2002/common/src/main/java/dev/latvian/mods/kubejs/recipe/component/OrRecipeComponent.java

(I only made it work, please refactor or make it look better/safer ๐Ÿ˜จ )

	@Override
	public boolean checkValueHasChanged(Either<H, L> oldValue, Either<H, L> newValue) {
		if (oldValue == null || newValue == null) return RecipeComponent.super.checkValueHasChanged(oldValue, newValue);
		var left = oldValue.left();
		if (left.isPresent()) {
			var h = high.checkValueHasChanged(oldValue.left().get(), newValue.left().get());
			if (h) return true;
		} else {
			var l = low.checkValueHasChanged(oldValue.right().get(), newValue.right().get());
			if (l) return true;
		}
		return RecipeComponent.super.checkValueHasChanged(oldValue, newValue);
	}