import Split from 'split.js' import { Base, DataModel, locale, LOCALES, ModelPath, SourceView, TreeView, Path, } from '@mcschema/core' import { getCollections, getSchemas } from '@mcschema/java-1.16' import { VisualizerView } from './visualization/VisualizerView' import { RegistryFetcher } from './RegistryFetcher' import { ErrorsView } from './ErrorsView' import config from '../config.json' import { BiomeNoiseVisualizer } from './visualization/BiomeNoiseVisualizer' const LOCAL_STORAGE_THEME = 'theme' const LOCAL_STORAGE_LANGUAGE = 'language' const publicPath = process.env.NODE_ENV === 'production' ? '/dev/' : '/'; const modelFromPath = (p: string) => p.replace(publicPath, '').replace(/\/$/, '') const addChecked = (el: HTMLElement) => { el.classList.add('check') setTimeout(() => { el.classList.remove('check') }, 2000) } const treeViewObserver = (el: HTMLElement) => { el.querySelectorAll('.node-header[data-help]').forEach(e => { const div = document.createElement('div') div.className = 'node-icon' div.addEventListener('click', evt => { div.getElementsByTagName('span')[0].classList.add('show') document.body.addEventListener('click', evt => { div.getElementsByTagName('span')[0].classList.remove('show') }, { capture: true, once: true }) }) div.insertAdjacentHTML('beforeend', `${e.getAttribute('data-help')}`) e.appendChild(div) }) el.querySelectorAll('.node-header[data-error]').forEach(e => { const div = document.createElement('div') div.className = 'node-icon' div.addEventListener('click', evt => { div.getElementsByTagName('span')[0].classList.add('show') document.body.addEventListener('click', evt => { div.getElementsByTagName('span')[0].classList.remove('show') }, { capture: true, once: true }) }) div.insertAdjacentHTML('beforeend', `${e.getAttribute('data-error')}`) e.appendChild(div) }) el.querySelectorAll('.collapse.closed, button.add').forEach(e => { e.insertAdjacentHTML('afterbegin', ``) }) el.querySelectorAll('.collapse.open, button.remove').forEach(e => { e.insertAdjacentHTML('afterbegin', ``) }) } const treeViewNodeInjector = (path: ModelPath, view: TreeView) => { let res = VisualizerView.visualizers .filter(v => v.active(path)) .map(v => { const id = view.registerClick(() => { views.visualizer.set(v, path) }) return `` }) .join('') if (views.visualizer.active && views.visualizer.visualizer?.getName() === 'biome-noise') { if (path.startsWith(new Path(['generator', 'biome_source', 'biomes'])) && path.getArray().length === 4) { const biomeVisualizer = views.visualizer.visualizer as BiomeNoiseVisualizer const biome = path.push('biome').get() const id = view.registerChange(el => { biomeVisualizer.setBiomeColor(biome, (el as HTMLInputElement).value) views.visualizer.visualizer!.state = {} views.visualizer.invalidated() }) res += `` } } return res } const fetchLocale = async (id: string) => { const response = await fetch(publicPath + `locales/${id}.json`) LOCALES.register(id, await response.json()) } LOCALES.language = localStorage.getItem(LOCAL_STORAGE_LANGUAGE)?.toLowerCase() ?? 'en' const homeLink = document.getElementById('home-link')! const homeGenerators = document.getElementById('home-generators')! const categoryGenerators = document.getElementById('category-generators')! const selectedModel = document.getElementById('selected-model')! const modelSelector = document.getElementById('model-selector')! const modelSelectorMenu = document.getElementById('model-selector-menu')! const languageSelector = document.getElementById('language-selector')! const languageSelectorMenu = document.getElementById('language-selector-menu')! const themeSelector = document.getElementById('theme-selector')! const treeViewEl = document.getElementById('tree-view')! const sourceViewEl = document.getElementById('source-view')! const errorsViewEl = document.getElementById('errors-view')! const homeViewEl = document.getElementById('home-view')! const errorsToggle = document.getElementById('errors-toggle')! const sourceViewOutput = (document.getElementById('source-view-output') as HTMLTextAreaElement) const treeViewOutput = document.getElementById('tree-view-output')! const sourceControlsToggle = document.getElementById('source-controls-toggle')! const sourceControlsMenu = document.getElementById('source-controls-menu')! const sourceControlsCopy = document.getElementById('source-controls-copy')! const sourceControlsDownload = document.getElementById('source-controls-download')! const sourceToggle = document.getElementById('source-toggle')! const treeControlsToggle = document.getElementById('tree-controls-toggle')! const treeControlsMenu = document.getElementById('tree-controls-menu')! const treeControlsReset = document.getElementById('tree-controls-reset')! const treeControlsUndo = document.getElementById('tree-controls-undo')! const treeControlsRedo = document.getElementById('tree-controls-redo')! const visualizerOutput = document.getElementById('visualizer-output')! Split([treeViewEl, sourceViewEl], { sizes: [66, 34] }) Split([sourceViewOutput, visualizerOutput], { sizes: [60, 40], direction: 'vertical' }) const dummyModel = new DataModel(Base) const views = { 'tree': new TreeView(dummyModel, treeViewOutput, { showErrors: true, observer: treeViewObserver, nodeInjector: treeViewNodeInjector }), 'source': new SourceView(dummyModel, sourceViewOutput, { indentation: 2 }), 'errors': new ErrorsView(dummyModel, errorsViewEl), 'visualizer': new VisualizerView(dummyModel, visualizerOutput as HTMLCanvasElement) } const COLLECTIONS = getCollections() Promise.all([ fetchLocale(LOCALES.language), ...(LOCALES.language === 'en' ? [] : [fetchLocale('en')]), RegistryFetcher(COLLECTIONS, config.registries) ]).then(responses => { const SCHEMAS = getSchemas(COLLECTIONS) let models: { [key: string]: DataModel } = {} const buildModel = (model: any) => { if (model.schema) { models[model.id] = new DataModel(SCHEMAS.get(model.schema)) } else if (model.children) { model.children.forEach(buildModel) } } config.models.forEach(buildModel) let selected = '' Object.values(models).forEach(m => m.validate(true)) const updateModel = () => { let title = '' if (models[selected] === undefined) { title = locale('title.home') } else { title = locale('title.generator', [locale(selected)]) Object.values(views).forEach(v => v.setModel(models[selected])) models[selected].invalidate() } selectedModel.textContent = title document.title = title modelSelectorMenu.innerHTML = '' Object.keys(models).forEach(m => { modelSelectorMenu.insertAdjacentHTML('beforeend', `