diff --git a/src/app/Main.tsx b/src/app/Main.tsx index 86579dc1..85845ca9 100644 --- a/src/app/Main.tsx +++ b/src/app/Main.tsx @@ -62,7 +62,7 @@ function Main() { } return <> -
+
diff --git a/src/app/Schemas.ts b/src/app/Schemas.ts index 68594d0a..258b1cf5 100644 --- a/src/app/Schemas.ts +++ b/src/app/Schemas.ts @@ -11,10 +11,10 @@ export type VersionId = typeof VersionIds[number] export type BlockStateRegistry = { [block: string]: { - properties: { + properties?: { [key: string]: string[], }, - default: { + default?: { [key: string]: string, }, }, diff --git a/src/app/components/Header.tsx b/src/app/components/Header.tsx index 39009a06..4ef0ee41 100644 --- a/src/app/components/Header.tsx +++ b/src/app/components/Header.tsx @@ -1,7 +1,9 @@ -import { getCurrentUrl, Link } from 'preact-router' +import { getCurrentUrl, Link, route } from 'preact-router' import { Btn, BtnMenu, Icons, Octicon } from '.' import config from '../../config.json' import { locale } from '../Locales' +import type { VersionId } from '../Schemas' +import { checkVersion } from '../Schemas' import { cleanUrl, getGenerator } from '../Utils' const Themes: Record = { @@ -13,21 +15,27 @@ const Themes: Record = { type HeaderProps = { lang: string, title: string, + version: VersionId, theme: string, changeTheme: (theme: string) => unknown, language: string, changeLanguage: (language: string) => unknown, } -export function Header({ lang, title, theme, changeTheme, language, changeLanguage }: HeaderProps) { +export function Header({ lang, title, version, theme, changeTheme, language, changeLanguage }: HeaderProps) { const loc = locale.bind(null, lang) - const category = getGenerator(getCurrentUrl())?.category + const gen = getGenerator(getCurrentUrl()) return
-
- - {Icons.home} - +
+ {Icons.home}

{title}

+ {gen && + {config.generators + .filter(g => g.category === gen?.category && checkVersion(version, g.minVersion)) + .map(g => + route(cleanUrl(g.url))} /> + )} + }
- +
- +
} diff --git a/src/app/schema/renderHtml.ts b/src/app/schema/renderHtml.ts index 9347a987..a982e279 100644 --- a/src/app/schema/renderHtml.ts +++ b/src/app/schema/renderHtml.ts @@ -16,7 +16,7 @@ export type TreeProps = { const selectRegistries = ['loot_table.type', 'loot_entry.type', 'function.function', 'condition.condition', 'criterion.trigger', 'dimension.generator.type', 'dimension.generator.biome_source.type', 'carver.type', 'feature.type', 'decorator.type', 'feature.tree.minimum_size.type', 'block_state_provider.type', 'trunk_placer.type', 'foliage_placer.type', 'tree_decorator.type', 'int_provider.type', 'float_provider.type', 'height_provider.type', 'structure_feature.type', 'surface_builder.type', 'processor.processor_type', 'rule_test.predicate_type', 'pos_rule_test.predicate_type', 'template_element.element_type', 'block_placer.type'] const hiddenFields = ['number_provider.type', 'score_provider.type', 'nbt_provider.type', 'int_provider.type', 'float_provider.type', 'height_provider.type'] const flattenedFields = ['feature.config', 'decorator.config', 'int_provider.value', 'float_provider.value', 'block_state_provider.simple_state_provider.state', 'block_state_provider.rotated_block_provider.state', 'block_state_provider.weighted_state_provider.entries.entry.data', 'rule_test.block_state', 'structure_feature.config', 'surface_builder.config', 'template_pool.elements.entry.element'] -const inlineFields = ['loot_entry.type', 'function.function', 'condition.condition', 'criterion.trigger', 'dimension.generator.type', 'dimension.generator.biome_source.type', 'feature.type', 'decorator.type', 'block_state_provider.type', 'feature.tree.minimum_size.type', 'trunk_placer.type', 'foliage_placer.type', 'tree_decorator.type', 'block_placer.type', 'rule_test.predicate_type', 'processor.processor_type', 'template_element.element_type'] +const inlineFields = ['loot_entry.type', 'function.function', 'condition.condition', 'criterion.trigger', 'dimension.generator.type', 'dimension.generator.biome_source.type', 'feature.type', 'decorator.type', 'block_state_provider.type', 'feature.tree.minimum_size.type', 'trunk_placer.type', 'foliage_placer.type', 'tree_decorator.type', 'block_placer.type', 'rule_test.predicate_type', 'processor.processor_type', 'template_element.element_type', 'nbt_operation.op', 'number_provider.value', 'score_provider.name', 'score_provider.target', 'nbt_provider.source', 'nbt_provider.target'] /** * Secondary model used to remember the keys of a map @@ -132,9 +132,9 @@ export const renderHtml: Hook<[any, TreeProps], [string, string, string]> = { const suffix = keyRendered[1] + `` if (blockState && path.last() === 'Properties') { if (typeof value !== 'object') value = {} - const properties = Object.entries(blockState.properties) + const properties = Object.entries(blockState.properties ?? {}) .map(([key, values]) => [key, StringNode(null!, { enum: values })]) - Object.entries(blockState.properties).forEach(([key, values]) => { + Object.entries(blockState.properties ?? {}).forEach(([key, values]) => { if (typeof value[key] !== 'string') { path.model.errors.add(path.push(key), 'error.expected_string') } else if (!values.includes(value[key])) { @@ -151,9 +151,9 @@ export const renderHtml: Hook<[any, TreeProps], [string, string, string]> = { const childPath = path.modelPush(key) const category = children.category(childPath) const childrenSchema = blockState - ? StringNode(null!, { enum: blockState.properties[key] ?? [] }) + ? StringNode(null!, { enum: blockState.properties?.[key] ?? [] }) : children - if (blockState?.properties[key] && !blockState.properties[key].includes(value[key])) { + if (blockState?.properties?.[key] && !blockState.properties?.[key].includes(value[key])) { path.model.errors.add(childPath, 'error.invalid_enum_option', value[key]) } const [cPrefix, cSuffix, cBody] = childrenSchema.hook(this, childPath, value[key], props) diff --git a/src/app/schema/transformOutput.ts b/src/app/schema/transformOutput.ts index 03f3866b..68303dcb 100644 --- a/src/app/schema/transformOutput.ts +++ b/src/app/schema/transformOutput.ts @@ -27,7 +27,7 @@ export const transformOutput: Hook<[any, OutputProps], any> = { const res: any = {} Object.keys(value).forEach(f => { if (blockState) { - if (!Object.keys(blockState.properties).includes(f)) return + if (!Object.keys(blockState.properties ?? {}).includes(f)) return } res[f] = children.hook(this, path.push(f), value[f], props) }) diff --git a/src/locales/de.json b/src/locales/de.json index b3cf1dfc..0664d419 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -10,7 +10,7 @@ "preview": "Visualisieren", "reset": "Zurücksetzen", "share": "Teilen", - "title.generator": "%0%_Generator", + "title.generator": "%0%-Generator", "title.home": "Datenpaketgeneratoren", "worldgen/biome": "Biom", "worldgen/configured_carver": "Borer", diff --git a/src/styles/global.css b/src/styles/global.css index d59dfe5b..aeb3bb72 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -99,12 +99,12 @@ body[data-panel="settings"] header { position: fixed; } -.header-title { +.title { display: flex; align-items: center; } -.header-title h2 { +.title h2 { color: var(--nav); } @@ -170,14 +170,23 @@ nav li svg { height: 24px; } -nav li .btn-menu > .btn { +.title .btn-menu { + margin: 0 8px; +} + +.title .btn-menu > .btn svg { + width: 24px; + height: 24px; +} + +header .btn-menu > .btn { background: none !important; padding: 0; box-shadow: none; fill: var(--nav); } -nav li .btn-menu > .btn:hover { +header .btn-menu > .btn:hover { fill: var(--nav-hover); } @@ -683,8 +692,8 @@ hr { /* SMALL */ @media screen and (max-width: 580px) { - .header-title h2 { - font-size: 22px; + .title h2 { + font-size: 18px; } body nav li {