Register project noises and DFs to use in previews

This commit is contained in:
Misode
2022-06-16 17:54:45 +02:00
parent 561cd341a1
commit e2281e0d36
7 changed files with 70 additions and 29 deletions

View File

@@ -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<string | undefined>(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 <>
<div class="controls preview-controls">

View File

@@ -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])

View File

@@ -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<string, Record<string, unknown>>
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<typeof parser>(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')

View File

@@ -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<string, [number, number, number]> = {
@@ -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

View File

@@ -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)