import type { CollectionRegistry, INode, SchemaRegistry } from '@mcschema/core' import { ChoiceNode, DataModel, Reference, StringNode } from '@mcschema/core' import config from '../Config.js' import { initPartners } from '../partners/index.js' import { message } from '../Utils.js' import { fetchData } from './DataFetcher.js' export const VersionIds = ['1.15', '1.16', '1.17', '1.18', '1.18.2', '1.19'] as const export type VersionId = typeof VersionIds[number] export const DEFAULT_VERSION: VersionId = '1.19' export type BlockStateRegistry = { [block: string]: { properties?: { [key: string]: string[], }, default?: { [key: string]: string, }, }, } type VersionData = { collections: CollectionRegistry, schemas: SchemaRegistry, blockStates: BlockStateRegistry, } const Versions: Record> = {} type ModelData = { model: DataModel, version: VersionId, } const Models: Record = {} const versionGetter: { [versionId in VersionId]: () => Promise<{ getCollections: () => CollectionRegistry, getSchemas: (collections: CollectionRegistry) => SchemaRegistry, }> } = { 1.15: () => import('@mcschema/java-1.15'), 1.16: () => import('@mcschema/java-1.16'), 1.17: () => import('@mcschema/java-1.17'), 1.18: () => import('@mcschema/java-1.18'), '1.18.2': () => import('@mcschema/java-1.18.2'), 1.19: () => import('@mcschema/java-1.19'), } export let CachedDecorator: INode export let CachedFeature: INode export let CachedCollections: CollectionRegistry export let CachedSchemas: SchemaRegistry async function getVersion(id: VersionId): Promise { if (!Versions[id]) { Versions[id] = (async () => { try { const mcschema = await versionGetter[id]() const collections = mcschema.getCollections() const blockStates: BlockStateRegistry = {} await fetchData(id, collections, blockStates) const schemas = mcschema.getSchemas(collections) initPartners(schemas, collections) Versions[id] = { collections, schemas, blockStates } return Versions[id] } catch (e) { throw new Error(`Cannot get version "${id}": ${message(e)}`) } })() return Versions[id] } return Versions[id] } export async function getModel(version: VersionId, id: string): Promise { if (!Models[id] || Models[id].version !== version) { const versionData = await getVersion(version) CachedDecorator = Reference(versionData.schemas, 'configured_decorator') CachedFeature = ChoiceNode([ { type: 'string', node: StringNode(versionData.collections, { validator: 'resource', params: { pool: '$worldgen/configured_feature' } }), }, { type: 'object', node: Reference(versionData.schemas, 'configured_feature'), }, ], { choiceContext: 'feature' }) const schemaName = config.generators.find(g => g.id === id)?.schema if (!schemaName) { throw new Error(`Cannot find model ${id}`) } try { const schema = versionData.schemas.get(schemaName) const model = new DataModel(schema, { wrapLists: true }) if (Models[id]) { model.reset(Models[id].model.data, false) } else { model.validate(true) model.history = [JSON.stringify(model.data)] } Models[id] = { model, version } } catch (e) { const err = new Error(`Cannot get generator "${id}" for version "${version}": ${message(e)}`) if (e instanceof Error) err.stack = e.stack throw err } } return Models[id].model } export async function getCollections(version: VersionId): Promise { const versionData = await getVersion(version) CachedCollections = versionData.collections return versionData.collections } export async function getBlockStates(version: VersionId): Promise { const versionData = await getVersion(version) return versionData.blockStates } export async function getSchemas(version: VersionId): Promise { const versionData = await getVersion(version) CachedSchemas = versionData.schemas return versionData.schemas } export function checkVersion(versionId: string, minVersionId: string | undefined, maxVersionId?: string) { const version = config.versions.findIndex(v => v.id === versionId) const minVersion = minVersionId ? config.versions.findIndex(v => v.id === minVersionId) : 0 const maxVersion = maxVersionId ? config.versions.findIndex(v => v.id === maxVersionId) : config.versions.length - 1 return minVersion <= version && version <= maxVersion }