diff --git a/package-lock.json b/package-lock.json index 9c724a56..4419a845 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "MIT", "dependencies": { "@giscus/react": "^1.1.2", - "@mcschema/core": "^0.12.34", + "@mcschema/core": "^0.12.35", "@mcschema/java-1.15": "^0.2.5", "@mcschema/java-1.16": "^0.6.9", "@mcschema/java-1.17": "^0.2.28", @@ -400,9 +400,9 @@ } }, "node_modules/@mcschema/core": { - "version": "0.12.34", - "resolved": "https://registry.npmjs.org/@mcschema/core/-/core-0.12.34.tgz", - "integrity": "sha512-LnOOcsjFfkWkvlsGJCPQA9C59gcb6n7Zlyoifmz4S+sfBNFpxbeB2dqdXeFnsETIAnYF3IbyhdQN6mtoJaLTyA==" + "version": "0.12.35", + "resolved": "https://registry.npmjs.org/@mcschema/core/-/core-0.12.35.tgz", + "integrity": "sha512-6qGgtjFQnGuxp61/wnIs/mB+/kLGkcBza5kSS7QlwPtHNAv6e15fchh5LzJAy8jYaM5cpEuNnR5N4zrFmw2BwQ==" }, "node_modules/@mcschema/java-1.15": { "version": "0.2.5", @@ -5432,9 +5432,9 @@ "requires": {} }, "@mcschema/core": { - "version": "0.12.34", - "resolved": "https://registry.npmjs.org/@mcschema/core/-/core-0.12.34.tgz", - "integrity": "sha512-LnOOcsjFfkWkvlsGJCPQA9C59gcb6n7Zlyoifmz4S+sfBNFpxbeB2dqdXeFnsETIAnYF3IbyhdQN6mtoJaLTyA==" + "version": "0.12.35", + "resolved": "https://registry.npmjs.org/@mcschema/core/-/core-0.12.35.tgz", + "integrity": "sha512-6qGgtjFQnGuxp61/wnIs/mB+/kLGkcBza5kSS7QlwPtHNAv6e15fchh5LzJAy8jYaM5cpEuNnR5N4zrFmw2BwQ==" }, "@mcschema/java-1.15": { "version": "0.2.5", diff --git a/package.json b/package.json index 1e5e1c5d..b9a1b45b 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "license": "MIT", "dependencies": { "@giscus/react": "^1.1.2", - "@mcschema/core": "^0.12.34", + "@mcschema/core": "^0.12.35", "@mcschema/java-1.15": "^0.2.5", "@mcschema/java-1.16": "^0.6.9", "@mcschema/java-1.17": "^0.2.28", diff --git a/src/app/App.tsx b/src/app/App.tsx index e6c0017e..a28779d1 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -4,7 +4,7 @@ import '../styles/global.css' import '../styles/nodes.css' import { Analytics } from './Analytics' import { Header } from './components' -import { Category, Changelog, Generator, Guide, Guides, Home, Project, Sounds, Versions } from './pages' +import { Category, Changelog, Generator, Guide, Guides, Home, Partners, Project, Sounds, Versions } from './pages' import { cleanUrl } from './Utils' export function App() { @@ -20,6 +20,7 @@ export function App() { + diff --git a/src/app/components/Header.tsx b/src/app/components/Header.tsx index 5814bea0..45909032 100644 --- a/src/app/components/Header.tsx +++ b/src/app/components/Header.tsx @@ -26,7 +26,7 @@ export function Header() { {config.generators .filter(g => g.category === gen?.category && checkVersion(version, g.minVersion)) .map(g => - route(cleanUrl(g.url))} /> + route(cleanUrl(g.url))} /> )} } diff --git a/src/app/contexts/Locale.tsx b/src/app/contexts/Locale.tsx index acaa8f1a..ef757286 100644 --- a/src/app/contexts/Locale.tsx +++ b/src/app/contexts/Locale.tsx @@ -45,7 +45,11 @@ async function loadLocale(language: string) { const data = await import(`../../locales/${language}.json`) const schema = langConfig.schemas !== false && await import(`../../../node_modules/@mcschema/locales/src/${language}.json`) - Locales[language] = { ...data.default, ...schema.default } + let partners = { default: {} } + if (language === 'en') { + partners = await import('../partners/locales/en.json') + } + Locales[language] = { ...data.default, ...schema.default, ...partners.default } } export function useLocale() { diff --git a/src/app/contexts/Project.tsx b/src/app/contexts/Project.tsx index 57ee9fd3..324761da 100644 --- a/src/app/contexts/Project.tsx +++ b/src/app/contexts/Project.tsx @@ -124,6 +124,9 @@ export function ProjectProvider({ children }: { children: ComponentChildren }) { export function getFilePath(file: ProjectFile) { const [namespace, id] = file.id.includes(':') ? file.id.split(':') : ['minecraft', file.id] + if (file.type === 'pack_mcmeta') { + return 'pack.mcmeta' + } const gen = config.generators.find(g => g.id === file.type) if (!gen) { throw new Error(`Cannot find generator of type ${file.type}`) diff --git a/src/app/pages/Generator.tsx b/src/app/pages/Generator.tsx index 95fc2ff6..5a974884 100644 --- a/src/app/pages/Generator.tsx +++ b/src/app/pages/Generator.tsx @@ -40,7 +40,7 @@ export function Generator({}: Props) { .reverse() }, [gen.minVersion, gen.maxVersion]) - useTitle(locale('title.generator', locale(gen.id)), allowedVersions) + useTitle(locale('title.generator', locale(gen.partner ? `partner.${gen.partner}.${gen.id}` : gen.id)), allowedVersions) if (!checkVersion(version, gen.minVersion)) { setError(`The minimum version for this generator is ${gen.minVersion}`) @@ -210,7 +210,7 @@ export function Generator({}: Props) { const [presets, setPresets] = useState([]) useEffect(() => { getCollections(version).then(collections => { - setPresets(collections.get(gen.id).map(p => p.slice(10))) + setPresets(collections.get(gen.id).map(p => p.startsWith('minecraft:') ? p.slice(10) : p)) }) .catch(e => { console.error(e); setError(e) }) }, [version, gen.id]) @@ -341,7 +341,7 @@ export function Generator({}: Props) { return <>
- + {!gen.partner && }
diff --git a/src/app/pages/Home.tsx b/src/app/pages/Home.tsx index 8e7f0b13..6bfd6a20 100644 --- a/src/app/pages/Home.tsx +++ b/src/app/pages/Home.tsx @@ -22,6 +22,7 @@ export function Home({}: Props) { )} + diff --git a/src/app/pages/Partners.tsx b/src/app/pages/Partners.tsx new file mode 100644 index 00000000..2338382d --- /dev/null +++ b/src/app/pages/Partners.tsx @@ -0,0 +1,27 @@ +import config from '../../config.json' +import { ToolCard } from '../components' +import { useLocale, useTitle } from '../contexts' +import { cleanUrl } from '../Utils' + +const partners = [...new Set(config.generators + .filter(g => g.partner !== undefined) + .map(g => g.partner as string) +)] + +interface Props { + path?: string, +} +export function Partners({}: Props) { + const { locale } = useLocale() + useTitle(locale('title.partners')) + + return
+
+ {partners.map(p => + {config.generators.filter(g => g.partner === p).map(g => + + )} + )} +
+
+} diff --git a/src/app/pages/index.ts b/src/app/pages/index.ts index fa112ff0..f562da75 100644 --- a/src/app/pages/index.ts +++ b/src/app/pages/index.ts @@ -4,6 +4,7 @@ export * from './Generator' export * from './Guide' export * from './Guides' export * from './Home' +export * from './Partners' export * from './Project' export * from './Sounds' export * from './Versions' diff --git a/src/app/partners/ImmersiveWeathering.ts b/src/app/partners/ImmersiveWeathering.ts new file mode 100644 index 00000000..ac3da960 --- /dev/null +++ b/src/app/partners/ImmersiveWeathering.ts @@ -0,0 +1,210 @@ +import type { CollectionRegistry, ResourceType, SchemaRegistry } from '@mcschema/core' +import { BooleanNode, Case, ChoiceNode, ListNode, MapNode, NumberNode, ObjectNode, Opt, Reference as RawReference, StringNode as RawStringNode, Switch } from '@mcschema/core' + +const ID = 'immersive_weathering' + +export function initImmersiveWeathering(schemas: SchemaRegistry, collections: CollectionRegistry) { + const Reference = RawReference.bind(undefined, schemas) + const StringNode = RawStringNode.bind(undefined, collections) + + const Tag = (id: Exclude) => ChoiceNode([ + { + type: 'string', + node: StringNode({ validator: 'resource', params: { pool: id, allowTag: true } }), + change: (v: unknown) => { + if (Array.isArray(v) && typeof v[0] === 'string' && !v[0].startsWith('#')) { + return v[0] + } + return undefined + }, + }, + { + type: 'list', + node: ListNode( + StringNode({ validator: 'resource', params: { pool: id } }) + ), + change: (v: unknown) => { + if (typeof v === 'string' && !v.startsWith('#')) { + return [v] + } + return [] + }, + }, + ], { choiceContext: 'tag' }) + + schemas.register(`${ID}:block_growth`, ObjectNode({ + area_condition: Reference(`${ID}:area_condition`), + position_predicates: Opt(ListNode( + Reference(`${ID}:position_test`) + )), + growth_chance: NumberNode({ min: 0, max: 1 }), + growth_for_face: ListNode( + ObjectNode({ + direction: Opt(StringNode({ enum: 'direction' })), + weight: Opt(NumberNode({ integer: true })), + growth: ListNode( + ObjectNode({ + data: Reference(`${ID}:block_pair`), + weight: NumberNode({ integer: true }), + }) + ), + }, { category: 'pool' }) + ), + owners: ListNode( + StringNode({ validator: 'resource', params: { pool: 'block' } }) + ), + replacing_target: Reference(`${ID}:rule_test`), + target_self: Opt(BooleanNode()), + destroy_target: Opt(BooleanNode()), + }, { context: `${ID}.block_growth` })) + + schemas.register(`${ID}:area_condition`, ObjectNode({ + type: StringNode({ enum: ['generate_if_not_too_many', 'neighbor_based_generation'] }), + [Switch]: [{ push: 'type' }], + [Case]: { + generate_if_not_too_many: { + radiusX: NumberNode({ integer: true }), + radiusY: NumberNode({ integer: true }), + radiusZ: NumberNode({ integer: true }), + requiredAmount: NumberNode({ integer: true }), + yOffset: Opt(NumberNode({ integer: true })), + must_have: Opt(Reference(`${ID}:rule_test`)), + must_not_have: Opt(Reference(`${ID}:rule_test`)), + includes: Opt(Tag('block')), + }, + neighbor_based_generation: { + must_have: Reference(`${ID}:rule_test`), + must_not_have: Opt(Reference(`${ID}:rule_test`)), + required_amount: Opt(NumberNode({ integer: true })), + directions: ListNode( + StringNode({ enum: 'direction' }) + ), + }, + }, + }, { context: `${ID}.area_condition` })) + + schemas.register(`${ID}:block_pair`, ObjectNode({ + block: Reference(`${ID}:block_state`), + above_block: Opt(Reference(`${ID}:block_state`)), + }, { context: `${ID}.block_pair` })) + + schemas.register(`${ID}:block_state`, ObjectNode({ + Name: StringNode({ validator: 'resource', params: { pool: 'block' } }), + Properties: Opt(MapNode( + StringNode(), + StringNode(), + )), + }, { context: 'block_state' })) + + schemas.register(`${ID}:position_test`, ObjectNode({ + predicate_type: StringNode({ enum: ['biome_match', 'day_test', 'nand', 'precipitation_test', 'temperature_range'] }), + [Switch]: [{ push: 'predicate_type' }], + [Case]: { + biome_match: { + biomes: Tag('$worldgen/biome'), + }, + day_test: { + day: BooleanNode(), + }, + nand: { + predicates: ListNode( + Reference(`${ID}:position_test`) + ), + }, + precipitation_test: { + precipitation: StringNode({ enum: ['none', 'rain', 'snow']}), + }, + temperature_range: { + min: NumberNode(), + max: NumberNode(), + use_local_pos: Opt(BooleanNode()), + }, + }, + }, { context: `${ID}.position_test`, category: 'predicate' })) + + collections.register(`${ID}:rule_test`, [ + ...collections.get('rule_test'), + 'immersive_weathering:block_set_match', + 'immersive_weathering:fluid_match', + 'immersive_weathering:tree_log', + ]) + + schemas.register(`${ID}:rule_test`, ObjectNode({ + predicate_type: StringNode({ validator: 'resource', params: { pool: `${ID}:rule_test` as any } }), + [Switch]: [{ push: 'predicate_type' }], + [Case]: { + 'minecraft:block_match': { + block: StringNode({ validator: 'resource', params: { pool: 'block' } }), + }, + 'minecraft:blockstate_match': { + block_state: Reference('block_state'), + }, + 'minecraft:random_block_match': { + block: StringNode({ validator: 'resource', params: { pool: 'block' } }), + probability: NumberNode({ min: 0, max: 1 }), + }, + 'minecraft:random_blockstate_match': { + block_state: Reference('block_state'), + probability: NumberNode({ min: 0, max: 1 }), + }, + 'minecraft:tag_match': { + tag: StringNode({ validator: 'resource', params: { pool: '$tag/block' }}), + }, + 'immersive_weathering:block_set_match': { + blocks: Tag('block'), + probability: Opt(NumberNode({ min: 0, max: 1 })), + }, + 'immersive_weathering:fluid_match': { + fluid: StringNode({ validator: 'resource', params: { pool: 'fluid' } }), + }, + }, + }, { context: 'rule_test', disableSwitchContext: true })) + + collections.register('block_growth', [ + 'immersive_weathering:brain_coral', + 'immersive_weathering:bubble_coral', + 'immersive_weathering:cracked_mud_rivers', + 'immersive_weathering:crimson_nylium', + 'immersive_weathering:cryosol', + 'immersive_weathering:farmland_rare_weeds', + 'immersive_weathering:farmland_weeds', + 'immersive_weathering:fire_coral', + 'immersive_weathering:fire_soot', + 'immersive_weathering:fluvisol', + 'immersive_weathering:grass_base', + 'immersive_weathering:grass_block_badlands', + 'immersive_weathering:grass_block_bamboo_jungle', + 'immersive_weathering:grass_block_birch_forest', + 'immersive_weathering:grass_block_dark_forest', + 'immersive_weathering:grass_block_flower_forest', + 'immersive_weathering:grass_block_forest', + 'immersive_weathering:grass_block_jungle', + 'immersive_weathering:grass_block_lush_caves', + 'immersive_weathering:grass_block_old_growth_spruce', + 'immersive_weathering:grass_block_plains', + 'immersive_weathering:grass_block_sunflower_plains', + 'immersive_weathering:grass_block_swamp', + 'immersive_weathering:grass_block_taiga', + 'immersive_weathering:grass_block_wooded_badlands', + 'immersive_weathering:hanging_roots', + 'immersive_weathering:horn_coral', + 'immersive_weathering:humus', + 'immersive_weathering:icicle_growth', + 'immersive_weathering:large_fern', + 'immersive_weathering:magma', + 'immersive_weathering:mycelium', + 'immersive_weathering:podzol', + 'immersive_weathering:red_sand_weathering', + 'immersive_weathering:rooted_dirt', + 'immersive_weathering:rooted_grass', + 'immersive_weathering:sand_weathering', + 'immersive_weathering:sapling', + 'immersive_weathering:sapling_nether', + 'immersive_weathering:silt', + 'immersive_weathering:tall_grass', + 'immersive_weathering:tall_seagrass', + 'immersive_weathering:tube_coral', + 'immersive_weathering:vertisol', + 'immersive_weathering:warped_nylium', + ]) +} diff --git a/src/app/partners/index.ts b/src/app/partners/index.ts new file mode 100644 index 00000000..9db8bad4 --- /dev/null +++ b/src/app/partners/index.ts @@ -0,0 +1,8 @@ +import type { CollectionRegistry, SchemaRegistry } from '@mcschema/core' +import { initImmersiveWeathering } from './ImmersiveWeathering' + +export * from './ImmersiveWeathering' + +export function initPartners(schemas: SchemaRegistry, collections: CollectionRegistry) { + initImmersiveWeathering(schemas, collections) +} diff --git a/src/app/partners/locales/en.json b/src/app/partners/locales/en.json new file mode 100644 index 00000000..26f8dacb --- /dev/null +++ b/src/app/partners/locales/en.json @@ -0,0 +1,60 @@ +{ + "immersive_weathering.area_condition.type": "Type", + "immersive_weathering.area_condition.type.generate_if_not_too_many": "Generate if not too many", + "immersive_weathering.area_condition.type.neighbor_based_generation": "Neighbor based generation", + "immersive_weathering.area_condition.generate_if_not_too_many.radiusX": "Radius X", + "immersive_weathering.area_condition.generate_if_not_too_many.radiusY": "Radius Y", + "immersive_weathering.area_condition.generate_if_not_too_many.radiusZ": "Radius Z", + "immersive_weathering.area_condition.generate_if_not_too_many.requiredAmount": "Required amount", + "immersive_weathering.area_condition.generate_if_not_too_many.yOffset": "Y offset", + "immersive_weathering.area_condition.generate_if_not_too_many.must_have": "Must have", + "immersive_weathering.area_condition.generate_if_not_too_many.must_not_have": "Must not have", + "immersive_weathering.area_condition.generate_if_not_too_many.includes": "Includes", + "immersive_weathering.area_condition.neighbor_based_generation.must_have": "Must have", + "immersive_weathering.area_condition.neighbor_based_generation.must_not_have": "Must not have", + "immersive_weathering.area_condition.neighbor_based_generation.required_amount": "Required amount", + "immersive_weathering.area_condition.neighbor_based_generation.directions": "Directions", + "immersive_weathering.area_condition.neighbor_based_generation.directions.entry": "Direction", + "immersive_weathering.block_growth.area_condition": "Area conditions", + "immersive_weathering.block_growth.position_predicates": "Position predicates", + "immersive_weathering.block_growth.position_predicates.entry": "Position test", + "immersive_weathering.block_growth.growth_chance": "Growth chance", + "immersive_weathering.block_growth.growth_for_face": "Growth for face", + "immersive_weathering.block_growth.growth_for_face.entry": "Face", + "immersive_weathering.block_growth.growth_for_face.entry.direction": "Direction", + "immersive_weathering.block_growth.growth_for_face.entry.weight": "Weight", + "immersive_weathering.block_growth.growth_for_face.entry.growth": "Growth", + "immersive_weathering.block_growth.growth_for_face.entry.growth.entry.data": "Block pair", + "immersive_weathering.block_growth.growth_for_face.entry.growth.entry.weight": "Weight", + "immersive_weathering.block_growth.owners": "Owners", + "immersive_weathering.block_growth.owners.entry": "Block", + "immersive_weathering.block_growth.replacing_target": "Replacing target", + "immersive_weathering.block_growth.target_self": "Target self", + "immersive_weathering.block_growth.destroy_target": "Destroy target", + "immersive_weathering.block_pair.block": "Block", + "immersive_weathering.block_pair.above_block": "Above block", + "immersive_weathering.position_test.predicate_type": "Predicate type", + "immersive_weathering.position_test.predicate_type.biome_match": "Biome match", + "immersive_weathering.position_test.predicate_type.day_test": "Day test", + "immersive_weathering.position_test.predicate_type.nand": "NAND", + "immersive_weathering.position_test.predicate_type.precipitation_test": "Precipitation test", + "immersive_weathering.position_test.predicate_type.temperature_range": "Temperature range", + "immersive_weathering.position_test.biome_match.biomes": "Biomes", + "immersive_weathering.position_test.day_test.day": "Day", + "immersive_weathering.position_test.nand.predicates": "Predicates", + "immersive_weathering.position_test.precipitation_test.precipitation": "Precipitation", + "immersive_weathering.position_test.temperature_range.min": "Min", + "immersive_weathering.position_test.temperature_range.max": "Max", + "immersive_weathering.position_test.temperature_range.use_local_pos": "Use local pos", + "immersive_weathering:rule_test.always_true": "Always true", + "immersive_weathering:rule_test.block_match": "Block match", + "immersive_weathering:rule_test.blockstate_match": "Block state match", + "immersive_weathering:rule_test.random_block_match": "Random block match", + "immersive_weathering:rule_test.random_blockstate_match": "Random block state match", + "immersive_weathering:rule_test.tag_match": "Tag match", + "immersive_weathering:rule_test.immersive_weathering:block_set_match": "Block set match", + "immersive_weathering:rule_test.immersive_weathering:fluid_match": "Fluid match", + "immersive_weathering:rule_test.immersive_weathering:tree_log": "Tree log", + "rule_test.blocks": "Blocks", + "rule_test.fluid": "Fluid" +} diff --git a/src/app/schema/renderHtml.tsx b/src/app/schema/renderHtml.tsx index ba474c32..24e498dd 100644 --- a/src/app/schema/renderHtml.tsx +++ b/src/app/schema/renderHtml.tsx @@ -15,7 +15,7 @@ import { ModelWrapper } from './ModelWrapper' const selectRegistries = ['loot_table.type', 'loot_entry.type', 'function.function', 'condition.condition', 'criterion.trigger', 'recipe.type', 'dimension.generator.type', 'dimension.generator.biome_source.type', 'dimension.generator.biome_source.preset', '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', 'block_predicate.type', 'material_rule.type', 'material_condition.type', 'structure_placement.type', 'density_function.type', 'root_placer.type', 'entity.type_specific.cat.variant', 'entity.type_specific.frog.variant'] 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', 'decorator.block_survives_filter.state', 'material_rule.block.result_state'] -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', 'generator_biome.biome', 'block_predicate.type', 'material_rule.type', 'material_condition.type', 'density_function.type', 'root_placer.type', 'entity.type_specific.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', 'generator_biome.biome', 'block_predicate.type', 'material_rule.type', 'material_condition.type', 'density_function.type', 'root_placer.type', 'entity.type_specific.type', 'immersive_weathering.area_condition.type', 'immersive_weathering.block_growth.growth_for_face.entry.direction', 'immersive_weathering.position_test.predicate_type'] const nbtFields = ['function.set_nbt.tag', 'advancement.display.icon.nbt', 'text_component_object.nbt', 'entity.nbt', 'block.nbt', 'item.nbt'] const fixedLists = ['generator_biome.parameters.temperature', 'generator_biome.parameters.humidity', 'generator_biome.parameters.continentalness', 'generator_biome.parameters.erosion', 'generator_biome.parameters.depth', 'generator_biome.parameters.weirdness', 'feature.end_spike.crystal_beam_target', 'feature.end_gateway.exit', 'decorator.block_filter.offset', 'block_predicate.matching_blocks.offset', 'block_predicate.matching_fluids.offset', 'model_element.from', 'model_element.to', 'model_element.rotation.origin', 'model_element.faces.uv', 'item_transform.rotation', 'item_transform.translation', 'item_transform.scale', 'generator_structure.random_spread.locate_offset'] const collapsedFields = ['noise_settings.surface_rule', 'noise_settings.noise.terrain_shaper'] diff --git a/src/app/services/DataFetcher.ts b/src/app/services/DataFetcher.ts index 4ba063e1..4b3f36c4 100644 --- a/src/app/services/DataFetcher.ts +++ b/src/app/services/DataFetcher.ts @@ -83,8 +83,13 @@ export async function fetchPreset(versionId: VersionId, registry: string, id: st console.debug(`[fetchPreset] ${versionId} ${registry} ${id}`) const version = config.versions.find(v => v.id === versionId)! try { - const type = ['blockstates', 'models'].includes(registry) ? 'assets' : 'data' - const url = `${mcmeta(version, type)}/${type}/minecraft/${registry}/${id}.json` + let url + if (id.startsWith('immersive_weathering:')) { + url = `https://raw.githubusercontent.com/AstralOrdana/Immersive-Weathering/main/src/main/resources/data/immersive_weathering/block_growths/${id.slice(21)}.json` + } else { + const type = ['blockstates', 'models'].includes(registry) ? 'assets' : 'data' + url = `${mcmeta(version, type)}/${type}/minecraft/${registry}/${id}.json` + } const res = await fetch(url) return await res.json() } catch (e) { diff --git a/src/app/services/Schemas.ts b/src/app/services/Schemas.ts index a4de0f92..aad2ddcb 100644 --- a/src/app/services/Schemas.ts +++ b/src/app/services/Schemas.ts @@ -1,6 +1,7 @@ import type { CollectionRegistry, INode, SchemaRegistry } from '@mcschema/core' import { ChoiceNode, DataModel, Reference, StringNode } from '@mcschema/core' import config from '../../config.json' +import { initPartners } from '../partners' import { message } from '../Utils' import { fetchData } from './DataFetcher' @@ -58,6 +59,7 @@ async function getVersion(id: VersionId): Promise { 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) { diff --git a/src/config.json b/src/config.json index ad58ff8d..6756e481 100644 --- a/src/config.json +++ b/src/config.json @@ -266,6 +266,15 @@ "path": "models", "category": "assets", "schema": "model" + }, + { + "id": "block_growth", + "url": "partners/immersive-weathering/block-growth", + "path": "block_growths", + "category": "partners", + "partner": "immersive_weathering", + "schema": "immersive_weathering:block_growth", + "minVersion": "1.18.2" } ] } diff --git a/src/locales/en.json b/src/locales/en.json index 38a372a5..895f898b 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -88,9 +88,12 @@ "title.generator_category": "%0% Generators", "title.guides": "Data Pack Guides", "title.home": "Data Pack Generators", + "title.partners": "Partners", "title.project": "%0% Project", "title.sounds": "Sound Explorer", "title.versions": "Versions Explorer", + "partner.immersive_weathering": "Immersive Weathering", + "partner.immersive_weathering.block_growth": "Block Growth", "presets": "Presets", "preview": "Visualize", "preview.auto_scroll": "Auto scroll", diff --git a/src/styles/global.css b/src/styles/global.css index d3d05d9e..c22579f7 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -819,9 +819,14 @@ main.has-preview { grid-template-columns: 1fr 1fr; gap: 0 8px; align-items: flex-start; + grid-template-rows: min-content 1fr repeat(6, auto); } -.home > *:nth-child(n+3) { +.home > *:first-child { + grid-row: 1 / 3; +} + +.home > *:nth-child(n+4) { grid-column: 1 / 3; }