diff --git a/src/app/App.ts b/src/app/App.ts index 9a8c2299..540d604a 100644 --- a/src/app/App.ts +++ b/src/app/App.ts @@ -40,7 +40,7 @@ export const Models: { config.models.filter(m => m.schema) .forEach(m => Models[m.id] = new DataModel(ObjectNode({}))) -export const BlockStateRegistry: { +export let BlockStateRegistry: { [block: string]: { properties: { [key: string]: string[] @@ -106,6 +106,7 @@ App.mobilePanel.watchRun((value) => { }) async function updateSchemas(version: string) { + BlockStateRegistry = {} const collections = Versions[version].getCollections() await fetchData(collections, version) const schemas = Versions[version].getSchemas(collections) diff --git a/src/app/DataFetcher.ts b/src/app/DataFetcher.ts index 9c1d4b08..82ba5f89 100644 --- a/src/app/DataFetcher.ts +++ b/src/app/DataFetcher.ts @@ -2,6 +2,8 @@ import { CollectionRegistry } from '@mcschema/core' import { BlockStateRegistry, checkVersion } from './App' import config from '../config.json' +const CACHE_FORMAT = 1 + type VersionConfig = { id: string, mcdata_ref: string @@ -27,59 +29,54 @@ export const fetchData = async (target: CollectionRegistry, versionId: string) = if (!version) return const cache = JSON.parse(localStorage.getItem(localStorageCache(versionId)) ?? '{}') - const cacheValid = version.mcdata_ref !== 'master' || cache.mcdata_hash === __MCDATA_MASTER_HASH__ + const cacheValid = cache.format === CACHE_FORMAT && (version.mcdata_ref !== 'master' || cache.mcdata_hash === __MCDATA_MASTER_HASH__) - const cacheDirty = (await Promise.all([ + await Promise.all([ fetchRegistries(target, version, cache, cacheValid), fetchBlockStateMap(version, cache, cacheValid) - ])).some(v => v) + ]) - if (cacheDirty) { + if (!cacheValid) { if (version.mcdata_ref === 'master') { cache.mcdata_hash = __MCDATA_MASTER_HASH__ } + cache.format = CACHE_FORMAT localStorage.setItem(localStorageCache(versionId), JSON.stringify(cache)) } } const fetchRegistries = async (target: CollectionRegistry, version: VersionConfig, cache: any, cacheValid: boolean) => { - let cacheDirty = false - if (!cache.registries) cache.registries = {} + if (cacheValid && cache.registries) { + config.registries.forEach((r: string | RegistryConfig) => { + if (typeof r === 'string') r = { id: r } + if (!checkVersion(version.id, r.minVersion, r.maxVersion)) return + + target.register(r.id, cache.registries[r.id]) + }) + return + } + + cache.registries = {} if (checkVersion('1.15', version.id)) { const url = `${baseUrl}/${version.mcdata_ref}/generated/reports/registries.json` - if (cacheValid && cache.registries) { - config.registries.forEach((r: string | RegistryConfig) => { + try { + const res = await fetch(url) + const data = await res.json() + config.registries.forEach(async (r: string | RegistryConfig) => { if (typeof r === 'string') r = { id: r } if (!checkVersion(version.id, r.minVersion, r.maxVersion)) return - target.register(r.id, cache.registries[r.id]) + const values = Object.keys(data[`minecraft:${r.id}`].entries) + target.register(r.id, values) + cache.registries[r.id] = values }) - } else { - try { - const res = await fetch(url) - const data = await res.json() - config.registries.forEach(async (r: string | RegistryConfig) => { - if (typeof r === 'string') r = { id: r } - if (!checkVersion(version.id, r.minVersion, r.maxVersion)) return - - const values = Object.keys(data[`minecraft:${r.id}`].entries) - target.register(r.id, values) - cache.registries[r.id] = values - cacheDirty = true - }) - } catch (e) { - console.warn(`Error occurred while fetching registries for version ${version.id}`) - } + } catch (e) { + console.warn(`Error occurred while fetching registries for version ${version.id}`) } } else { await Promise.all(config.registries.map(async (r: string | RegistryConfig) => { if (typeof r === 'string') r = { id: r } if (!checkVersion(version.id, r.minVersion, r.maxVersion)) return - - if (cacheValid && cache.registries?.[r.id]) { - target.register(r.id, cache.registries[r.id]) - return - } const url = r.path ? `${baseUrl}/${version.mcdata_ref}/${r.path}/data.min.json` @@ -91,13 +88,11 @@ const fetchRegistries = async (target: CollectionRegistry, version: VersionConfi target.register(r.id, data.values) cache.registries[r.id] = data.values - cacheDirty = true } catch (e) { console.warn(`Error occurred while fetching registry "${r.id}":`, e) } })) } - return cacheDirty } const fetchBlockStateMap = async (version: VersionConfig, cache: any, cacheValid: boolean) => { @@ -105,9 +100,10 @@ const fetchBlockStateMap = async (version: VersionConfig, cache: any, cacheValid Object.keys(cache.block_state_map).forEach(block => { BlockStateRegistry[block] = cache.block_state_map[block] }) - return false + return } + cache.block_state_map = {} const url = (checkVersion(version.id, undefined, '1.15')) ? `${baseUrl}/${version.mcdata_ref}/generated/reports/blocks.json` : `${baseUrl}/${version.mcdata_ref}/processed/reports/blocks/data.min.json` @@ -115,7 +111,6 @@ const fetchBlockStateMap = async (version: VersionConfig, cache: any, cacheValid const res = await fetch(url) const data = await res.json() - cache.block_state_map = {} Object.keys(data).forEach(block => { const res = { properties: data[block].properties, @@ -124,6 +119,4 @@ const fetchBlockStateMap = async (version: VersionConfig, cache: any, cacheValid BlockStateRegistry[block] = res cache.block_state_map[block] = res }) - - return true } diff --git a/src/app/hooks/renderHtml.ts b/src/app/hooks/renderHtml.ts index cfbed461..8355d095 100644 --- a/src/app/hooks/renderHtml.ts +++ b/src/app/hooks/renderHtml.ts @@ -1,10 +1,10 @@ -import { Hook, ModelPath, Path, StringHookParams, ValidationOption, EnumOption, INode, DataModel, MapNode, StringNode } from '@mcschema/core' +import { Hook, ModelPath, Path, StringHookParams, ValidationOption, EnumOption, INode, DataModel, MapNode, StringNode, relativePath } from '@mcschema/core' import { locale, segmentedLocale } from '../Locales' import { Mounter } from '../views/View' import { hexId, htmlEncode } from '../Utils' import { suffixInjector } from './suffixInjector' import { Octicon } from '../components/Octicon' -import { App } from '../App' +import { App, BlockStateRegistry } from '../App' /** * Secondary model used to remember the keys of a map @@ -105,13 +105,19 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = { return ['', suffix, body] }, - map({ keys, children }, path, value, mounter) { + map({ keys, children, config }, path, value, mounter) { const keyPath = new ModelPath(keysModel, new Path([hashString(path.toString())])) const onAdd = mounter.onClick(el => { const key = keyPath.get() path.model.set(path.push(key), children.default()) }) - const keyRendered = keys.hook(this, keyPath, keyPath.get() ?? '', mounter) + const blockState = (config.validation?.validator === 'block_state_map' ? BlockStateRegistry[relativePath(path, config.validation.params.id).get()] : null) + if (blockState && !blockState.properties) { + return ['', '', ''] + } + const keyRendered = (blockState + ? StringNode(null!, { enum: Object.keys(blockState.properties ?? {}) }) + : keys).hook(this, keyPath, keyPath.get() ?? '', mounter) const suffix = keyRendered[1] + `` let body = '' if (typeof value === 'object' && value !== undefined) { @@ -120,7 +126,9 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = { const removeId = mounter.onClick(el => path.model.set(path.push(key), undefined)) const childPath = path.modelPush(key) const category = children.category(childPath) - const [cPrefix, cSuffix, cBody] = children.hook(this, childPath, value[key], mounter) + const [cPrefix, cSuffix, cBody] = (blockState + ? StringNode(null!, { enum: blockState.properties[key] }) + : children).hook(this, childPath, value[key], mounter) return `
${error(childPath, mounter)}