diff --git a/package-lock.json b/package-lock.json index 689427b3..512cd15b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "brace": "^0.11.1", "buffer": "^6.0.3", "comment-json": "^4.1.1", - "deepslate": "^0.11.0", + "deepslate": "^0.11.1", "deepslate-1.18": "npm:deepslate@^0.9.0-beta.9", "deepslate-1.18.2": "npm:deepslate@^0.9.0-beta.13", "deepslate-rs": "^0.1.6", @@ -1934,10 +1934,9 @@ "dev": true }, "node_modules/deepslate": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/deepslate/-/deepslate-0.11.0.tgz", - "integrity": "sha512-EPKWS+cEuBZqb8eNH8mCCV+eoYoDTnWQZY+LprQtmcIpQlmCaKAzj3C64qahHBTru8XwAS61UN1Dag02AJdjTw==", - "license": "MIT", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/deepslate/-/deepslate-0.11.1.tgz", + "integrity": "sha512-1m4TFkzHcTdAH00+S/oIzfhaeUomQokf66FIz8rvtakBcF/YraRnu8h4ic6tBMlnWI9pOb4Wuc2rtbEw8pgbNQ==", "dependencies": { "gl-matrix": "^3.3.0", "md5": "^2.3.0", @@ -6628,9 +6627,9 @@ "dev": true }, "deepslate": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/deepslate/-/deepslate-0.11.0.tgz", - "integrity": "sha512-EPKWS+cEuBZqb8eNH8mCCV+eoYoDTnWQZY+LprQtmcIpQlmCaKAzj3C64qahHBTru8XwAS61UN1Dag02AJdjTw==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/deepslate/-/deepslate-0.11.1.tgz", + "integrity": "sha512-1m4TFkzHcTdAH00+S/oIzfhaeUomQokf66FIz8rvtakBcF/YraRnu8h4ic6tBMlnWI9pOb4Wuc2rtbEw8pgbNQ==", "requires": { "gl-matrix": "^3.3.0", "md5": "^2.3.0", diff --git a/package.json b/package.json index cd49d4dd..10d3f69d 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "brace": "^0.11.1", "buffer": "^6.0.3", "comment-json": "^4.1.1", - "deepslate": "^0.11.0", + "deepslate": "^0.11.1", "deepslate-1.18": "npm:deepslate@^0.9.0-beta.9", "deepslate-1.18.2": "npm:deepslate@^0.9.0-beta.13", "deepslate-rs": "^0.1.6", diff --git a/src/app/components/previews/DensityFunctionPreview.tsx b/src/app/components/previews/DensityFunctionPreview.tsx index b02f1a3a..b626193c 100644 --- a/src/app/components/previews/DensityFunctionPreview.tsx +++ b/src/app/components/previews/DensityFunctionPreview.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from 'preact/hooks' -import { useLocale } from '../../contexts/index.js' +import { useLocale, useProject } from '../../contexts/index.js' import { useCanvas } from '../../hooks/index.js' import { densityFunction } from '../../previews/index.js' import { randomSeed } from '../../Utils.js' @@ -8,6 +8,7 @@ import type { PreviewProps } from './index.js' export const DensityFunctionPreview = ({ data, shown, version }: PreviewProps) => { const { locale } = useLocale() + const { project } = useProject() const [seed, setSeed] = useState(randomSeed()) const [autoScroll, setAutoScroll] = useState(false) const [focused, setFocused] = useState(undefined) @@ -21,7 +22,7 @@ export const DensityFunctionPreview = ({ data, shown, version }: PreviewProps) = return [size, size] }, async draw(img) { - const options = { offset: offset.current, width: img.width, seed, version } + const options = { offset: offset.current, width: img.width, seed, version, project } await densityFunction(data, img, options) }, async onDrag(dx) { @@ -36,7 +37,7 @@ export const DensityFunctionPreview = ({ data, shown, version }: PreviewProps) = onLeave() { setFocused(undefined) }, - }, [version, state, seed]) + }, [version, state, seed, project]) useEffect(() => { if (scrollInterval.current) { @@ -51,7 +52,7 @@ export const DensityFunctionPreview = ({ data, shown, version }: PreviewProps) = }, 100) as any } } - }, [version, state, seed, shown, autoScroll]) + }, [version, state, seed, project, shown, autoScroll]) return <>
diff --git a/src/app/components/previews/NoiseSettingsPreview.tsx b/src/app/components/previews/NoiseSettingsPreview.tsx index c22269eb..84eb67dd 100644 --- a/src/app/components/previews/NoiseSettingsPreview.tsx +++ b/src/app/components/previews/NoiseSettingsPreview.tsx @@ -1,5 +1,5 @@ import { useEffect, useMemo, useRef, useState } from 'preact/hooks' -import { useLocale } from '../../contexts/index.js' +import { useLocale, useProject } from '../../contexts/index.js' import { useCanvas } from '../../hooks/index.js' import { getNoiseBlock, noiseSettings } from '../../previews/index.js' import { CachedCollections, checkVersion } from '../../services/index.js' @@ -9,6 +9,7 @@ import type { PreviewProps } from './index.js' export const NoiseSettingsPreview = ({ data, shown, version }: PreviewProps) => { const { locale } = useLocale() + const { project } = useProject() const [seed, setSeed] = useState(randomSeed()) const [biome, setBiome] = useState('minecraft:plains') const [biomeScale, setBiomeScale] = useState(0.2) @@ -25,7 +26,7 @@ export const NoiseSettingsPreview = ({ data, shown, version }: PreviewProps) => return [size, size] }, async draw(img) { - const options = { biome, biomeDepth, biomeScale, offset: offset.current, width: img.width, seed, version } + const options = { biome, biomeDepth, biomeScale, offset: offset.current, width: img.width, seed, version, project } await noiseSettings(data, img, options) }, async onDrag(dx) { @@ -41,7 +42,7 @@ export const NoiseSettingsPreview = ({ data, shown, version }: PreviewProps) => onLeave() { setFocused(undefined) }, - }, [state, seed]) + }, [state, seed, project]) useEffect(() => { if (scrollInterval.current) { @@ -62,7 +63,7 @@ export const NoiseSettingsPreview = ({ data, shown, version }: PreviewProps) => } })() } - }, [version, state, seed, shown, biome, biomeScale, biomeDepth, autoScroll]) + }, [version, state, seed, project, shown, biome, biomeScale, biomeDepth, autoScroll]) const allBiomes = useMemo(() => CachedCollections?.get('worldgen/biome') ?? [], [version]) diff --git a/src/app/previews/Deepslate.ts b/src/app/previews/Deepslate.ts index 05212a84..db1e610f 100644 --- a/src/app/previews/Deepslate.ts +++ b/src/app/previews/Deepslate.ts @@ -4,6 +4,13 @@ import type { VersionId } from '../services/index.js' import { checkVersion, fetchAllPresets } from '../services/index.js' import { deepClone, deepEqual } from '../Utils.js' +export type ProjectData = Record> + +const DYNAMIC_REGISTRIES = new Set([ + 'minecraft:worldgen/noise', + 'minecraft:worldgen/density_function', +]) + export class Deepslate { private d = deepslate19 private loadedVersion: VersionId | undefined @@ -17,18 +24,19 @@ export class Deepslate { private generatorCache: ChunkGenerator | undefined private chunksCache: Chunk[] = [] - public async loadVersion(version: VersionId) { + public async loadVersion(version: VersionId, project?: ProjectData) { if (this.loadedVersion === version) { + this.applyProjectData(version, project) return } if (this.loadingVersion !== version || !this.loadingPromise) { this.loadingVersion = version - this.loadingPromise = this.doLoadVersion(version) + this.loadingPromise = this.doLoadVersion(version, project) } return this.loadingPromise } - private async doLoadVersion(version: VersionId) { + private async doLoadVersion(version: VersionId, project?: ProjectData) { const cachedDeepslate = this.deepslateCache.get(version) if (cachedDeepslate) { this.d = cachedDeepslate @@ -40,26 +48,47 @@ export class Deepslate { } else { this.d = await import('deepslate-1.18') as any } - if (this.d.WorldgenRegistries) { + if (checkVersion(version, '1.19')) { + await Promise.all(this.d.Registry.REGISTRY.map(async (id, registry) => { + if (DYNAMIC_REGISTRIES.has(id.toString())) { + const entries = await fetchAllPresets(version, id.path) + for (const [key, value] of entries.entries()) { + registry.register(this.d.Identifier.parse(key), registry.parse(value), true) + } + } + })) + } else if (checkVersion(version, '1.18.2')) { const REGISTRIES: [string, keyof typeof deepslate19.WorldgenRegistries, { fromJson(obj: unknown): any}][] = [ ['worldgen/noise', 'NOISE', this.d.NoiseParameters], ['worldgen/density_function', 'DENSITY_FUNCTION', this.d.DensityFunction], ] await Promise.all(REGISTRIES.map(async ([id, name, parser]) => { const entries = await fetchAllPresets(version, id) - const registry = new this.d.Registry(this.d.Identifier.create(id)) for (const [key, value] of entries.entries()) { - registry.register(this.d.Identifier.parse(key), parser.fromJson(value)) + this.d.WorldgenRegistries[name].register(this.d.Identifier.parse(key), parser.fromJson(value), true) } - this.d.WorldgenRegistries[name].assign(registry as any) })) } this.deepslateCache.set(version, this.d) } + this.applyProjectData(version, project) this.loadedVersion = version this.loadingVersion = undefined } + private applyProjectData(version: VersionId, project?: ProjectData) { + if (checkVersion(version, '1.19')) { + this.d.Registry.REGISTRY.forEach((id, registry) => { + if (DYNAMIC_REGISTRIES.has(id.toString())) { + registry.clear() + for (const [key, value] of Object.entries(project?.[id.path] ?? {})) { + registry.register(this.d.Identifier.parse(key), registry.parse(value)) + } + } + }) + } + } + public loadChunkGenerator(settings: unknown, seed: bigint, biome = 'unknown') { if (!this.loadedVersion) { throw new Error('No deepslate version loaded') diff --git a/src/app/previews/NoiseSettings.ts b/src/app/previews/NoiseSettings.ts index 02016082..82404dd4 100644 --- a/src/app/previews/NoiseSettings.ts +++ b/src/app/previews/NoiseSettings.ts @@ -1,4 +1,5 @@ import { BlockState, clampedMap, DensityFunction } from 'deepslate/worldgen' +import type { Project } from '../contexts/Project.jsx' import type { VersionId } from '../services/index.js' import { checkVersion } from '../services/index.js' import { Deepslate } from './Deepslate.js' @@ -12,6 +13,7 @@ export type NoiseSettingsOptions = { width: number, seed: bigint, version: VersionId, + project: Project, } const colors: Record = { @@ -37,8 +39,7 @@ const DEEPSLATE = new Deepslate() export async function noiseSettings(state: any, img: ImageData, options: NoiseSettingsOptions) { if (checkVersion(options.version, '1.18')) { - - await DEEPSLATE.loadVersion(options.version) + await DEEPSLATE.loadVersion(options.version, getProjectData(options.project)) DEEPSLATE.loadChunkGenerator(state, options.seed, options.biome) DEEPSLATE.generateChunks(-options.offset, options.width, options.biome) const noise = DEEPSLATE.getNoiseSettings() @@ -80,7 +81,7 @@ export function getNoiseBlock(x: number, y: number) { } export async function densityFunction(state: any, img: ImageData, options: NoiseSettingsOptions) { - await DEEPSLATE.loadVersion(options.version) + await DEEPSLATE.loadVersion(options.version, getProjectData(options.project)) const fn = DEEPSLATE.loadDensityFunction(state, options.seed) const noise = DEEPSLATE.getNoiseSettings() @@ -107,6 +108,16 @@ export async function densityFunction(state: any, img: ImageData, options: Noise } } +function getProjectData(project: Project) { + return Object.fromEntries(['worldgen/noise', 'worldgen/density_function'].map(type => { + const resources = Object.fromEntries( + project.files.filter(file => file.type === type) + .map<[string, unknown]>(file => [file.id, file.data]) + ) + return [type, resources] + })) +} + function getColor(noise: number[], y: number): number { if (noise[y] > 0) { return 0 diff --git a/src/app/previews/NormalNoise.ts b/src/app/previews/NormalNoise.ts index e50955bb..40364780 100644 --- a/src/app/previews/NormalNoise.ts +++ b/src/app/previews/NormalNoise.ts @@ -1,5 +1,5 @@ import { DataModel } from '@mcschema/core' -import { LegacyRandom, NoiseParameters, NormalNoise } from 'deepslate/worldgen' +import { NoiseParameters, NormalNoise, XoroshiroRandom } from 'deepslate/worldgen' import type { VersionId } from '../services/index.js' export type NoiseOptions = { @@ -10,7 +10,7 @@ export type NoiseOptions = { } export function normalNoise(state: any, img: ImageData, options: NoiseOptions) { - const random = new LegacyRandom(options.seed) + const random = XoroshiroRandom.create(options.seed) const params = NoiseParameters.fromJson(DataModel.unwrapLists(state)) const noise = new NormalNoise(random, params)