minecraft-renderer 0.1.103 → 0.1.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mesher.js +112 -106
- package/dist/mesher.js.map +4 -4
- package/dist/mesherWasm.js +250 -244
- package/dist/minecraft-renderer.js +60 -60
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +455 -449
- package/package.json +2 -2
- package/src/lib/mesherMcDataSupply.ts +41 -0
- package/src/lib/worldrendererCommon.ts +3 -1
- package/src/mesher-legacy/test/tests.test.ts +25 -2
- package/src/mesher-shared/mcDataWorkerShim.cjs +74 -0
- package/src/mesher-shared/mcDataWorkerShim.test.ts +87 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "minecraft-renderer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.105",
|
|
4
4
|
"description": "The most Modular Minecraft world renderer with Three.js WebGL backend",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"lil-gui": "^0.18.2",
|
|
81
81
|
"lodash": "^4.17.21",
|
|
82
82
|
"mc-assets": "^0.2.72",
|
|
83
|
-
"minecraft-data": "3.
|
|
83
|
+
"minecraft-data": "3.117.0",
|
|
84
84
|
"mineflayer": "^4.33.0",
|
|
85
85
|
"npm-run-all": "^4.1.5",
|
|
86
86
|
"prettier": "^3.8.4",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import MinecraftData, { IndexedData } from 'minecraft-data'
|
|
3
|
+
import pcFeatures from 'minecraft-data/minecraft-data/data/pc/common/features.json'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Version tables the mesher workers need to behave like `minecraft-data`.
|
|
7
|
+
* The worker bundles don't contain any (see src/mesher-shared/mcDataWorkerShim.cjs), they are supplied with the `mcData` message
|
|
8
|
+
* so the workers support every version the main thread's `minecraft-data` supports.
|
|
9
|
+
*/
|
|
10
|
+
export type MesherVersionTables = {
|
|
11
|
+
/** pc protocolVersions, newest first (same order as minecraft-data); only the fields needed for comparisons */
|
|
12
|
+
protocolVersions: Array<{ minecraftVersion: string; majorVersion: string; dataVersion?: number; version?: number }>
|
|
13
|
+
/** `supportFeature(name)` resolved for the current version */
|
|
14
|
+
features: Record<string, unknown>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let protocolVersionsCache: MesherVersionTables['protocolVersions'] | undefined
|
|
18
|
+
const featuresCache = new WeakMap<object, MesherVersionTables['features']>()
|
|
19
|
+
|
|
20
|
+
export const getMesherVersionTables = (mcDataFull: IndexedData): MesherVersionTables => {
|
|
21
|
+
protocolVersionsCache ??= MinecraftData.versions.pc.map(({ minecraftVersion, majorVersion, dataVersion, version }: any) => ({
|
|
22
|
+
minecraftVersion,
|
|
23
|
+
majorVersion,
|
|
24
|
+
dataVersion,
|
|
25
|
+
version
|
|
26
|
+
}))
|
|
27
|
+
|
|
28
|
+
let features = featuresCache.get(mcDataFull)
|
|
29
|
+
if (!features) {
|
|
30
|
+
features = {}
|
|
31
|
+
// bedrock features are not used by the mesher
|
|
32
|
+
if (mcDataFull.type === 'pc') {
|
|
33
|
+
for (const { name } of pcFeatures as Array<{ name: string }>) {
|
|
34
|
+
features[name] = mcDataFull.supportFeature(name as any)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
featuresCache.set(mcDataFull, features)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return { protocolVersions: protocolVersionsCache, features }
|
|
41
|
+
}
|
|
@@ -8,6 +8,7 @@ import { subscribeKey } from 'valtio/utils'
|
|
|
8
8
|
import { proxy, subscribe } from 'valtio'
|
|
9
9
|
import type { ResourcesManagerTransferred } from '../resourcesManager/resourcesManager'
|
|
10
10
|
import { dynamicMcDataFiles } from './buildSharedConfig.mjs'
|
|
11
|
+
import { getMesherVersionTables } from './mesherMcDataSupply'
|
|
11
12
|
import { DisplayWorldOptions, GraphicsInitOptions, RendererReactiveState, SoundSystem, UpdateCameraOptions } from '../graphicsBackend/types'
|
|
12
13
|
import {
|
|
13
14
|
HighestBlockInfo,
|
|
@@ -1587,7 +1588,8 @@ let mesherMcDataTintsMissingWarned = false
|
|
|
1587
1588
|
|
|
1588
1589
|
export const meshersSendMcData = (workers: Worker[], version: string, mcDataKeys = dynamicMcDataFiles, mcDataFull: IndexedData) => {
|
|
1589
1590
|
const mcData: { version: IndexedData['version']; tints?: unknown; [key: string]: unknown } = {
|
|
1590
|
-
version: JSON.parse(JSON.stringify(mcDataFull.version))
|
|
1591
|
+
version: JSON.parse(JSON.stringify(mcDataFull.version)),
|
|
1592
|
+
...getMesherVersionTables(mcDataFull)
|
|
1591
1593
|
}
|
|
1592
1594
|
for (const [finalKey, sourceKey] of Object.entries(mcDataKeys)) {
|
|
1593
1595
|
mcData[finalKey] = mcDataFull[sourceKey]
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
//@ts-nocheck
|
|
2
2
|
import { test, expect } from 'vitest'
|
|
3
|
-
import { versions } from 'minecraft-data'
|
|
3
|
+
import minecraftData, { versions } from 'minecraft-data'
|
|
4
4
|
import { INVISIBLE_BLOCKS } from '../../mesher-shared/worldConstants'
|
|
5
5
|
import { setup } from './mesherTester'
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
// newest release that minecraft-data has data for (its protocol versions list can run ahead of the data, e.g. 26.2 / 26.3)
|
|
8
|
+
const lastVersion = versions.pc
|
|
9
|
+
.map(x => x.minecraftVersion)
|
|
10
|
+
.filter(version => !/w|-pre|-rc|-snapshot/.test(version))
|
|
11
|
+
.find(version => minecraftData(version))!
|
|
8
12
|
|
|
9
13
|
const addPositions = [
|
|
10
14
|
// [[0, 0, 0], 'diamond_block'],
|
|
@@ -48,9 +52,28 @@ test('Known blocks are not rendered', () => {
|
|
|
48
52
|
console.log('Average time', time / times)
|
|
49
53
|
// should be fixed, but to avoid regressions & for visibility
|
|
50
54
|
// TODO resolve creaking_heart issue (1.21.3)
|
|
55
|
+
// TODO 26.x: copper chests / copper golem statues (block entity models) and golden_dandelion have no block model yet
|
|
51
56
|
expect(missingBlocks).toMatchInlineSnapshot(`
|
|
52
57
|
{
|
|
58
|
+
"copper_chest": true,
|
|
59
|
+
"copper_golem_statue": true,
|
|
60
|
+
"exposed_copper_chest": true,
|
|
61
|
+
"exposed_copper_golem_statue": true,
|
|
62
|
+
"golden_dandelion": true,
|
|
63
|
+
"oxidized_copper_chest": true,
|
|
64
|
+
"oxidized_copper_golem_statue": true,
|
|
65
|
+
"potted_golden_dandelion": true,
|
|
53
66
|
"structure_void": true,
|
|
67
|
+
"waxed_copper_chest": true,
|
|
68
|
+
"waxed_copper_golem_statue": true,
|
|
69
|
+
"waxed_exposed_copper_chest": true,
|
|
70
|
+
"waxed_exposed_copper_golem_statue": true,
|
|
71
|
+
"waxed_oxidized_copper_chest": true,
|
|
72
|
+
"waxed_oxidized_copper_golem_statue": true,
|
|
73
|
+
"waxed_weathered_copper_chest": true,
|
|
74
|
+
"waxed_weathered_copper_golem_statue": true,
|
|
75
|
+
"weathered_copper_chest": true,
|
|
76
|
+
"weathered_copper_golem_statue": true,
|
|
54
77
|
}
|
|
55
78
|
`)
|
|
56
79
|
expect(erroredBlocks).toMatchInlineSnapshot('{}')
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Version-agnostic replacement for `minecraft-data` inside the mesher worker bundles (see scripts/buildWorkerShared.mjs).
|
|
2
|
+
//
|
|
3
|
+
// The real package would bake its version tables (data.js, protocolVersions.json, features.json) into the bundle at build
|
|
4
|
+
// time, so a worker could only ever load versions that the renderer's devDependency knew about. Nothing version-specific is
|
|
5
|
+
// bundled here: everything is read lazily from `globalThis.mcData`, which the main thread supplies with the `mcData`
|
|
6
|
+
// message (see `meshersSendMcData`):
|
|
7
|
+
// - `version` IndexedData['version'] of the current version
|
|
8
|
+
// - `protocolVersions` pc protocolVersions list (used for version comparisons)
|
|
9
|
+
// - `features` `supportFeature(name)` already resolved for the current version
|
|
10
|
+
// - everything else data files (blocks, biomes, blockCollisionShapes, tints, ...)
|
|
11
|
+
const mcDataToNode = require('minecraft-data/lib/loader')
|
|
12
|
+
const indexer = require('minecraft-data/lib/indexer.js')
|
|
13
|
+
|
|
14
|
+
function createVersion (type, suppliedVersion, protocolVersions) {
|
|
15
|
+
const versions = indexer.buildIndexFromArray(protocolVersions, 'minecraftVersion') ?? {}
|
|
16
|
+
// Allows comparisons against majorVersion even if `other` is not present in the versions list (e.g. 1.17.0 exists but not 1.17)
|
|
17
|
+
for (const key in versions) {
|
|
18
|
+
const versionObj = versions[key]
|
|
19
|
+
if (versionObj.minecraftVersion.endsWith('.0')) versions[versionObj.majorVersion] = versionObj
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const self = {}
|
|
23
|
+
// the supplied dataVersion is authoritative: the current version doesn't have to be present in the supplied list
|
|
24
|
+
self.dataVersion = suppliedVersion.dataVersion ?? versions[suppliedVersion.minecraftVersion]?.dataVersion
|
|
25
|
+
const v1 = self.dataVersion ?? 0
|
|
26
|
+
const raise = other => { throw new RangeError(`Version '${other}' not found in protocolVersions supplied by the main thread for ${type}`) }
|
|
27
|
+
self['>='] = other => versions[other] ? v1 >= versions[other].dataVersion : raise(other)
|
|
28
|
+
self['>'] = other => versions[other] ? v1 > versions[other].dataVersion : raise(other)
|
|
29
|
+
self['<'] = other => versions[other] ? v1 < versions[other].dataVersion : raise(other)
|
|
30
|
+
self['<='] = other => versions[other] ? v1 <= versions[other].dataVersion : raise(other)
|
|
31
|
+
self['=='] = other => versions[other] ? v1 === versions[other].dataVersion : raise(other)
|
|
32
|
+
self.type = type
|
|
33
|
+
self.majorVersion = suppliedVersion.majorVersion
|
|
34
|
+
return self
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let cache = null
|
|
38
|
+
|
|
39
|
+
module.exports = function (mcVersion) {
|
|
40
|
+
const supplied = globalThis.mcData
|
|
41
|
+
const suppliedVersion = supplied?.version
|
|
42
|
+
if (!suppliedVersion) return null // not supplied (yet)
|
|
43
|
+
|
|
44
|
+
const requested = String(mcVersion)
|
|
45
|
+
// a worker only ever works with the single version it was supplied data for
|
|
46
|
+
if (requested !== suppliedVersion.minecraftVersion && requested !== suppliedVersion.majorVersion && requested !== String(suppliedVersion.version)) return null
|
|
47
|
+
|
|
48
|
+
if (cache?.src === supplied) return cache.value
|
|
49
|
+
|
|
50
|
+
const type = suppliedVersion.type ?? 'pc'
|
|
51
|
+
const protocolVersions = supplied.protocolVersions ?? []
|
|
52
|
+
protocolVersions.forEach((entry, i) => {
|
|
53
|
+
// same as minecraft-data: bottom entries are lower
|
|
54
|
+
if (!entry.dataVersion) entry.dataVersion = -i
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const { version: _version, protocolVersions: _protocolVersions, features: _features, ...files } = supplied
|
|
58
|
+
const nmcData = mcDataToNode({ ...files, version: suppliedVersion })
|
|
59
|
+
nmcData.type = type
|
|
60
|
+
nmcData.isNewerOrEqualTo = version => nmcData.version['>='](version)
|
|
61
|
+
nmcData.isOlderThan = version => nmcData.version['<'](version)
|
|
62
|
+
nmcData.version = Object.assign(createVersion(type, suppliedVersion, protocolVersions), nmcData.version)
|
|
63
|
+
const features = supplied.features ?? {}
|
|
64
|
+
nmcData.supportFeature = featureName => features[featureName] || false
|
|
65
|
+
|
|
66
|
+
cache = { src: supplied, value: nmcData }
|
|
67
|
+
return nmcData
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Used eagerly by prismarine-block (preflat id mapping), static and version independent
|
|
71
|
+
module.exports.legacy = {
|
|
72
|
+
pc: require('minecraft-data/minecraft-data/data/pc/common/legacy.json'),
|
|
73
|
+
bedrock: {}
|
|
74
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import { createRequire } from 'module'
|
|
3
|
+
import { afterEach, describe, expect, it } from 'vitest'
|
|
4
|
+
import MinecraftData from 'minecraft-data'
|
|
5
|
+
import { getMesherVersionTables } from '../lib/mesherMcDataSupply'
|
|
6
|
+
|
|
7
|
+
const require = createRequire(import.meta.url)
|
|
8
|
+
const loadShim = () => {
|
|
9
|
+
delete require.cache[require.resolve('./mcDataWorkerShim.cjs')]
|
|
10
|
+
return require('./mcDataWorkerShim.cjs') as (version: string) => any
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** What `meshersSendMcData` sends to the workers */
|
|
14
|
+
const supplyFor = (version: string) => {
|
|
15
|
+
const full = MinecraftData(version)
|
|
16
|
+
return {
|
|
17
|
+
full,
|
|
18
|
+
mcData: {
|
|
19
|
+
version: JSON.parse(JSON.stringify(full.version)),
|
|
20
|
+
...getMesherVersionTables(full),
|
|
21
|
+
blocks: full.blocksArray,
|
|
22
|
+
biomes: full.biomesArray,
|
|
23
|
+
blockCollisionShapes: full.blockCollisionShapes
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe('mesher worker minecraft-data shim', () => {
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
delete (globalThis as any).mcData
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('returns null until data is supplied', () => {
|
|
34
|
+
expect(loadShim()('1.20.4')).toBeNull()
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it.each(['1.8.8', '1.16.5', '1.20.4', '1.21.8'])('behaves like minecraft-data for %s', version => {
|
|
38
|
+
const { full, mcData } = supplyFor(version)
|
|
39
|
+
;(globalThis as any).mcData = mcData
|
|
40
|
+
const shimmed = loadShim()(version)
|
|
41
|
+
|
|
42
|
+
expect(shimmed.version.minecraftVersion).toBe(version)
|
|
43
|
+
expect(shimmed.type).toBe('pc')
|
|
44
|
+
expect(shimmed.blocksByName.stone.id).toBe(full.blocksByName.stone.id)
|
|
45
|
+
expect(shimmed.blocksByStateId[full.blocksByName.stone.defaultState].name).toBe('stone')
|
|
46
|
+
expect(shimmed.biomes[full.biomesArray[0].id].name).toBe(full.biomesArray[0].name)
|
|
47
|
+
for (const feature of ['blockStateId', 'theFlattening', 'usesBlockStates', 'itemsAreNotBlocks', 'sendsClientTickEndPacket']) {
|
|
48
|
+
expect(shimmed.supportFeature(feature)).toBe(full.supportFeature(feature as any))
|
|
49
|
+
}
|
|
50
|
+
for (const other of ['1.8', '1.12.2', '1.16.5', '1.21.1']) {
|
|
51
|
+
expect(shimmed.isNewerOrEqualTo(other)).toBe(full.isNewerOrEqualTo(other))
|
|
52
|
+
expect(shimmed.isOlderThan(other)).toBe(full.isOlderThan(other))
|
|
53
|
+
}
|
|
54
|
+
expect(shimmed.supportFeature('unknownFeature')).toBe(false)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('works with a version that is not in anything bundled with the worker', () => {
|
|
58
|
+
const { mcData } = supplyFor('1.21.8')
|
|
59
|
+
const newest = mcData.protocolVersions[0]
|
|
60
|
+
// a version from the future: only the main thread knows it
|
|
61
|
+
const future = { ...mcData.version, minecraftVersion: '99.9', majorVersion: '99', dataVersion: (newest.dataVersion ?? 0) + 1000, version: 9999 }
|
|
62
|
+
;(globalThis as any).mcData = {
|
|
63
|
+
...mcData,
|
|
64
|
+
version: future,
|
|
65
|
+
protocolVersions: [{ ...future }, ...mcData.protocolVersions],
|
|
66
|
+
features: { ...mcData.features, someFutureFeature: true }
|
|
67
|
+
}
|
|
68
|
+
const shimmed = loadShim()('99.9')
|
|
69
|
+
|
|
70
|
+
expect(shimmed).not.toBeNull()
|
|
71
|
+
expect(shimmed.version.minecraftVersion).toBe('99.9')
|
|
72
|
+
expect(shimmed.isNewerOrEqualTo('1.21.8')).toBe(true)
|
|
73
|
+
expect(shimmed.isOlderThan('1.21.8')).toBe(false)
|
|
74
|
+
expect(shimmed.supportFeature('someFutureFeature')).toBe(true)
|
|
75
|
+
// the worker only knows the version it was supplied
|
|
76
|
+
expect(loadShim()('1.21.8')).toBeNull()
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('picks up newly supplied data (worker reconfigure)', () => {
|
|
80
|
+
;(globalThis as any).mcData = supplyFor('1.16.5').mcData
|
|
81
|
+
const shim = loadShim()
|
|
82
|
+
expect(shim('1.16.5').version.minecraftVersion).toBe('1.16.5')
|
|
83
|
+
;(globalThis as any).mcData = supplyFor('1.20.4').mcData
|
|
84
|
+
expect(shim('1.20.4').version.minecraftVersion).toBe('1.20.4')
|
|
85
|
+
expect(shim('1.16.5')).toBeNull()
|
|
86
|
+
})
|
|
87
|
+
})
|