#HashTable help: Starter template for Botany Pots in 1.20?
81 messages · Page 1 of 1 (latest)
Once your ticket has been resolved, please close it with </ticket close:1054771505520717835> command!
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

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
[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'

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.
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
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```

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.
so where are we getting the null value?
"block":{"item":"sushigocrafting:rice"}} would it be here?
let's try this: block: Block.of(v).toJson()
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"
}
}
}
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,
},
then you probably need a third id for that block as it's different from the seed / result
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.
you could just make a function and make a function call each time
or use arrays inside of one array
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?
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])
})
wait, aging is an optional property?
i thought it was required.
lemme rip that out real quick.
yeah that's optional, with aging it goes through the stages of the crop, without it just grows over time
oh very cool. thank you.
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),`
so we basically went full circle. 
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. 😭
[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
You don't need to manually Register the blocks, Check with F3 the ID of the crop when placed
Oh. Yeah, let me try that.
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
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? 