Make generator config more robust

This commit is contained in:
Misode
2021-07-02 02:36:01 +02:00
parent cabd97cb39
commit f43cb03cc3
20 changed files with 158 additions and 172 deletions

View File

@@ -67,8 +67,7 @@ function Main() {
<Home path="/" {...{lang, changeTitle}} />
<FieldSettings path="/settings/fields" {...{lang, changeTitle}} />
<Worldgen path="/worldgen" {...{lang, changeTitle}} />
<Generator path="/:generator" {...{lang, version, changeTitle}} onChangeVersion={changeVersion} />
<Generator path="/worldgen/:generator" category="worldgen" {...{lang, version, changeTitle}} onChangeVersion={changeVersion} />
<Generator default {...{lang, version, changeTitle}} onChangeVersion={changeVersion} />
</Router>
</>
}

View File

@@ -66,7 +66,7 @@ async function getVersion(id: VersionId): Promise<VersionData> {
export async function getModel(version: VersionId, id: string): Promise<DataModel> {
if (!Models[id] || Models[id].version !== version) {
const versionData = await getVersion(version)
const schemaName = config.models.find(m => m.id === id)?.schema
const schemaName = config.generators.find(g => g.id === id)?.schema
if (!schemaName) {
throw new Error(`Cannot find model ${id}`)
}

View File

@@ -1,3 +1,5 @@
import config from '../config.json'
export function isPromise(obj: any): obj is Promise<any> {
return typeof (obj as any)?.then === 'function'
}
@@ -26,6 +28,11 @@ export function cleanUrl(url: string) {
return `/${url}/`.replaceAll('//', '/')
}
export function getGenerator(url: string) {
const trimmedUrl = url.replace(/^\//, '').replace(/\/$/, '')
return config.generators.find(g => g.url === trimmedUrl)
}
export function stringToColor(str: string): [number, number, number] {
const h = Math.abs(hashString(str))
return [h % 256, (h >> 8) % 256, (h >> 16) % 256]

View File

@@ -2,7 +2,7 @@ import { getCurrentUrl, Link } from 'preact-router'
import { Btn, BtnMenu, Icons, Octicon } from '.'
import config from '../../config.json'
import { locale } from '../Locales'
import { cleanUrl } from '../Utils'
import { cleanUrl, getGenerator } from '../Utils'
const Themes: Record<string, keyof typeof Octicon> = {
system: 'device_desktop',
@@ -20,8 +20,7 @@ type HeaderProps = {
}
export function Header({ lang, title, theme, changeTheme, language, changeLanguage }: HeaderProps) {
const loc = locale.bind(null, lang)
const id = getCurrentUrl().replace(/^\//, '').replace(/\/$/, '')
const category = config.models.find(m => m.id === id)?.category
const category = getGenerator(getCurrentUrl())?.category
return <header>
<div class="header-title">

View File

@@ -6,7 +6,7 @@ import { useModel } from '../hooks'
import type { VersionId } from '../Schemas'
import { BiomeSourcePreview, DecoratorPreview, NoiseSettingsPreview } from './previews'
export const HasPreview = ['dimension', 'worldgen/noise-settings', 'worldgen/feature']
export const HasPreview = ['dimension', 'worldgen/noise_settings', 'worldgen/configured_feature']
export const Previews: {
id: string,
@@ -30,14 +30,14 @@ export const Previews: {
},
{
id: 'noise-settings',
generator: 'worldgen/noise-settings',
generator: 'worldgen/noise_settings',
path: new Path(['noise']),
predicate: () => true,
preview: NoiseSettingsPreview,
},
{
id: 'decorator',
generator: 'worldgen/feature',
generator: 'worldgen/configured_feature',
path: new Path([]),
predicate: () => true,
preview: DecoratorPreview,

View File

@@ -1,4 +1,5 @@
import type { DataModel } from '@mcschema/core'
import { getCurrentUrl } from 'preact-router'
import { useEffect, useErrorBoundary, useState } from 'preact/hooks'
import config from '../../config.json'
import { Analytics } from '../Analytics'
@@ -7,17 +8,16 @@ import { fetchPreset } from '../DataFetcher'
import { locale } from '../Locales'
import type { BlockStateRegistry, VersionId } from '../Schemas'
import { checkVersion, getBlockStates, getCollections, getModel } from '../Schemas'
import { getGenerator } from '../Utils'
type GeneratorProps = {
lang: string,
changeTitle: (title: string, versions?: string[]) => unknown,
version: VersionId,
onChangeVersion: (version: VersionId) => unknown,
generator?: string,
path?: string,
category?: string,
default?: true,
}
export function Generator({ lang, changeTitle, version, onChangeVersion, category, generator }: GeneratorProps) {
export function Generator({ lang, changeTitle, version, onChangeVersion }: GeneratorProps) {
const loc = locale.bind(null, lang)
const [error, setError] = useState('')
const [errorBoundary] = useErrorBoundary()
@@ -25,19 +25,17 @@ export function Generator({ lang, changeTitle, version, onChangeVersion, categor
return <main><ErrorPanel error={`Something went wrong rendering the generator: ${errorBoundary.message}`}/></main>
}
const id = category ? `${category}/${generator}` : generator ?? ''
const modelConfig = config.models.find(m => m.id === id)
if (!modelConfig) {
return <main><ErrorPanel error={`Cannot find generator "${id}"`}/></main>
const generator = getGenerator(getCurrentUrl())
if (!generator) {
return <main><ErrorPanel error="Cannot find generator" /></main>
}
const minVersion = config.models.find(m => m.id === id)?.minVersion ?? '1.15'
const minVersion = generator.minVersion ?? '1.15'
const allowedVersions = config.versions
.filter(v => checkVersion(v.id, minVersion))
.map(v => v.id as VersionId)
changeTitle(loc('title.generator', loc(id)), allowedVersions)
changeTitle(loc('title.generator', loc(generator.id)), allowedVersions)
const [model, setModel] = useState<DataModel | null>(null)
const [blockStates, setBlockStates] = useState<BlockStateRegistry | null>(null)
@@ -45,10 +43,10 @@ export function Generator({ lang, changeTitle, version, onChangeVersion, categor
setModel(null)
getBlockStates(version)
.then(b => setBlockStates(b))
getModel(version, id)
getModel(version, generator.id)
.then(m => setModel(m))
.catch(e => setError(e.message))
}, [version, category, generator])
.catch(e => { console.error(e); setError(e.message) })
}, [version, generator.id])
const reset = () => {
Analytics.generatorEvent('reset')
@@ -83,25 +81,23 @@ export function Generator({ lang, changeTitle, version, onChangeVersion, categor
const [presetFilter, setPresetFilter] = useState('')
const [presetResults, setPresetResults] = useState<string[]>([])
const registry = (modelConfig.category ? modelConfig.category + '/' : '') + modelConfig.schema
useEffect(() => {
if (!modelConfig.path) return
getCollections(version)
.then(collections => {
const terms = (presetFilter ?? '').trim().split(' ')
const presets = collections.get(registry)
const presets = collections.get(generator.id)
.map(p => p.slice(10))
.filter(p => terms.every(t => p.includes(t)))
if (presets) {
setPresetResults(presets)
}
})
.catch(e => setError(e.message))
}, [version, category, generator, presetFilter])
.catch(e => { console.error(e); setError(e.message) })
}, [version, generator.id, presetFilter])
const loadPreset = (id: string) => {
Analytics.generatorEvent('load-preset', id)
fetchPreset(version, modelConfig.path!, id).then(preset => {
fetchPreset(version, generator.path ?? generator.id, id).then(preset => {
model?.reset(preset, false)
})
}
@@ -134,7 +130,7 @@ export function Generator({ lang, changeTitle, version, onChangeVersion, categor
const [previewShown, setPreviewShown] = useState(false)
const hasPreview = HasPreview.includes(id)
const hasPreview = HasPreview.includes(generator.id)
let actionsShown = 1
if (hasPreview) actionsShown += 1
if (sourceShown) actionsShown += 2
@@ -149,13 +145,13 @@ export function Generator({ lang, changeTitle, version, onChangeVersion, categor
<Ad id="data-pack-generator" type="text" />
<div class="controls">
<Btn icon="upload" label={loc('import')} onClick={importSource} />
{modelConfig.path && <BtnMenu icon="archive" label={loc('presets')} relative={false}>
<BtnMenu icon="archive" label={loc('presets')} relative={false}>
<BtnInput icon="search" large value={presetFilter} onChange={setPresetFilter} doSelect={1} />
<div class="result-list">
{presetResults.map(preset => <Btn label={preset} onClick={() => loadPreset(preset)} />)}
</div>
{presetResults.length === 0 && <Btn label={loc('no_presets')}/>}
</BtnMenu>}
</BtnMenu>
<BtnMenu icon="tag" label={version}>
{allowedVersions.reverse().map(v =>
<Btn label={v} active={v === version} onClick={() => onChangeVersion(v)} />
@@ -185,10 +181,10 @@ export function Generator({ lang, changeTitle, version, onChangeVersion, categor
</div>
</div>
<div class={`popup-preview${previewShown ? ' shown' : ''}`}>
<PreviewPanel {...{lang, model, version, id}} shown={previewShown} onError={setError} />
<PreviewPanel {...{lang, model, version, id: generator.id}} shown={previewShown} onError={setError} />
</div>
<div class={`popup-source${sourceShown ? ' shown' : ''}`}>
<SourcePanel {...{lang, model, blockStates, doCopy, doDownload, doImport}} name={modelConfig.schema ?? 'data'} onError={setError} />
<SourcePanel {...{lang, model, blockStates, doCopy, doDownload, doImport}} name={generator.schema ?? 'data'} onError={setError} />
</div>
</>
}

View File

@@ -13,9 +13,10 @@ export function Home({ lang, changeTitle }: HomeProps) {
changeTitle(loc('title.home'))
return <main>
<div class="home">
{config.models.filter(m => typeof m.category !== 'string').map(m =>
<ToolCard title={loc(m.id)} link={cleanUrl(m.id)} />
{config.generators.filter(g => !g.category).map(g =>
<ToolCard title={loc(g.id)} link={cleanUrl(g.url)} />
)}
<ToolCard title={loc('worldgen')} link="/worldgen/" />
<hr />
<ToolCard title="Report Inspector" icon="report" link="https://misode.github.io/report/">
<p>Analyse your performance reports</p>

View File

@@ -13,8 +13,8 @@ export function Worldgen({ lang, changeTitle }: WorldgenProps) {
changeTitle(loc('title.generator_category', loc('worldgen')))
return <main>
<div class="home">
{config.models.filter(m => m.category === 'worldgen').map(m =>
<ToolCard title={loc(m.id)} link={cleanUrl(m.id)} />
{config.generators.filter(g => g.category === 'worldgen').map(g =>
<ToolCard title={loc(g.id)} link={cleanUrl(g.url)} />
)}
</div>
</main>