OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

Issues with Automated Generation of Minecraft Item Data Using PrismarineJS

  • Thread starter Thread starter Yanis GANGNANT
  • Start date Start date
Y

Yanis GANGNANT

Guest
I started a Minecraft project involving automated accounts, and I need the bots to recognize different ways to obtain items. For simplicity, I exclude advanced methods like trading with villagers. I attempted to generate a JSON file listing all Minecraft items and their acquisition methods using JavaScript. However, the generated data contains inaccuracies. For instance, bedrock is marked as mineable and drops bamboo_block, while jungle_log drops yellow_wool.

Here is the relevant part of my JavaScript code and a link to the generated items.json file:


Code:
const fs = require('fs');
const registry = require('prismarine-registry')('1.20.4');
const {Recipe} = require('prismarine-recipe')('1.20.4');
const Block = require('prismarine-block')('1.20.4');

const items = registry.items;
const blocks = registry.blocks;

function getCraftingRecipes(itemId) {
    const recipesForItem = Recipe.find(itemId, null);
    if (!recipesForItem) return [];
    return recipesForItem.map(recipe => {
        const requiredItems = {};
        // console.log("ITEM ---------------------------------- \n");
        // console.log(registry.items[itemId].name);
        // console.log("RECIPES ------------------------------- \n");
        // console.log(recipe);
        // console.log("INGREDIENTS --------------------------- \n");
        // console.log(recipe.ingredients);

        if (recipe.inShape) {
            recipe.inShape.forEach(row => {
                row.forEach(ingredient => {
                    if (ingredient) {
                        const itemName = items[ingredient.id] ? items[ingredient.id].name : 'unknown';
                        requiredItems[itemName] = (requiredItems[itemName] || 0) + Math.abs(ingredient.count);
                    }
                });
            });
        } else if (recipe.delta) {
            recipe.delta.forEach(deltaItem => {
                if (deltaItem.id !== itemId) {
                    const itemName = items[deltaItem.id] ? items[deltaItem.id].name : 'unknown';
                    requiredItems[itemName] = (requiredItems[itemName] || 0) + Math.abs(deltaItem.count);
                }
            });
        }

        return {
            required_items: requiredItems,
            obtained_count: recipe.result.count
        };
    }).sort((a, b) => b.obtained_count - a.obtained_count);
}

function getSmeltingRecipe(itemId) {
    // Smelting recipes are not handled by prismarine-recipe, so handle manually
    const smeltingRecipes = [
        {input: 'iron_ore', result: 'iron_ingot'},
        {input: 'deepslate_iron_ore', result: 'iron_ingot'},
        {input: 'gold_ore', result: 'gold_ingot'},
        {input: 'deepslate_gold_ore', result: 'gold_ingot'},
        {input: 'copper_ore', result: 'copper_ingot'},
        {input: 'deepslate_copper_ore', result: 'copper_ingot'},
        {input: 'nether_gold_ore', result: 'gold_ingot'},
        {input: 'ancient_debris', result: 'netherite_scrap'},
        {input: 'sand', result: 'glass'},
        {input: 'red_sand', result: 'glass'},
        {input: 'cobblestone', result: 'stone'},
        {input: 'stone', result: 'smooth_stone'},
        {input: 'netherrack', result: 'nether_brick'},
        {input: 'clay_ball', result: 'brick'},
        {input: 'clay', result: 'terracotta'},
        {input: 'wet_sponge', result: 'sponge'},
        {input: 'cactus', result: 'green_dye'},
        {input: 'kelp', result: 'dried_kelp'},
        {input: 'log', result: 'charcoal'},
        {input: 'wood', result: 'charcoal'},
        {input: 'sandstone', result: 'smooth_sandstone'},
        {input: 'red_sandstone', result: 'smooth_red_sandstone'},
        {input: 'quartz_block', result: 'smooth_quartz'},
        {input: 'andesite', result: 'polished_andesite'},
        {input: 'granite', result: 'polished_granite'},
        {input: 'diorite', result: 'polished_diorite'},
        {input: 'blackstone', result: 'polished_blackstone'},
        {input: 'beef', result: 'cooked_beef'},
        {input: 'chicken', result: 'cooked_chicken'},
        {input: 'porkchop', result: 'cooked_porkchop'},
        {input: 'mutton', result: 'cooked_mutton'},
        {input: 'rabbit', result: 'cooked_rabbit'},
        {input: 'cod', result: 'cooked_cod'},
        {input: 'salmon', result: 'cooked_salmon'},
        {input: 'potato', result: 'baked_potato'},
        {input: 'chorus_fruit', result: 'popped_chorus_fruit'},
        {input: 'sea_pickle', result: 'lime_dye'}
    ];

    const smeltingRecipe = smeltingRecipes.find(recipe => registry.itemsByName[recipe.result].id === itemId);

    if (smeltingRecipe) {
        return {
            input_item: smeltingRecipe.input,
            output_count: 1 // Generally, smelting recipes yield 1 item
        };
    }
    return null;
}

function getMiningInfo(blockName) {
    const block = blocks[blockName];
    if (!block) return null;

    const blockInstance = Block.fromStateId(block.minStateId, 1);
    if (!blockInstance) return null;

    let requiredTool = null;
    if (blockInstance.harvestTools) {
        const tools = Object.keys(blockInstance.harvestTools);
        if (tools.length > 0) {
            requiredTool = items[parseInt(tools[0])]?.name || null;
        }
    }

    let drops = null;
    if (blockInstance.drops && blockInstance.drops.length > 0) {
        const dropId = blockInstance.drops[0];
        drops = registry.items[dropId]?.name || null;
    }

    let mineable = blockInstance.diggable || false;

    return {
        mineable: mineable,
        required_tool: requiredTool,
        drops: drops
    };
}

const itemData = {};

for (const itemName in items) {
    const item = items[itemName];
    const itemInfo = {
        craftable: getCraftingRecipes(item.id).length > 0,
        mineable: false,
        obtainable_by_killing: false,
        obtainable_by_smelting: false,
        crafting_recipes: getCraftingRecipes(item.id)
    };

    const smeltingRecipe = getSmeltingRecipe(item.id);
    if (smeltingRecipe) {
        itemInfo.obtainable_by_smelting = true;
        itemInfo.smelting_recipe = smeltingRecipe;
    }

    const block = blocks[itemName];
    if (block) {
        const miningInfo = getMiningInfo(itemName);
        if (miningInfo) {
            itemInfo.mineable = miningInfo.mineable;
            itemInfo.required_tool = miningInfo.required_tool;
            itemInfo.drops = miningInfo.drops;
        }
    }

    itemData[item.name] = itemInfo;
}

fs.writeFileSync('items.json', JSON.stringify(itemData, null, 2));

console.log('items.json file has been created.');

Problem: The generated items.json file contains incorrect data, such as bedrock being marked as mineable with bamboo_block drops, and jungle_log dropping yellow_wool. I suspect the issue lies with how IDs are handled, but I can't pinpoint the exact problem.

Expectations: The items.json file should accurately reflect the mineability, correct drops, and crafting recipes of each item.

What I've Tried:


  • Debugging the code to handle IDs correctly.


  • Checking the data returned by prismarine-registry and prismarine-recipe.

Could you help me identify and fix the issue in my script?

EDIT:

06/24/2024


  • Added let mineable = blockInstance.diggable || false; to check if a block is mineable or not.


  • Updated the items.json file.

<p>I started a Minecraft project involving automated accounts, and I need the bots to recognize different ways to obtain items. For simplicity, I exclude advanced methods like trading with villagers. I attempted to generate a JSON file listing all Minecraft items and their acquisition methods using JavaScript. However, the generated data contains inaccuracies. For instance, bedrock is marked as mineable and drops bamboo_block, while jungle_log drops yellow_wool.</p>
<p>Here is the relevant part of my JavaScript code and a link to the generated <code>items.json</code> file:</p>
<ul>
<li><a href="https://mail.gangnant.fr/cloud/index.php/s/items_json" rel="nofollow noreferrer">items.json (https://mail.gangnant.fr/cloud/index.php/s/items_json)</a></li>
</ul>
<pre class="lang-js prettyprint-override"><code>const fs = require('fs');
const registry = require('prismarine-registry')('1.20.4');
const {Recipe} = require('prismarine-recipe')('1.20.4');
const Block = require('prismarine-block')('1.20.4');

const items = registry.items;
const blocks = registry.blocks;

function getCraftingRecipes(itemId) {
const recipesForItem = Recipe.find(itemId, null);
if (!recipesForItem) return [];
return recipesForItem.map(recipe => {
const requiredItems = {};
// console.log("ITEM ---------------------------------- \n");
// console.log(registry.items[itemId].name);
// console.log("RECIPES ------------------------------- \n");
// console.log(recipe);
// console.log("INGREDIENTS --------------------------- \n");
// console.log(recipe.ingredients);

if (recipe.inShape) {
recipe.inShape.forEach(row => {
row.forEach(ingredient => {
if (ingredient) {
const itemName = items[ingredient.id] ? items[ingredient.id].name : 'unknown';
requiredItems[itemName] = (requiredItems[itemName] || 0) + Math.abs(ingredient.count);
}
});
});
} else if (recipe.delta) {
recipe.delta.forEach(deltaItem => {
if (deltaItem.id !== itemId) {
const itemName = items[deltaItem.id] ? items[deltaItem.id].name : 'unknown';
requiredItems[itemName] = (requiredItems[itemName] || 0) + Math.abs(deltaItem.count);
}
});
}

return {
required_items: requiredItems,
obtained_count: recipe.result.count
};
}).sort((a, b) => b.obtained_count - a.obtained_count);
}

function getSmeltingRecipe(itemId) {
// Smelting recipes are not handled by prismarine-recipe, so handle manually
const smeltingRecipes = [
{input: 'iron_ore', result: 'iron_ingot'},
{input: 'deepslate_iron_ore', result: 'iron_ingot'},
{input: 'gold_ore', result: 'gold_ingot'},
{input: 'deepslate_gold_ore', result: 'gold_ingot'},
{input: 'copper_ore', result: 'copper_ingot'},
{input: 'deepslate_copper_ore', result: 'copper_ingot'},
{input: 'nether_gold_ore', result: 'gold_ingot'},
{input: 'ancient_debris', result: 'netherite_scrap'},
{input: 'sand', result: 'glass'},
{input: 'red_sand', result: 'glass'},
{input: 'cobblestone', result: 'stone'},
{input: 'stone', result: 'smooth_stone'},
{input: 'netherrack', result: 'nether_brick'},
{input: 'clay_ball', result: 'brick'},
{input: 'clay', result: 'terracotta'},
{input: 'wet_sponge', result: 'sponge'},
{input: 'cactus', result: 'green_dye'},
{input: 'kelp', result: 'dried_kelp'},
{input: 'log', result: 'charcoal'},
{input: 'wood', result: 'charcoal'},
{input: 'sandstone', result: 'smooth_sandstone'},
{input: 'red_sandstone', result: 'smooth_red_sandstone'},
{input: 'quartz_block', result: 'smooth_quartz'},
{input: 'andesite', result: 'polished_andesite'},
{input: 'granite', result: 'polished_granite'},
{input: 'diorite', result: 'polished_diorite'},
{input: 'blackstone', result: 'polished_blackstone'},
{input: 'beef', result: 'cooked_beef'},
{input: 'chicken', result: 'cooked_chicken'},
{input: 'porkchop', result: 'cooked_porkchop'},
{input: 'mutton', result: 'cooked_mutton'},
{input: 'rabbit', result: 'cooked_rabbit'},
{input: 'cod', result: 'cooked_cod'},
{input: 'salmon', result: 'cooked_salmon'},
{input: 'potato', result: 'baked_potato'},
{input: 'chorus_fruit', result: 'popped_chorus_fruit'},
{input: 'sea_pickle', result: 'lime_dye'}
];

const smeltingRecipe = smeltingRecipes.find(recipe => registry.itemsByName[recipe.result].id === itemId);

if (smeltingRecipe) {
return {
input_item: smeltingRecipe.input,
output_count: 1 // Generally, smelting recipes yield 1 item
};
}
return null;
}

function getMiningInfo(blockName) {
const block = blocks[blockName];
if (!block) return null;

const blockInstance = Block.fromStateId(block.minStateId, 1);
if (!blockInstance) return null;

let requiredTool = null;
if (blockInstance.harvestTools) {
const tools = Object.keys(blockInstance.harvestTools);
if (tools.length > 0) {
requiredTool = items[parseInt(tools[0])]?.name || null;
}
}

let drops = null;
if (blockInstance.drops && blockInstance.drops.length > 0) {
const dropId = blockInstance.drops[0];
drops = registry.items[dropId]?.name || null;
}

let mineable = blockInstance.diggable || false;

return {
mineable: mineable,
required_tool: requiredTool,
drops: drops
};
}

const itemData = {};

for (const itemName in items) {
const item = items[itemName];
const itemInfo = {
craftable: getCraftingRecipes(item.id).length > 0,
mineable: false,
obtainable_by_killing: false,
obtainable_by_smelting: false,
crafting_recipes: getCraftingRecipes(item.id)
};

const smeltingRecipe = getSmeltingRecipe(item.id);
if (smeltingRecipe) {
itemInfo.obtainable_by_smelting = true;
itemInfo.smelting_recipe = smeltingRecipe;
}

const block = blocks[itemName];
if (block) {
const miningInfo = getMiningInfo(itemName);
if (miningInfo) {
itemInfo.mineable = miningInfo.mineable;
itemInfo.required_tool = miningInfo.required_tool;
itemInfo.drops = miningInfo.drops;
}
}

itemData[item.name] = itemInfo;
}

fs.writeFileSync('items.json', JSON.stringify(itemData, null, 2));

console.log('items.json file has been created.');
</code></pre>
<p><strong>Problem:</strong> The generated <code>items.json</code> file contains incorrect data, such as bedrock being marked as mineable with bamboo_block drops, and jungle_log dropping yellow_wool. I suspect the issue lies with how IDs are handled, but I can't pinpoint the exact problem.</p>
<p><strong>Expectations:</strong> The <code>items.json</code> file should accurately reflect the mineability, correct drops, and crafting recipes of each item.</p>
<p><strong>What I've Tried:</strong></p>
<ul>
<li><p>Debugging the code to handle IDs correctly.</p>
</li>
<li><p>Checking the data returned by <code>prismarine-registry</code> and <code>prismarine-recipe</code>.</p>
</li>
</ul>
<p>Could you help me identify and fix the issue in my script?</p>
<p><strong>EDIT:</strong></p>
<p><em>06/24/2024</em></p>
<ul>
<li><p>Added <code>let mineable = blockInstance.diggable || false;</code> to check if a block is mineable or not.</p>
</li>
<li><p>Updated the items.json file.</p>
</li>
</ul>
 
Top