From 0e00b6304171a2908fc93eac34ff607ad1f64f54 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Mon, 9 Jan 2023 22:07:02 -0500 Subject: [PATCH 01/11] bedrock support, add blockVariantsByStateId from prismarine-viewer --- index.js | 265 +++++++++++++++++++++++++------------------------ lib/indexer.js | 94 ++++++++++++++++++ lib/indexes.js | 11 +- lib/loader.js | 14 +-- package.json | 11 +- test/api.js | 16 +++ 6 files changed, 266 insertions(+), 145 deletions(-) create mode 100644 test/api.js diff --git a/index.js b/index.js index 94155fc..a62de54 100644 --- a/index.js +++ b/index.js @@ -1,138 +1,143 @@ const mcDataToNode = require('./lib/loader') -const cache = {} // prevent reindexing when requiring multiple time the same version - -function getVersion (mcVersion) { - if (cache[mcVersion]) { return cache[mcVersion] } - const mcData = data[mcVersion] - if (mcData == null) { return null } - const nmcData = mcDataToNode(mcData, mcVersion) - cache[mcVersion] = nmcData - return nmcData -} - -function toMajor (version) { - const [a, b] = (version + '').split('.') - return a + '.' + b +const path = require('path') +const cache = { pc: {}, bedrock: {} } // prevent reindexing when requiring multiple time the same version +const data = { + pc: { + '1.8.8': { + directory: path.join(__dirname, './minecraft-assets/data/1.8.8/'), + blocksTextures: require('./minecraft-assets/data/1.8.8/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.8.8/items_textures'), + textureContent: require('./minecraft-assets/data/1.8.8/texture_content'), + blocksStates: require('./minecraft-assets/data/1.8.8/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.8.8/blocks_models') + }, + 1.9: { + directory: path.join(__dirname, './minecraft-assets/data/1.8.9/'), + blocksTextures: require('./minecraft-assets/data/1.9/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.9/items_textures'), + textureContent: require('./minecraft-assets/data/1.9/texture_content'), + blocksStates: require('./minecraft-assets/data/1.9/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.9/blocks_models') + }, + '1.10': { + directory: path.join(__dirname, './minecraft-assets/data/1.10/'), + blocksTextures: require('./minecraft-assets/data/1.10/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.10/items_textures'), + textureContent: require('./minecraft-assets/data/1.10/texture_content'), + blocksStates: require('./minecraft-assets/data/1.10/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.10/blocks_models') + }, + '1.11.2': { + directory: path.join(__dirname, './minecraft-assets/data/1.11.2/'), + blocksTextures: require('./minecraft-assets/data/1.11.2/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.11.2/items_textures'), + textureContent: require('./minecraft-assets/data/1.11.2/texture_content'), + blocksStates: require('./minecraft-assets/data/1.11.2/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.11.2/blocks_models') + }, + 1.12: { + directory: path.join(__dirname, './minecraft-assets/data/1.12/'), + blocksTextures: require('./minecraft-assets/data/1.12/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.12/items_textures'), + textureContent: require('./minecraft-assets/data/1.12/texture_content'), + blocksStates: require('./minecraft-assets/data/1.12/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.12/blocks_models') + }, + 1.13: { + directory: path.join(__dirname, './minecraft-assets/data/1.13/'), + blocksTextures: require('./minecraft-assets/data/1.13/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.13/items_textures'), + textureContent: require('./minecraft-assets/data/1.13/texture_content'), + blocksStates: require('./minecraft-assets/data/1.13/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.13/blocks_models') + }, + '1.13.2': { + directory: path.join(__dirname, './minecraft-assets/data/1.13.2/'), + blocksTextures: require('./minecraft-assets/data/1.13.2/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.13.2/items_textures'), + textureContent: require('./minecraft-assets/data/1.13.2/texture_content'), + blocksStates: require('./minecraft-assets/data/1.13.2/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.13.2/blocks_models') + }, + '1.14.4': { + directory: path.join(__dirname, './minecraft-assets/data/1.14.4/'), + blocksTextures: require('./minecraft-assets/data/1.14.4/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.14.4/items_textures'), + textureContent: require('./minecraft-assets/data/1.14.4/texture_content'), + blocksStates: require('./minecraft-assets/data/1.14.4/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.14.4/blocks_models') + }, + '1.15.2': { + directory: path.join(__dirname, './minecraft-assets/data/1.15.2/'), + blocksTextures: require('./minecraft-assets/data/1.15.2/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.15.2/items_textures'), + textureContent: require('./minecraft-assets/data/1.15.2/texture_content'), + blocksStates: require('./minecraft-assets/data/1.15.2/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.15.2/blocks_models') + }, + '1.16.1': { + directory: path.join(__dirname, './minecraft-assets/data/1.16.1/'), + blocksTextures: require('./minecraft-assets/data/1.16.1/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.16.1/items_textures'), + textureContent: require('./minecraft-assets/data/1.16.1/texture_content'), + blocksStates: require('./minecraft-assets/data/1.16.1/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.16.1/blocks_models') + }, + '1.16.4': { + directory: path.join(__dirname, './minecraft-assets/data/1.16.4/'), + blocksTextures: require('./minecraft-assets/data/1.16.4/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.16.4/items_textures'), + textureContent: require('./minecraft-assets/data/1.16.4/texture_content'), + blocksStates: require('./minecraft-assets/data/1.16.4/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.16.4/blocks_models') + }, + '1.17.1': { + directory: path.join(__dirname, './minecraft-assets/data/1.17.1/'), + blocksTextures: require('./minecraft-assets/data/1.17.1/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.17.1/items_textures'), + textureContent: require('./minecraft-assets/data/1.17.1/texture_content'), + blocksStates: require('./minecraft-assets/data/1.17.1/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.17.1/blocks_models') + }, + '1.18.1': { + directory: path.join(__dirname, './minecraft-assets/data/1.18.1/'), + blocksTextures: require('./minecraft-assets/data/1.18.1/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.18.1/items_textures'), + textureContent: require('./minecraft-assets/data/1.18.1/texture_content'), + blocksStates: require('./minecraft-assets/data/1.18.1/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.18.1/blocks_models') + } + } } -function minor (version) { - const [, , c] = (version + '.0').split('.') - return parseInt(c, 10) -} +Object.assign(data, { + bedrock: { + '1.16.220': data.pc['1.16.1'], + '1.17.10': data.pc['1.17.1'], + '1.17.40': data.pc['1.17.1'], + '1.18.0': data.pc['1.18.1'], + '1.19.1': data.pc['1.18.1'] + } +}) -module.exports = function (mcVersion) { - // Check exact version first - let assets = getVersion(mcVersion) - if (assets) { return assets } - // If not found, resort to the last of major - assets = getVersion(lastOfMajor[toMajor(mcVersion)]) - return assets -} +const reduce = what => what.reduce((acc, cur) => { + const major = cur.split('.').slice(0, 2).join('.') + const arr = acc[major] = acc[major] || [] + arr.push(cur) + return acc +}, {}) -const data = { - '1.8.8': { - blocksTextures: require('./minecraft-assets/data/1.8.8/blocks_textures'), - itemsTextures: require('./minecraft-assets/data/1.8.8/items_textures'), - textureContent: require('./minecraft-assets/data/1.8.8/texture_content'), - blocksStates: require('./minecraft-assets/data/1.8.8/blocks_states'), - blocksModels: require('./minecraft-assets/data/1.8.8/blocks_models') - }, - 1.9: { - blocksTextures: require('./minecraft-assets/data/1.9/blocks_textures'), - itemsTextures: require('./minecraft-assets/data/1.9/items_textures'), - textureContent: require('./minecraft-assets/data/1.9/texture_content'), - blocksStates: require('./minecraft-assets/data/1.9/blocks_states'), - blocksModels: require('./minecraft-assets/data/1.9/blocks_models') - }, - '1.10': { - blocksTextures: require('./minecraft-assets/data/1.10/blocks_textures'), - itemsTextures: require('./minecraft-assets/data/1.10/items_textures'), - textureContent: require('./minecraft-assets/data/1.10/texture_content'), - blocksStates: require('./minecraft-assets/data/1.10/blocks_states'), - blocksModels: require('./minecraft-assets/data/1.10/blocks_models') - }, - '1.11.2': { - blocksTextures: require('./minecraft-assets/data/1.11.2/blocks_textures'), - itemsTextures: require('./minecraft-assets/data/1.11.2/items_textures'), - textureContent: require('./minecraft-assets/data/1.11.2/texture_content'), - blocksStates: require('./minecraft-assets/data/1.11.2/blocks_states'), - blocksModels: require('./minecraft-assets/data/1.11.2/blocks_models') - }, - 1.12: { - blocksTextures: require('./minecraft-assets/data/1.12/blocks_textures'), - itemsTextures: require('./minecraft-assets/data/1.12/items_textures'), - textureContent: require('./minecraft-assets/data/1.12/texture_content'), - blocksStates: require('./minecraft-assets/data/1.12/blocks_states'), - blocksModels: require('./minecraft-assets/data/1.12/blocks_models') - }, - 1.13: { - blocksTextures: require('./minecraft-assets/data/1.13/blocks_textures'), - itemsTextures: require('./minecraft-assets/data/1.13/items_textures'), - textureContent: require('./minecraft-assets/data/1.13/texture_content'), - blocksStates: require('./minecraft-assets/data/1.13/blocks_states'), - blocksModels: require('./minecraft-assets/data/1.13/blocks_models') - }, - '1.13.2': { - blocksTextures: require('./minecraft-assets/data/1.13.2/blocks_textures'), - itemsTextures: require('./minecraft-assets/data/1.13.2/items_textures'), - textureContent: require('./minecraft-assets/data/1.13.2/texture_content'), - blocksStates: require('./minecraft-assets/data/1.13.2/blocks_states'), - blocksModels: require('./minecraft-assets/data/1.13.2/blocks_models') - }, - '1.14.4': { - blocksTextures: require('./minecraft-assets/data/1.14.4/blocks_textures'), - itemsTextures: require('./minecraft-assets/data/1.14.4/items_textures'), - textureContent: require('./minecraft-assets/data/1.14.4/texture_content'), - blocksStates: require('./minecraft-assets/data/1.14.4/blocks_states'), - blocksModels: require('./minecraft-assets/data/1.14.4/blocks_models') - }, - '1.15.2': { - blocksTextures: require('./minecraft-assets/data/1.15.2/blocks_textures'), - itemsTextures: require('./minecraft-assets/data/1.15.2/items_textures'), - textureContent: require('./minecraft-assets/data/1.15.2/texture_content'), - blocksStates: require('./minecraft-assets/data/1.15.2/blocks_states'), - blocksModels: require('./minecraft-assets/data/1.15.2/blocks_models') - }, - '1.16.1': { - blocksTextures: require('./minecraft-assets/data/1.16.1/blocks_textures'), - itemsTextures: require('./minecraft-assets/data/1.16.1/items_textures'), - textureContent: require('./minecraft-assets/data/1.16.1/texture_content'), - blocksStates: require('./minecraft-assets/data/1.16.1/blocks_states'), - blocksModels: require('./minecraft-assets/data/1.16.1/blocks_models') - }, - '1.16.4': { - blocksTextures: require('./minecraft-assets/data/1.16.4/blocks_textures'), - itemsTextures: require('./minecraft-assets/data/1.16.4/items_textures'), - textureContent: require('./minecraft-assets/data/1.16.4/texture_content'), - blocksStates: require('./minecraft-assets/data/1.16.4/blocks_states'), - blocksModels: require('./minecraft-assets/data/1.16.4/blocks_models') - }, - '1.17.1': { - blocksTextures: require('./minecraft-assets/data/1.17.1/blocks_textures'), - itemsTextures: require('./minecraft-assets/data/1.17.1/items_textures'), - textureContent: require('./minecraft-assets/data/1.17.1/texture_content'), - blocksStates: require('./minecraft-assets/data/1.17.1/blocks_states'), - blocksModels: require('./minecraft-assets/data/1.17.1/blocks_models') - }, - '1.18.1': { - blocksTextures: require('./minecraft-assets/data/1.18.1/blocks_textures'), - itemsTextures: require('./minecraft-assets/data/1.18.1/items_textures'), - textureContent: require('./minecraft-assets/data/1.18.1/texture_content'), - blocksStates: require('./minecraft-assets/data/1.18.1/blocks_states'), - blocksModels: require('./minecraft-assets/data/1.18.1/blocks_models') - } -} +const byMajor = { pc: reduce(Object.keys(data.pc)), bedrock: reduce(Object.keys(data.bedrock)) } +const lastOfMajor = (type, major) => byMajor[type][major][byMajor[type][major].length - 1] -module.exports.versions = Object.keys(data) +module.exports = function (registry) { + if (typeof registry === 'string') registry = require('prismarine-registry')(registry) + const v = registry.version + if (cache[v.type][v.minecraftVersion]) return cache[v.type][v.minecraftVersion] -const lastOfMajor = {} -for (const version in data) { - const major = toMajor(version) - if (lastOfMajor[major]) { - if (minor(lastOfMajor[major]) < minor(version)) { - lastOfMajor[major] = version - } - } else { - lastOfMajor[major] = version - } + // Check exact version first, else check the last minor version of the major + const assets = data[v.type][v.minecraftVersion] || data[v.type][lastOfMajor(v.type, v.majorVersion)] + const updated = cache[v.type][v.minecraftVersion] = mcDataToNode(assets, registry) + return updated } +module.exports.versions = byMajor diff --git a/lib/indexer.js b/lib/indexer.js index a2432a1..0028d43 100644 --- a/lib/indexer.js +++ b/lib/indexer.js @@ -5,3 +5,97 @@ module.exports.buildIndexFromArray = function (array, fieldToIndex) { return index }, {}) } + +function parseProperties (properties) { + if (typeof properties === 'object') { return properties } + + const json = {} + for (const prop of properties.split(',')) { + const [key, value] = prop.split('=') + json[key] = value + } + return json +} + +function matchProperties (block, properties) { + if (!properties) { return true } + + properties = parseProperties(properties) + const blockProps = block.getProperties() + for (const prop in blockProps) { + if (properties[prop] !== undefined && (blockProps[prop] + '') !== properties[prop]) { + return false + } + } + return true +} + +function getModelVariants (block, blockStates) { + const state = blockStates[block.name] + if (!state) return [] + if (state.variants) { + for (const [properties, variant] of Object.entries(state.variants)) { + if (!matchProperties(block, properties)) continue + if (variant instanceof Array) return [variant[0]] + return [variant] + } + } + if (state.multipart) { + const parts = state.multipart.filter(multipart => matchProperties(block, multipart.when)) + let variants = [] + for (const part of parts) { + if (part.apply instanceof Array) { + variants = [...variants, ...part.apply] + } else { + variants = [...variants, part.apply] + } + } + + return variants + } + + return [] +} + +module.exports.buildBedrockBlockStatesArray = function (registry, pcAssetBlockStates) { + const blockStateVariantsByStateId = {} + const blockStates = registry.blockStates + // First make a mapping of pe -> pc blocks from the block mapping schema + const pe = {} + const keyFromStates = states => Object.entries(states).map(entry => entry[0] + '=' + (entry[1].value ?? entry[1])).join(',') + for (const mapping of registry.blockMappings) { + pe[mapping.pe.name] = pe[mapping.pe.name] || {} + pe[mapping.pe.name][keyFromStates(mapping.pe.states)] = mapping.pc + } + // Then iterate over all the bedrock blocks and store the ModelVariants for each state ID + for (let stateId = 0; stateId < blockStates.length; stateId++) { + const blockState = blockStates[stateId] + const mapping = pe[blockState.name][keyFromStates(blockState.states)] + if (mapping) { + blockStateVariantsByStateId[stateId] = getModelVariants({ name: mapping.name, getProperties: () => mapping.states }, pcAssetBlockStates) + } else { + const fallback = Object.values(pe[blockState.name])[0] + if (fallback) { + blockStateVariantsByStateId[stateId] = getModelVariants({ name: fallback.name, getProperties: () => fallback.states }, pcAssetBlockStates) + } + } + } + return blockStateVariantsByStateId +} + +module.exports.buildPCBlockStatesArray = function (registry, blockStates) { + const Block = require('prismarine-block')(registry) + const blockStateVariantsByStateId = {} + const minStateId = 0 + let maxStateId = 0 + for (const block of registry.blocksArray) { + maxStateId = Math.max(maxStateId, block.maxStateId) + if (isNaN(maxStateId)) throw new Error('maxStateId is NaN') + } + for (let i = minStateId; i <= maxStateId; i++) { + const block = Block.fromStateId(i, 0) + const variants = getModelVariants(block, blockStates) + blockStateVariantsByStateId[i] = variants + } + return blockStateVariantsByStateId +} diff --git a/lib/indexes.js b/lib/indexes.js index a36df15..1da4538 100644 --- a/lib/indexes.js +++ b/lib/indexes.js @@ -1,9 +1,12 @@ const indexer = require('./indexer.js') -module.exports = function (mcData) { +module.exports = function (mcAssets, registry) { return { - blocksByName: indexer.buildIndexFromArray(mcData.blocksTextures, 'name'), - itemsByName: indexer.buildIndexFromArray(mcData.itemsTextures, 'name'), - textureContentByName: indexer.buildIndexFromArray(mcData.textureContent, 'name') + blocksByName: indexer.buildIndexFromArray(mcAssets.blocksTextures, 'name'), + itemsByName: indexer.buildIndexFromArray(mcAssets.itemsTextures, 'name'), + textureContentByName: indexer.buildIndexFromArray(mcAssets.textureContent, 'name'), + blockStateVariantsByStateId: registry.type === 'bedrock' + ? indexer.buildBedrockBlockStatesArray(registry, mcAssets.blocksStates) + : indexer.buildPCBlockStatesArray(registry, mcAssets.blocksStates) } } diff --git a/lib/loader.js b/lib/loader.js index ac3f354..d09b7e4 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -3,8 +3,8 @@ const path = require('path') module.exports = mcDataToNode -function mcDataToNode (mcData, mcVersion) { - const indexes = require('./indexes.js')(mcData) +function mcDataToNode (mcData, registry) { + const indexes = require('./indexes.js')(mcData, registry) function findItemOrBlockByName (name) { const item = indexes.itemsByName[name] if (item !== undefined) return item @@ -25,16 +25,16 @@ function mcDataToNode (mcData, mcVersion) { blocksStates: mcData.blocksStates, blocksModels: mcData.blocksModels, - directory: path.join(__dirname, '/../minecraft-assets/data/', mcVersion, '/'), - version: mcVersion, + blockStateVariantsByStateId: indexes.blockStateVariantsByStateId, + version: registry.version, - findItemOrBlockByName: findItemOrBlockByName, - getTexture: getTexture, + findItemOrBlockByName, + getTexture, getImageContent: function (name) { const texture = getTexture(name) if (texture == null) { return null } - return 'data:image/png;base64,' + fs.readFileSync(path.join(__dirname, '/../minecraft-assets/data/', mcVersion, '/', texture, '.png'), 'base64') + return 'data:image/png;base64,' + fs.readFileSync(path.join(mcData.directory, texture, '.png'), 'base64') } } } diff --git a/package.json b/package.json index 4c76799..9d5b8aa 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,9 @@ "main": "index.js", "tonicExampleFilename": "example.js", "scripts": { - "test": "npm run lint", + "test": "npm run lint && mocha --bail --exit", "lint": "standard", - "fix": "standard --fix", - "prepare": "npm install require-self && require-self" + "fix": "standard --fix" }, "repository": { "type": "git", @@ -25,7 +24,11 @@ }, "homepage": "https://github.com/rom1504/node-minecraft-assets#readme", "devDependencies": { - "require-self": "^0.2.3", + "minecraft-assets": "file:.", + "mocha": "^9.2.1", "standard": "^17.0.0" + }, + "dependencies": { + "prismarine-registry": "^1.1.0" } } diff --git a/test/api.js b/test/api.js new file mode 100644 index 0000000..762bbbe --- /dev/null +++ b/test/api.js @@ -0,0 +1,16 @@ +/* eslint-env mocha */ +const assert = require('assert') +const versions = ['bedrock_1.19.1', '1.8', '1.9', '1.10', '1.11', '1.12', '1.13.2', '1.14.4', '1.15.2', '1.16.1', '1.17', '1.18'] + +describe('api works', function () { + for (const version of versions) { + it('on ' + version, function () { + const registry = require('prismarine-registry')(version) + const mcAssets = require('minecraft-assets')(registry) + + assert(Object.values(mcAssets.blockStateVariantsByStateId).length > 0) + + console.log('Read', Object.values(mcAssets.blockStateVariantsByStateId).length, 'blockStateVariants') + }) + } +}) From 86946a3c735f27415fc34a6786e515f72a2cde95 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Mon, 9 Jan 2023 22:19:41 -0500 Subject: [PATCH 02/11] update API --- doc/api.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/api.md b/doc/api.md index e3a92f6..1334b9f 100644 --- a/doc/api.md +++ b/doc/api.md @@ -10,6 +10,14 @@ blocks textures by name array of blocks textures +### blocksModels + +map of block variant => model + +### blockStates + +array of block states + ## Items ### items @@ -30,6 +38,10 @@ texture content by name array of texture content +### blockStateVariantsByStateId + +Returns an array of block model variants mapped by block state ID, lookup with .blocksModels field + ## version ## directory From 7540a9c744a2e75cae623a7f02003ce046a984db Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sat, 25 Mar 2023 05:39:53 -0400 Subject: [PATCH 03/11] handle special cases, update .versions --- index.js | 8 ++------ lib/indexer.js | 16 +++++++++++++--- lib/loader.js | 1 + 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/index.js b/index.js index a62de54..234148f 100644 --- a/index.js +++ b/index.js @@ -12,7 +12,7 @@ const data = { blocksModels: require('./minecraft-assets/data/1.8.8/blocks_models') }, 1.9: { - directory: path.join(__dirname, './minecraft-assets/data/1.8.9/'), + directory: path.join(__dirname, './minecraft-assets/data/1.9/'), blocksTextures: require('./minecraft-assets/data/1.9/blocks_textures'), itemsTextures: require('./minecraft-assets/data/1.9/items_textures'), textureContent: require('./minecraft-assets/data/1.9/texture_content'), @@ -112,10 +112,6 @@ const data = { Object.assign(data, { bedrock: { - '1.16.220': data.pc['1.16.1'], - '1.17.10': data.pc['1.17.1'], - '1.17.40': data.pc['1.17.1'], - '1.18.0': data.pc['1.18.1'], '1.19.1': data.pc['1.18.1'] } }) @@ -140,4 +136,4 @@ module.exports = function (registry) { const updated = cache[v.type][v.minecraftVersion] = mcDataToNode(assets, registry) return updated } -module.exports.versions = byMajor +module.exports.versions = { pc: Object.keys(data.pc), bedrock: Object.keys(data.bedrock) } diff --git a/lib/indexer.js b/lib/indexer.js index 0028d43..1545a71 100644 --- a/lib/indexer.js +++ b/lib/indexer.js @@ -57,6 +57,8 @@ function getModelVariants (block, blockStates) { return [] } +// This function uses the minecraft-data blockMappings.json to translate the pc blockStates.json +// to bedrock block states. It also handles the special cases of stairs (but not snow layers/waterlogging). module.exports.buildBedrockBlockStatesArray = function (registry, pcAssetBlockStates) { const blockStateVariantsByStateId = {} const blockStates = registry.blockStates @@ -65,20 +67,28 @@ module.exports.buildBedrockBlockStatesArray = function (registry, pcAssetBlockSt const keyFromStates = states => Object.entries(states).map(entry => entry[0] + '=' + (entry[1].value ?? entry[1])).join(',') for (const mapping of registry.blockMappings) { pe[mapping.pe.name] = pe[mapping.pe.name] || {} - pe[mapping.pe.name][keyFromStates(mapping.pe.states)] = mapping.pc + pe[mapping.pe.name][keyFromStates(mapping.pe.states)] ??= mapping.pc } // Then iterate over all the bedrock blocks and store the ModelVariants for each state ID for (let stateId = 0; stateId < blockStates.length; stateId++) { const blockState = blockStates[stateId] const mapping = pe[blockState.name][keyFromStates(blockState.states)] + let variants + function getProperties () { + const states = { ...mapping.states } + // Stairs need special handling + if (states.shape) states.shape = 'straight' + return states + } if (mapping) { - blockStateVariantsByStateId[stateId] = getModelVariants({ name: mapping.name, getProperties: () => mapping.states }, pcAssetBlockStates) + variants = getModelVariants({ name: mapping.name, getProperties }, pcAssetBlockStates) } else { const fallback = Object.values(pe[blockState.name])[0] if (fallback) { - blockStateVariantsByStateId[stateId] = getModelVariants({ name: fallback.name, getProperties: () => fallback.states }, pcAssetBlockStates) + variants = getModelVariants({ name: fallback.name, getProperties }, pcAssetBlockStates) } } + blockStateVariantsByStateId[stateId] = variants } return blockStateVariantsByStateId } diff --git a/lib/loader.js b/lib/loader.js index d09b7e4..66e5928 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -28,6 +28,7 @@ function mcDataToNode (mcData, registry) { blockStateVariantsByStateId: indexes.blockStateVariantsByStateId, version: registry.version, + directory: mcData.directory, findItemOrBlockByName, getTexture, From 3271c8d764b6d2f4273446f8f562e6ca4b77c329 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sat, 25 Mar 2023 05:43:02 -0400 Subject: [PATCH 04/11] 1.19 update --- index.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 234148f..13e7853 100644 --- a/index.js +++ b/index.js @@ -106,13 +106,20 @@ const data = { textureContent: require('./minecraft-assets/data/1.18.1/texture_content'), blocksStates: require('./minecraft-assets/data/1.18.1/blocks_states'), blocksModels: require('./minecraft-assets/data/1.18.1/blocks_models') + }, + '1.19.1': { + blocksTextures: require('./minecraft-assets/data/1.19.1/blocks_textures'), + itemsTextures: require('./minecraft-assets/data/1.19.1/items_textures'), + textureContent: require('./minecraft-assets/data/1.19.1/texture_content'), + blocksStates: require('./minecraft-assets/data/1.19.1/blocks_states'), + blocksModels: require('./minecraft-assets/data/1.19.1/blocks_models') } } } Object.assign(data, { bedrock: { - '1.19.1': data.pc['1.18.1'] + '1.19.1': data.pc['1.19.1'] } }) From b2f839a24ad22699dbd85fb3661fd5d8536df8fd Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sat, 25 Mar 2023 05:49:53 -0400 Subject: [PATCH 05/11] Update ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2857598..192b707 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - node-version: [12.x] + node-version: [16.x] steps: - uses: actions/checkout@master From e6da80f15d08f43ac31e8ecbe608bc7bfba6abf0 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sat, 25 Mar 2023 05:52:24 -0400 Subject: [PATCH 06/11] add prismarine-block dep --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 4870a8b..67795f3 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "standard": "^17.0.0" }, "dependencies": { + "prismarine-block": "^1.16.3", "prismarine-registry": "^1.1.0" } } From b95c4cdd668c7ccadbb7281594ccdca87399c255 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sat, 25 Mar 2023 14:19:10 -0400 Subject: [PATCH 07/11] fix pc legacy blocks --- lib/indexer.js | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/indexer.js b/lib/indexer.js index 1545a71..3a08ee6 100644 --- a/lib/indexer.js +++ b/lib/indexer.js @@ -1,3 +1,5 @@ +const mcData = require('minecraft-data') + module.exports.buildIndexFromArray = function (array, fieldToIndex) { if (array === undefined) { return undefined } return array.reduce(function (index, element) { @@ -96,16 +98,26 @@ module.exports.buildBedrockBlockStatesArray = function (registry, pcAssetBlockSt module.exports.buildPCBlockStatesArray = function (registry, blockStates) { const Block = require('prismarine-block')(registry) const blockStateVariantsByStateId = {} - const minStateId = 0 - let maxStateId = 0 - for (const block of registry.blocksArray) { - maxStateId = Math.max(maxStateId, block.maxStateId) - if (isNaN(maxStateId)) throw new Error('maxStateId is NaN') - } - for (let i = minStateId; i <= maxStateId; i++) { - const block = Block.fromStateId(i, 0) - const variants = getModelVariants(block, blockStates) - blockStateVariantsByStateId[i] = variants + if (registry.supportFeature('usesBlockStates')) { + const minStateId = 0 + let maxStateId = 0 + for (const block of registry.blocksArray) { + maxStateId = Math.max(maxStateId, block.maxStateId) + if (isNaN(maxStateId)) throw new Error('maxStateId is NaN') + } + for (let i = minStateId; i <= maxStateId; i++) { + const block = Block.fromStateId(i, 0) + const variants = getModelVariants(block, blockStates) + blockStateVariantsByStateId[i] = variants + } + } else { + const states = Object.keys(mcData.legacy.pc.blocks).map(k => k.split(':')) + for (const [type, meta] of states) { + const stateId = type << 4 | meta + const block = Block.fromStateId(stateId, 0) + const variants = getModelVariants(block, blockStates) + blockStateVariantsByStateId[block.stateId] = variants + } } return blockStateVariantsByStateId } From 64bc9ecea8a7a70584e6e70a76f205268f644832 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sat, 25 Mar 2023 16:30:31 -0400 Subject: [PATCH 08/11] checkout submodules on install --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 67795f3..47f19e5 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "scripts": { "test": "npm run lint && mocha --bail --exit", "lint": "standard", + "postinstall": "git submodule update --init", "fix": "standard --fix" }, "repository": { From d22eb482d70702f95feb3c4ef6fa9ad53d21a344 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sun, 26 Mar 2023 02:47:39 -0400 Subject: [PATCH 09/11] revert last commit --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 47f19e5..67795f3 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,6 @@ "scripts": { "test": "npm run lint && mocha --bail --exit", "lint": "standard", - "postinstall": "git submodule update --init", "fix": "standard --fix" }, "repository": { From 76e76cbffec30d5f06e03cc5495ef6109163d3d6 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sun, 26 Mar 2023 04:42:05 -0400 Subject: [PATCH 10/11] fix missing 1.19.1 dir --- index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/index.js b/index.js index 13e7853..f526b45 100644 --- a/index.js +++ b/index.js @@ -108,6 +108,7 @@ const data = { blocksModels: require('./minecraft-assets/data/1.18.1/blocks_models') }, '1.19.1': { + directory: path.join(__dirname, './minecraft-assets/data/1.19.1/'), blocksTextures: require('./minecraft-assets/data/1.19.1/blocks_textures'), itemsTextures: require('./minecraft-assets/data/1.19.1/items_textures'), textureContent: require('./minecraft-assets/data/1.19.1/texture_content'), From 98578b751dc18566d466373180591821c152dc74 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Tue, 25 Jun 2024 04:06:59 +0000 Subject: [PATCH 11/11] fix --- index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.js b/index.js index 05981ed..11e8d47 100644 --- a/index.js +++ b/index.js @@ -131,6 +131,7 @@ Object.assign(data, { } }) +// Get {'1.18': ['1.18', '1.18.1', ...]} from ['1.18', '1.18.1', ...] const reduce = (what) => what.reduce((acc, cur) => { const major = cur.split('.').slice(0, 2).join('.') const arr = acc[major] = acc[major] || [] @@ -139,6 +140,8 @@ const reduce = (what) => what.reduce((acc, cur) => { }, {}) const cache = { pc: {}, bedrock: {} } // prevent reindexing when requiring multiple time the same version +const byMajor = { pc: reduce(Object.keys(data.pc)), bedrock: reduce(Object.keys(data.bedrock)) } +const lastOfMajor = (type, major) => byMajor[type][major][byMajor[type][major].length - 1] module.exports = function (registry) { if (typeof registry === 'string') registry = require('prismarine-registry')(registry)