#HashTable help: Starter template for Botany Pots in 1.20?

81 messages · Page 1 of 1 (latest)

ancient robin
#

Title.

Does anyone have a starter template for Botany Pots in 1.20?

warped cloudBOT
#

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

ancient robin
#

i got a template, but now i'm having JS errors, because i'm trying a new approach (for the time being)

#

HashTable help: Starter template for Botany Pots in 1.20?

#
ServerEvents.recipes((event) => {
  const sushigo = new HashTable(
    "sushigocrafting:rice",
    ["sushigocrafting:rice_seeds"],
    "sushigocrafting:cucumber",
    ["sushigocrafting:cucumber_seeds"],
    "sushigocrafting:soy_bean",
    ["sushigocrafting:soy_seeds"],
    "sushigocrafting:wasabi_root",
    ["sushigocrafting:wasabi_seeds"],
    "sushigocrafting:sesame_seed",
    ["sushigocrafting:sesame_seeds"]
  );
  // const sushiseeds = Ingredient.of(/sushigocrafting:.*_seeds/).itemIds
  // const crop = s.split(':')
  sushigo.forEach((k, v) => {
    event.custom({
      type: "botanypots:crop",
      seed: {
        item: v,
      },
      categories: ["dirt", "farmland"],
      growthTicks: 1200,
      display: {
        type: "botanypots:aging",
        block: k,
      },
      drops: [
        {
          chance: 1.0,
          output: {
            item: k,
          },
          minRolls: 1,
          maxRols: 2,
        },
        {
          chance: 0.15,
          output: {
            item: k,
          },
          minRolls: 1,
          maxRols: 2,
        },
      ],
    });
  });
});

new error:
[08:32:23] [ERROR] ! mods/botanypots/botanypots.js#5: Error occurred while handling event 'ServerEvents.recipes': ReferenceError: "HashTable" is not defined.

#

flipped the hashtable to map and now i'm getting an expected object but got string. is hastable not exposed in kubejs?

#

ah, new error: [08:43:30] [WARN] Error parsing recipe botanypots:kjs_1thiphdfpatx18m9gnexy2tqd[botanypots:crop]: {"type":"botanypots:crop","seed":{"item":"sushigocrafting:rice"},"categories":["dirt","farmland"],"growthTicks":1200,"display":{"type":"botanypots:aging","block":"sushigocrafting:rice_seeds"},"drops":[{"chance":1,"output":{"item":"sushigocrafting:rice_seeds"},"minRolls":1,"maxRols":2},{"chance":0.15,"output":{"item":"sushigocrafting:rice_seeds"},"minRolls":1,"maxRols":2}]}: com.google.gson.JsonParseException: ID 'sushigocrafting:rice_seeds' has not been registered

#

oh lol, i have this backwards

#

[08:47:33] [WARN] Error parsing recipe botanypots:kjs_6n3fj58iy03emlcpbkwt08dbv[botanypots:crop]: {"type":"botanypots:crop","seed":{"item":"sushigocrafting:rice_seeds"},"categories":["dirt","farmland"],"growthTicks":1200,"display":{"type":"botanypots:aging","block":"sushigocrafting:rice"},"drops":[{"chance":1,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRols":2},{"chance":0.15,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRols":2}]}: com.google.gson.JsonParseException: ID 'sushigocrafting:rice' has not been registered

thinking2

i need to step away for work. if i can get some assistance in what i am missing, not necessarily a fix, but just a pointer of what i should look fo, that would be grately appreciated.

#

the seeds are all registered with forge:seeds btw.

#

i might just try and use the forge seed variant instead.

#

but after i get done with work since i have to drive all around town

ancient robin
#

[20:10:10] [WARN] Error parsing recipe botanypots:kjs_ifpx88q9lb5l3c1ge0vkyexo[botanypots:crop]: {"type":"botanypots:crop","seed":{"item":"forge:seeds/rice_seeds"},"categories":["dirt","farmland"],"growthTicks":1200,"display":{"type":"botanypots:aging","block":"sushigocrafting:rice"},"drops":[{"chance":1,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRols":2},{"chance":0.15,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRols":2}]}: com.google.gson.JsonSyntaxException: Unknown item 'forge:seeds/rice_seeds'

headdesk

ancient robin
#

also, i realized that the rice seed should be planted on water, but i'll take care of that when i can get this custom recipe working.

jade warren
#

Replace your
{item: v} at the top with
Ingredient.of(v).toJson()

#

And If you want to use a Tag add the # Infront

#

This is because If you want to use a Tag you need to modify the json Key aswell

ancient robin
#
ServerEvents.recipes((event) => {
  const sushigo = new Map();
  sushigo.set("sushigocrafting:rice", "sushigocrafting:rice_seeds");
  sushigo.set("sushigocrafting:cucumber", "sushigocrafting:cucumber_seeds");
  sushigo.set("sushigocrafting:soy_bean", "sushigocrafting:soy_seeds");
  sushigo.set("sushigocrafting:wasabi_root", "sushigocrafting:wasabi_seeds");
  sushigo.set("sushigocrafting:sesame_seed", "sushigocrafting:sesame_seeds");
  sushigo.forEach((k, v) => {
    event.custom({
      type: "botanypots:crop",
      seed: {
        item: k,
      },
      categories: ["dirt", "farmland"],
      growthTicks: 1200,
      display: {
        type: "botanypots:aging",
        block: v,
      },
      drops: [
        {
          chance: 1.0,
          output: {
            item: v,
          },
          minRolls: 1,
          maxRols: 2,
        },
        {
          chance: 0.15,
          output: {
            item: v,
          },
          minRolls: 1,
          maxRols: 2,
        },
      ],
    });
  });
});

you're saying change item: k to item: Ingredient.of(k).toJson()?

#

[07:16:51] [WARN] Error parsing recipe botanypots:kjs_bscaqg7qb711mvct26vqo83pd[botanypots:crop]: {"type":"botanypots:crop","seed":{"item":{"item":"sushigocrafting:rice_seeds"}},"categories":["dirt","farmland"],"growthTicks":1200,"display":{"type":"botanypots:aging","block":"sushigocrafting:rice"},"drops":[{"chance":1,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRols":2},{"chance":0.15,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRols":2}]}: com.google.gson.JsonSyntaxException: Expected item to be a string, was an object ({"it...s"})

heh

#

OHHHHHHHHHHHH

#

"seed":{"item":{"item":"sushigocrafting:rice_seeds"}}

#

i see i see

#

[07:20:21] [WARN] Error parsing recipe botanypots:kjs_6n3fj58iy03emlcpbkwt08dbv[botanypots:crop]: {"type":"botanypots:crop","seed":{"item":"sushigocrafting:rice_seeds"},"categories":["dirt","farmland"],"growthTicks":1200,"display":{"type":"botanypots:aging","block":"sushigocrafting:rice"},"drops":[{"chance":1,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRols":2},{"chance":0.15,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRols":2}]}: com.google.gson.JsonParseException: ID 'sushigocrafting:rice' has not been registered

progress

#

[07:21:58] [WARN] Error parsing recipe botanypots:kjs_8m9adkd1hay5johhw65zaxu4y[botanypots:crop]: {"type":"botanypots:crop","seed":{"item":"sushigocrafting:rice_seeds"},"categories":["dirt","farmland"],"growthTicks":1200,"display":{"type":"botanypots:aging","block":{"item":"sushigocrafting:rice"}},"drops":[{"chance":1,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRols":2},{"chance":0.15,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRols":2}]}: java.lang.NullPointerException: Cannot invoke "com.google.gson.JsonElement.isJsonPrimitive()" because "json" is null

#
[07:25:27] [WARN] java.lang.NullPointerException```
![thinking2](https://cdn.discordapp.com/emojis/836455586543435817.webp?size=128 "thinking2")
#
  sushigo.forEach((k, v) => {
    event.custom({
      type: "botanypots:crop",
      seed: Ingredient.of(k).toJson(),
      categories: ["dirt", "farmland"],
      growthTicks: 1200,
      display: {
        type: "botanypots:aging",
        block: Ingredient.of(v).toJson(),
      },
      drops: [
        {
          chance: 1.0,
          output: v,
          minRolls: 1,
          maxRols: 2,
        },
        {
          chance: 0.15,
          output: v,
          minRolls: 1,
          maxRols: 2,
        },
      ],
    });
  });

as it sits now.

#

oh, found a typo

#

no change after fixing the maxRols typo.

ancient robin
#

so where are we getting the null value?

ancient robin
#

"block":{"item":"sushigocrafting:rice"}} would it be here?

#

let's try this: block: Block.of(v).toJson()

ancient robin
#

block: Block.getBlock(v) results in [18:30:35] [WARN] Error parsing recipe botanypots:kjs_40836cx6by1pu3n1e8kvla4kr[botanypots:crop]: {"type":"botanypots:crop","seed":{"item":"sushigocrafting:rice_seeds"},"categories":["dirt","farmland"],"growthTicks":1200,"display":{"type":"botanypots:aging","block":null},"drops":[{"chance":1,"output":"sushigocrafting:rice","minRolls":1,"maxRolls":2},{"chance":0.15,"output":"sushigocrafting:rice","minRolls":1,"maxRolls":2}]}: com.google.gson.JsonParseException: Expected properties to be an object. Recieved null (json)
and that's probably because on sushigocrafting github, the blocks for rice, specifically, are

{
  "variants": {
    "age=0": {
      "model": "sushigocrafting:block/rice_crop_0"
    },
    "age=1": {
      "model": "sushigocrafting:block/rice_crop_1"
    },
    "age=2": {
      "model": "sushigocrafting:block/rice_crop_2"
    },
    "age=3": {
      "model": "sushigocrafting:block/rice_crop_3"
    }
  }
}
jade warren
#

Where the Block ist you don't use the ingredient.of Just v

ancient robin
# jade warren Where the Block ist you don't use the ingredient.of Just `v`

[06:51:40] [WARN] Error parsing recipe botanypots:kjs_7puhhlkfevoecw1pkh17tmozs[botanypots:crop]: {"type":"botanypots:crop","seed":{"item":"sushigocrafting:rice_seeds"},"categories":["dirt","farmland"],"growthTicks":1200,"display":{"type":"botanypots:aging","block":"sushigocrafting:rice"},"drops":[{"chance":1,"output":"sushigocrafting:rice","minRolls":1,"maxRolls":2},{"chance":0.15,"output":"sushigocrafting:rice","minRolls":1,"maxRolls":2}]}: com.google.gson.JsonParseException: ID 'sushigocrafting:rice' has not been registered

      display: {
        type: "botanypots:aging",
        block: v,
      },
jade warren
#

then you probably need a third id for that block as it's different from the seed / result

ancient robin
#

yup, and that's why i was wanting a hashtable, but seems like they don't work the same way in JS as i am familiar with powershell.

#

powershell hashtable, i can define names for the values. JS? ehh... i think i have to define an object literal.

jade warren
#

you could just make a function and make a function call each time

#

or use arrays inside of one array

ancient robin
#

see, i'm not versed in JS and my IDE kept throwing syntax errors.

#

my search engine fu wasn't producing anything meaningful.

#

why not register the item value as it's block?

jade warren
#

You can also use a function I've made which is much more dynamic (though doesn't support aging)

function arrConvert(element) {
    let array = Array.isArray(element) ? element : [element]
    return array
}

function blockConvert(blockString, withType) {
    let block = blockString.substring(0, 1) === "#" ? {tag: blockString.substring(1)} : {block: blockString}
    if (withType) block["type"] = blockString.substring(0, 1) === "#" ? "tag" : "block"
    return block
}

let crop = (event, output, inputSeed, soilCategories, growthTicks, displayBlock) => {
  if (typeof displayBlock!="string") displayBlock = inputSeed
  let results = []
  output.forEach(roll => {
    results.push({
      output: Ingredient.of(roll[0]).toResultJson(),
      chance: typeof roll[1]=='undefined' ? 1 : roll[1],
      minRolls: typeof roll[2]=='undefined' ? 1 : roll[2],
      maxRolls: typeof roll[3]=='undefined' ? 1 : roll[3]
    })
  })
  event.custom({
    type: "botanypots:crop",

    seed: Ingredient.of(inputSeed).id,
    drops: results,

    categories: arrConvert(soilCategories),
    growthTicks: typeof growthTicks == "number" ? growthTicks : 1200,
    display: blockConvert(displayBlock, false)
  })
}

And then to register new recipes:

crop(event, [["sushigocrafting:rice", 1, 1, 2], ["sushigocrafting:rice", 0.15, 1, 2]], "sushigocrafting:rice_seeds", ["dirt", "farmland"], 1200, "blockid")
#

Or you can even use a loop if you want them to have the same properties:

let cropRecipes = [
  ["sushigocrafting:rice", "sushigocrafting:rice_seeds", "block_id_if_different_from_input"],
  ["sushigocrafting:cucumber", "sushigocrafting:cucumber_seeds"]
]
cropRecipes.forEach(rData => {
  crop(event, [[rData[0], 1, 1, 2], [rData[0], 0.15, 1, 2]], rData[1], ["dirt", "farmland"], 1200, rData[2] == undefined ? rData[1] : rData[2])
})
ancient robin
#

wait, aging is an optional property?

#

i thought it was required.

#

lemme rip that out real quick.

jade warren
#

yeah that's optional, with aging it goes through the stages of the crop, without it just grows over time

ancient robin
#

oh very cool. thank you.

ancient robin
#

oohhh, there's an array inside of an array.

#

hopefully, no offense. i took your functions and used it as inspiration to try and take a crack at it

#
ServerEvents.recipes((event) => {
  const crops = ["rice", "cucumber", "soy_bean", "wasabi_root", "sesame_seed"];
  function categories(crop) {
    return crop == "rice" ? ["water"] : ["dirt", "farmland"];
  }
  function seeds(crop) {
    return `sushigocrafting:${crop}_seeds`;
  }
  function items(crop) {
    return `sushigocrafting:${crop}`;
  }
  function blockConvert(blockString, withType) {
    const block =
      blockString.substring(0, 1) === "#"
        ? { tag: blockString.substring(1) }
        : { block: blockString };
    if (withType)
      block.type = blockString.substring(0, 1) === "#" ? "tag" : "block";
    return block;
  }
  crops.forEach((crop) => {
    event.custom({
      type: "botanypots:crop",
      seed: Ingredient.of(seeds(crop)).toJson(),
      categories: categories(crop),
      growthTicks: 1200,
      display: {
        // type: "botanypots:aging",
        block: blockConvert(crop, false),
      },
      drops: [
        {
          chance: 1.0,
          output: Ingredient.of(items(crop)).toJson(),
          minRolls: 1,
          maxRolls: 2,
        },
        {
          chance: 0.15,
          output: Ingredient.of(items(crop)).toJson(),
          minRolls: 1,
          maxRolls: 2,
        },
      ],
    });
  });
});

new error:
[19:01:12] [WARN] Error parsing recipe botanypots:kjs_22hy9mki7evjkzpdrltxix84l[botanypots:crop]: {"type":"botanypots:crop","seed":{"item":"sushigocrafting:rice_seeds"},"categories":["water"],"growthTicks":1200,"display":{"block":{"block":"rice"}},"drops":[{"chance":1,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRolls":2},{"chance":0.15,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRolls":2}]}: com.google.gson.JsonSyntaxException: Expected a string, was an object ({"bl...e"})

#

also, i lifted the block convert function, not knowing 100% what it does.

#

made a small change

display: Ingredient.of(items(crop)).toJson(),

new error:
[19:16:50] [WARN] Error parsing recipe botanypots:kjs_7fa58dbyy6jsi1k5w57tmk20s[botanypots:crop]: {"type":"botanypots:crop","seed":{"item":"sushigocrafting:rice_seeds"},"categories":["water"],"growthTicks":1200,"display":{"item":"sushigocrafting:rice"},"drops":[{"chance":1,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRolls":2},{"chance":0.15,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRolls":2}]}: java.lang.NullPointerException: Cannot invoke "com.google.gson.JsonElement.isJsonPrimitive()" because "json" is null

#

oh, because it's looking for block type instead of item

#

got it

#

went back to the blockConvert function

[19:22:37] [WARN] Error parsing recipe botanypots:kjs_56gjfia7uy2f8se1hawa9fq3t[botanypots:crop]: {"type":"botanypots:crop","seed":{"item":"sushigocrafting:rice_seeds"},"categories":["water"],"growthTicks":1200,"display":{"block":"sushigocrafting:rice"},"drops":[{"chance":1,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRolls":2},{"chance":0.15,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRolls":2}]}: com.google.gson.JsonParseException: ID 'sushigocrafting:rice' has not been registered

#
display: blockConvert(`sushigocrafting:${crop}`, false),`
ancient robin
#

so we basically went full circle. topkek

ancient robin
#

tried to manually register the blocks in startup

/// this is in startup
ServerEvents.tags("block", (event) => {
  const crops = ["rice", "cucumber", "soy_bean", "wasabi_root", "sesame_seed"];
  crops.forEach((crop) => {
    event.create(`sushigocrafting:blocks/${crop}`).displayname(crop);
  });
});
/// modified recipe
display: blockConvert(`sushigocrafting:blocks/${crop}`, false),

new error, which is the same of the above.
[20:28:11] [WARN] Error parsing recipe botanypots:kjs_7rgdydoylxtn5pgp2zwoulap5[botanypots:crop]: {"type":"botanypots:crop","seed":{"item":"sushigocrafting:rice_seeds"},"categories":["water"],"growthTicks":1200,"display":{"block":"sushigocrafting:blocks/rice"},"drops":[{"chance":1,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRolls":2},{"chance":0.15,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRolls":2}]}: com.google.gson.JsonParseException: ID 'sushigocrafting:blocks/rice' has not been registered
no errors in startup

#

oh wait

#

i'm using the wrong function

#

sec

#
ServerEvents.registry("block", (event) => {
  const crops = ["rice", "cucumber", "soy_bean", "wasabi_root", "sesame_seed"];
  crops.forEach((crop) => {
    event.create(`sushigocrafting:blocks/${crop}`).displayname(crop);
  });
});

no go. still stating that the id has not been registered... wait. i think i saw something about tags.

#
StartupEvents.registry("block", (event) => {
  event.create("example_block") // Create a new block with ID "kubejs:example_block"
})

oh. i'm looking for kubejs.

#

my adhd is refusing to let me play the game until i can get this recipe working. 😭

ancient robin
#

[20:48:09] [WARN] Error parsing recipe botanypots:kjs_au9d7bn00170j8857gp4hke9t[botanypots:crop]: {"type":"botanypots:crop","seed":{"item":"sushigocrafting:rice_seeds"},"categories":["water"],"growthTicks":1200,"display":{"block":"kubejs:blocks/rice"},"drops":[{"chance":1,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRolls":2},{"chance":0.15,"output":{"item":"sushigocrafting:rice"},"minRolls":1,"maxRolls":2}]}: com.google.gson.JsonParseException: ID 'kubejs:blocks/rice' has not been registered

jade warren
#

You don't need to manually Register the blocks, Check with F3 the ID of the crop when placed

ancient robin
#

Oh. Yeah, let me try that.

ancient robin
#

i don't get it

#

oh

#

rice_crop

#

HUZZAH!

#

but now got another issue, but this time, it's just string manipulation

#

[06:37:03] [WARN] Error parsing recipe botanypots:kjs_9dg2db0t6r3q5rkkl27i4d82w[botanypots:crop]: {"type":"botanypots:crop","seed":[],"categories":["dirt","farmland"],"growthTicks":1200,"display":{"block":"sushigocrafting:soy_bean_crop"},"drops":[{"chance":1,"output":{"item":"sushigocrafting:soy_bean"},"minRolls":1,"maxRolls":2},{"chance":0.15,"output":{"item":"sushigocrafting:soy_bean"},"minRolls":1,"maxRolls":2}]}: com.google.gson.JsonParseException: ID 'sushigocrafting:soy_bean_crop' has not been registered

#

it's supposed to be soy_crop

ancient robin
#

WINNING

#
ServerEvents.recipes((event) => {
  const crops = ["rice", "cucumber", "soy_bean", "wasabi_root", "sesame_seed"];
  function categories(crop) {
    return crop == "rice" ? ["water"] : ["dirt", "farmland"];
  }
  function seeds(crop) {
    return `sushigocrafting:${crop}_seeds`;
  }
  function items(crop) {
    return `sushigocrafting:${crop}`;
  }
  function blockConvert(blockString, withType) {
    const block =
      blockString.substring(0, 1) === "#"
        ? { tag: blockString.substring(1) }
        : { block: blockString };
    if (withType)
      block.type = blockString.substring(0, 1) === "#" ? "tag" : "block";
    return block;
  }
  function removeUnder(crop) {
    if (crop.includes("_")) {
      const base = `sushigocrafting:${crop.split("_")[0]}_crop`
      return blockConvert(base,false)
    } else {
      return blockConvert(`sushigocrafting:${crop}_crop`,false)
    }
  }
  crops.forEach((crop) => {
    event.custom({
      type: "botanypots:crop",
      seed: Ingredient.of(seeds(crop)).toJson(),
      categories: categories(crop),
      growthTicks: 1200,
      //display: blockConvert(`sushigocrafting:${crop}_crop`, false),
      display: removeUnder(crop),
      drops: [
        {
          chance: 1.0,
          output: Ingredient.of(items(crop)).toJson(),
          minRolls: 1,
          maxRolls: 2,
        },
        {
          chance: 0.15,
          output: Ingredient.of(items(crop)).toJson(),
          minRolls: 1,
          maxRolls: 2,
        },
      ],
    });
  });
});
#

i appreciate all your help, @jade warren

#

wonder if i feed it through chatgpt, will it clean up some of the code? thinking2