#Editing the json object of a recipe in a forEach loop

34 messages · Page 1 of 1 (latest)

primal raptor
#

Hi, I have some recipe types that replaceInput doesn't work on. I'm trying to make my own function to imitate it. Although I know how to get the contents of a JSON recipe object, I'm not sure how to set them. In their definition, they look like theyre the immutable JsonObject. I could build a new one as a copy in Java, but I'm not sure how to do so in JavaScript.
https://docs.oracle.com/javaee/7/api/javax/json/JsonObject.html
https://github1s.com/KubeJS-Mods/KubeJS/blob/2001/common/src/main/java/dev/latvian/mods/kubejs/recipe/RecipeJS.java#L60

When printed to console, they appear to have type HashMap. But neither JavaScript's set or Java's put seem to work.

Here's the code I'm working with:

    let replaceWithTag = (item, tag, recipetype) => {
        event.forEachRecipe( {type: recipetype, input: item}, r => {
            let ingredients = r.json.get("ingredients")
            let newIngredients = Array()

            console.log(r.json)
    
            for (const ingredient of ingredients) {
                if (ingredient.get("item") == item ) {
                    ingredient.delete("item")
                    ingredient.set("tag", tag)
                }
                newIngredients.push(ingredient)
            }

            r.json.set("ingredients", newIngredients) // doesn't work
    
        })
    }```
brisk tapirBOT
#

Once your ticket has been resolved, please close it with </ticket close:1054771505520717835> command!

silent ferry
#

try this:

let replaceWithTag = (item, tag, recipetype) => {
  event.forEachRecipe( {type: recipetype, input: item}, r => {
    const ingredients = r.json.get("ingredients")

    for (let i = 0; i < ingredients.size(); i++) {
      const ingredient = ingredients.get(i);
      if (ingredient.get("item") == item ) {
        ingredient.delete("item")
        ingredient.set("tag", tag)
      }
    }
  })
}
deft dirge
#

i like to use the "JSON.parse" in "forEachRecipe" ```js
let replaceWithTag = (item, tag, recipetype) => {
event.forEachRecipe({ type: recipetype, input: item }, (r) => {
const json = JSON.parse(r.json);
const { ingredients } = json;
const recipeId = r.getId();

  for (const ingredient of ingredients) {
    if (ingredient.item !== item) continue;
    delete ingredient.item;
    ingredient.tag = tag;
  }

  event.custom(json).id(recipeId);
});

};```

silent ferry
#

yes but here you are making a new recipe without even overriding the old one

#

while my solution is more ugly, it modifies the original recipe so that you don't have to remake it

deft dirge
silent ferry
primal raptor
primal raptor
primal raptor
#

yeah @silent ferry your method doesn't seem to work, unfortunately. 3deadto's does though! thank you both!

primal raptor
#

ah wait, there's a bit more complexity here. running 3deadto's method twice for different replacements causes issues. running as-is results in "duplicate recipe id" errors, and adding a line to remove the original recipe by id means that only the last-run replacement is applied (for recipes where multiple replacements apply)

primal raptor
#

an easy fix would be to make the function accept a dictionary of original-replacement pairs, but since i'm unfamiliar with javascript im having a bit of trouble getting it to work. it would also still likely cause issues with further editing such recipes down the line

primal raptor
#

hm.

#

i've discovered something... really strange

#

OH WAIT... it's because of the const keyword

#

because donald's for loop uses the const keyword when defining ingredients, all items are treated as if theyre the first ingredient

#

its scope extends outside a single iteration of the loop

#

unfortunately, modifying the json that way still doesnt seem to be supported

#

but it lets me use for loops instead of foreach loops, which are a bit more stable in the multi-replacement extension im working on

primal raptor
#

okay so. running into some weird problems.

my code is below:

    let replaceWithTag = (replacement_dict, recipetype) => {
        // replacement_dict is an object mapping item -> replacement tag

        let filter = []
        let as_map = new Map(Object.entries(replacement_dict))
        for (const [key, value] of as_map) {
            filter.push({type:recipetype, input: key})
        }

        console.log(filter)

        event.forEachRecipe(filter, (r) => {
            const json = JSON.parse(r.json);
            const recipeId = r.getId();

            let should_change = false
            
            const ingredients = r.json.get("ingredients")
            console.log(ingredients)

            if (ingredients != null) {

                for (let i = 0; i < ingredients.size(); i++) {

                    const ingredient = ingredients.get(i)
                    const item = ingredient.get("item");
                    
                    console.log(ingredient)
                    console.log(ingredient.item)
                    console.log(item == null ? "null" : item)
    
                    if (!as_map.has(item)) continue;
                    console.log("REPLACING........................")
    
                    console.log(json)
                    console.log(item);
                    console.log(replacement_dict[item]);
    
                    //delete ingredient.item;
                    //ingredient.tag = replacement_dict[item];
                    //should_change = true
                }
                
                //if (should_change) {
                //    event.custom(json).id(recipeId);
                //}
            }

        });
    };```
#

and here's the relevant part

  for (let i = 0; i < ingredients.size(); i++) {

      const ingredient = ingredients.get(i)
      const item = ingredient.get("item");
      
      console.log(ingredient)
      console.log(ingredient.item)
      console.log(item == null ? "null" : item)

      if (!as_map.has(item)) continue;
      ...
  }
#

first of all, ingredient.item is always undefined, which is very weird.

#

secondly, if ingredient and item are const, then it gets "stuck" on the first ingredient. output looks like this:

[{"item":"brewinandchewin:flaxen_cheese_wedge"}, {"item":"farmersdelight:raw_pasta"}, {"item":"farmersdelight:tomato"}, {"tag":"c:crops/cabbage"}] [java.util.ArrayList]

{item="brewinandchewin:flaxen_cheese_wedge"} [java.util.HashMap]
undefined
brewinandchewin:flaxen_cheese_wedge
{item="brewinandchewin:flaxen_cheese_wedge"} [java.util.HashMap]
undefined
brewinandchewin:flaxen_cheese_wedge
{item="brewinandchewin:flaxen_cheese_wedge"} [java.util.HashMap]
undefined
brewinandchewin:flaxen_cheese_wedge
{item="brewinandchewin:flaxen_cheese_wedge"} [java.util.HashMap]
undefined
brewinandchewin:flaxen_cheese_wedge```
#

it doesnt seem to be able to update ingredient, despite it being declared inside the loop

#

but if change const to let, i get this error on the line defining item

#

it's like once it changes to let, it thinks ingredients is an array and not a dictionary

#

it's really weird!! as far as i can tell, neither of these things should be possible in javascript???

#

a const variable should be reset every iteration of a for loop, and changing const to let shouldnt change the assumed type

deft dirge
primal raptor
#

very strange...

primal raptor