import { useCallback, useEffect, useErrorBoundary, useMemo, useRef, useState } from 'preact/hooks' import config from '../Config.js' import { deepClone, deepEqual, writeZip } from '../Utils.js' import { BasicSettings } from '../components/customized/BasicSettings.jsx' import { generateCustomized } from '../components/customized/CustomizedGenerator.js' import { CustomizedModel } from '../components/customized/CustomizedModel.js' import { OresSettings } from '../components/customized/OresSettings.jsx' import { StructuresSettings } from '../components/customized/StructuresSettings.jsx' import { Btn, ErrorPanel, Footer, Octicon, VersionSwitcher } from '../components/index.js' import { useLocale, useTitle } from '../contexts/index.js' import { useSearchParam } from '../hooks/index.js' import { stringifySource } from '../services/Source.js' const Tabs = ['basic', 'structures', 'ores'] interface Props { path?: string, } export function Customized({}: Props) { const { locale } = useLocale() // const { version, changeVersion } = useVersion() const version = '1.20.2' const changeVersion = () => {} useTitle(locale('title.customized')) const [errorBoundary, errorRetry] = useErrorBoundary() if (errorBoundary) { errorBoundary.message = `Something went wrong with the customized world tool: ${errorBoundary.message}` return
} const [tab, setTab] = useSearchParam('tab') useEffect(() => { if (tab === undefined || !Tabs.includes(tab)) { setTab(Tabs[0], true) } }, [tab]) const [model, setModel] = useState(CustomizedModel.getDefault(version)) const changeModel = useCallback((change: Partial) => { setModel(m => ({ ...m, ...change })) }, []) const initialModel = useMemo(() => { return CustomizedModel.getDefault(version) }, [version]) const isModified = useMemo(() => { return !deepEqual(model, initialModel) }, [model, initialModel]) const reset = useCallback(() => { setModel(deepClone(initialModel)) }, [initialModel]) const download = useRef(null) const [error, setError] = useState(null) const [hasDownloaded, setHasDownloaded] = useState(false) const generate = useCallback(async () => { if (!download.current) return try { const pack = await generateCustomized(model, version) console.log('Generated customized', pack) const entries = Object.entries(pack).flatMap(([type, files]) => { const prefix = `data/minecraft/${type}/` return [...files.entries()].map(([name, data]) => { return [prefix + name + '.json', stringifySource(data, 'json')] as [string, string] }) }) const pack_format = config.versions.find(v => v.id === version)!.pack_format entries.push(['pack.mcmeta', stringifySource({ pack: { pack_format, description: 'Customized world from misode.github.io' } }, 'json')]) const url = await writeZip(entries) download.current.setAttribute('href', url) download.current.setAttribute('download', 'customized.zip') download.current.click() setHasDownloaded(true) setError(null) } catch (e) { if (e instanceof Error) { e.message = `Something went wrong creating the customized pack: ${e.message}` setError(e) } } }, [model, version]) return
setTab('basic')}>{locale('customized.basic')} setTab('structures')}>{locale('customized.structures')} setTab('ores')}>{locale('customized.ores')}
{tab === 'basic' && } {tab === 'structures' && } {tab === 'ores' && }
{isModified && }
{error && setError(null)} body={`\n### Customized settings\n
\n
\n${JSON.stringify(getDiffModel(model, initialModel), null, 2)}\n
\n
\n`} />} {hasDownloaded &&

{Octicon.mortar_board} What now?

  1. After launching Minecraft, create a new singleplayer world.
  2. Select the "More" tab at the top.
  3. Click on "Data Packs" and drag the downloaded zip file onto the game window.
  4. Move the imported data pack to the right panel and click on "Done".
  5. A message will warn about the use of experimental world settings. Click on "Proceed".
}
} function getDiffModel(model: any, initial: any) { const result = deepClone(model) if (typeof result !== 'object' || result === null) return Object.keys(result).forEach(key => { if (deepEqual(result[key], initial[key])) { delete result[key] } else if (typeof result[key] === 'object' && result[key] !== null) { result[key] = getDiffModel(result[key], initial[key]) } }) return result }