mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-23 07:10:41 +00:00
Use mcmeta (#197)
* Simplify data fetching by using mcmeta * Fetch sounds from mcmeta
This commit is contained in:
22
.github/workflows/deploy.yml
vendored
22
.github/workflows/deploy.yml
vendored
@@ -12,27 +12,15 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Get latest mcdata commit hash
|
||||
uses: octokit/request-action@v2.x
|
||||
id: get_mcdata_hash
|
||||
with:
|
||||
route: GET /repos/Arcensoth/mcdata/branches/master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get latest vanilla-datapack commit hash
|
||||
uses: octokit/request-action@v2.x
|
||||
id: get_vanilla_datapack_summary_hash
|
||||
with:
|
||||
route: GET /repos/SPGoding/vanilla-datapack/branches/summary
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Get latest version
|
||||
id: get_latest_version
|
||||
run: |
|
||||
echo ::set-output name=data::$(curl -s "https://raw.githubusercontent.com/misode/mcmeta/summary/version.json")
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
npm install
|
||||
export mcdata_hash="'${{ fromJson(steps.get_mcdata_hash.outputs.data).commit.sha }}'"
|
||||
export vanilla_datapack_summary_hash="'${{ fromJson(steps.get_vanilla_datapack_summary_hash.outputs.data).commit.sha }}'"
|
||||
export latest_version="'${{ fromJson(steps.get_latest_version.outputs.data).commit.sha }}'"
|
||||
npm run build
|
||||
|
||||
- name: Deploy
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Howl } from 'howler'
|
||||
import { useEffect, useRef, useState } from 'preact/hooks'
|
||||
import { Btn, NumberInput, RangeInput, TextInput } from '..'
|
||||
import { useLocale } from '../../contexts'
|
||||
import type { SoundEvents, VersionAssets } from '../../services'
|
||||
import { getResourceUrl } from '../../services'
|
||||
import { useLocale, useVersion } from '../../contexts'
|
||||
import type { SoundEvents } from '../../services'
|
||||
import { getSoundUrl } from '../../services'
|
||||
|
||||
export interface SoundConfig {
|
||||
id: string,
|
||||
@@ -13,14 +13,14 @@ export interface SoundConfig {
|
||||
volume: number,
|
||||
}
|
||||
type SoundConfigProps = SoundConfig & {
|
||||
assets: VersionAssets,
|
||||
sounds: SoundEvents,
|
||||
onEdit: (changes: Partial<SoundConfig>) => unknown,
|
||||
onDelete: () => unknown,
|
||||
delayedPlay?: number,
|
||||
}
|
||||
export function SoundConfig({ assets, sounds, sound, delay, pitch, volume, onEdit, onDelete, delayedPlay }: SoundConfigProps) {
|
||||
export function SoundConfig({ sounds, sound, delay, pitch, volume, onEdit, onDelete, delayedPlay }: SoundConfigProps) {
|
||||
const { locale } = useLocale()
|
||||
const { version } = useVersion()
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [playing, setPlaying] = useState(false)
|
||||
const [invalid, setInvalid] = useState(false)
|
||||
@@ -33,8 +33,7 @@ export function SoundConfig({ assets, sounds, sound, delay, pitch, volume, onEdi
|
||||
howls.current.forEach(h => h.stop())
|
||||
howls.current = (soundEvent?.sounds ?? []).map(entry => {
|
||||
const soundPath = typeof entry === 'string' ? entry : entry.name
|
||||
const hash = assets[`minecraft/sounds/${soundPath}.ogg`].hash
|
||||
const url = getResourceUrl(hash)
|
||||
const url = getSoundUrl(version, soundPath)
|
||||
const howl = new Howl({
|
||||
src: [url],
|
||||
format: ['ogg'],
|
||||
|
||||
@@ -2,8 +2,8 @@ import { useEffect, useRef, useState } from 'preact/hooks'
|
||||
import config from '../../config.json'
|
||||
import { Ad, Btn, BtnMenu, ErrorPanel, SoundConfig, TextInput } from '../components'
|
||||
import { useLocale, useTitle, useVersion } from '../contexts'
|
||||
import type { SoundEvents, VersionAssets, VersionId } from '../services'
|
||||
import { getAssets, getSounds } from '../services'
|
||||
import type { SoundEvents, VersionId } from '../services'
|
||||
import { fetchSounds } from '../services'
|
||||
import { hexId, message } from '../Utils'
|
||||
|
||||
interface Props {
|
||||
@@ -15,13 +15,11 @@ export function Sounds({}: Props) {
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
useTitle(locale('title.sounds'))
|
||||
|
||||
const [assets, setAssets] = useState<VersionAssets>({})
|
||||
const [sounds, setSounds] = useState<SoundEvents>({})
|
||||
const soundKeys = Object.keys(sounds ?? {})
|
||||
useEffect(() => {
|
||||
getAssets(version)
|
||||
.then(assets => { setAssets(assets); return getSounds(version) })
|
||||
.then(sounds => { if (sounds) setSounds(sounds) })
|
||||
fetchSounds(version)
|
||||
.then(setSounds)
|
||||
.catch(e => { console.error(e); setError(message(e)) })
|
||||
}, [version])
|
||||
|
||||
@@ -74,7 +72,7 @@ export function Sounds({}: Props) {
|
||||
</BtnMenu>
|
||||
</div>
|
||||
<div class="sounds">
|
||||
{configs.map(c => <SoundConfig key={c.id} {...c} {...{ assets, sounds, delayedPlay }} onEdit={editConfig(c.id)} onDelete={deleteConfig(c.id)} />)}
|
||||
{configs.map(c => <SoundConfig key={c.id} {...c} {...{ sounds, delayedPlay }} onEdit={editConfig(c.id)} onDelete={deleteConfig(c.id)} />)}
|
||||
</div>
|
||||
<a ref={download} style="display: none;"></a>
|
||||
</>}
|
||||
|
||||
@@ -1,48 +1,31 @@
|
||||
import type { CollectionRegistry } from '@mcschema/core'
|
||||
import config from '../../config.json'
|
||||
import { message } from '../Utils'
|
||||
import type { VersionAssets, VersionManifest } from './Manifest'
|
||||
import type { BlockStateRegistry, VersionId } from './Schemas'
|
||||
import { checkVersion } from './Schemas'
|
||||
|
||||
['1.15', '1.16', '1.17'].forEach(v => localStorage.removeItem(`cache_${v}`))
|
||||
// Cleanup old caches
|
||||
['1.15', '1.16', '1.17'].forEach(v => localStorage.removeItem(`cache_${v}`));
|
||||
['mcdata_master', 'vanilla_datapack_summary'].forEach(v => localStorage.removeItem(`cached_${v}`))
|
||||
caches.delete('misode-v1')
|
||||
|
||||
const CACHE_NAME = 'misode-v1'
|
||||
|
||||
type VersionRef = 'mcdata_master' | 'mcassets' | 'vanilla_datapack_summary' | 'vanilla_datapack_data'
|
||||
const CACHE_NAME = 'misode-v2'
|
||||
const CACHE_LATEST_VERSION = 'cached_latest_version'
|
||||
|
||||
type Version = {
|
||||
id: string,
|
||||
refs: Partial<{ [key in VersionRef]: string }>,
|
||||
ref?: string,
|
||||
dynamic?: boolean,
|
||||
}
|
||||
|
||||
declare var __MCDATA_MASTER_HASH__: string
|
||||
declare var __VANILLA_DATAPACK_SUMMARY_HASH__: string
|
||||
declare var __LATEST_VERSION__: string
|
||||
const latestVersion = __LATEST_VERSION__ ?? ''
|
||||
const mcmetaUrl = 'https://raw.githubusercontent.com/misode/mcmeta'
|
||||
|
||||
const mcdataUrl = 'https://raw.githubusercontent.com/Arcensoth/mcdata'
|
||||
const mcassetsUrl = 'https://raw.githubusercontent.com/InventivetalentDev/minecraft-assets'
|
||||
const vanillaDatapackUrl = 'https://raw.githubusercontent.com/SPGoding/vanilla-datapack'
|
||||
const manifestUrl = 'https://launchermeta.mojang.com/mc/game/version_manifest.json'
|
||||
const resourceUrl = 'https://resources.download.minecraft.net/'
|
||||
const corsUrl = 'https://misode-cors-anywhere.herokuapp.com/'
|
||||
type McmetaTypes = 'summary' | 'data' | 'assets'
|
||||
|
||||
const refs: {
|
||||
id: VersionRef,
|
||||
hash: string,
|
||||
url: string,
|
||||
}[] = [
|
||||
{
|
||||
id: 'mcdata_master',
|
||||
hash: __MCDATA_MASTER_HASH__,
|
||||
url: mcdataUrl,
|
||||
},
|
||||
{
|
||||
id: 'vanilla_datapack_summary',
|
||||
hash: __VANILLA_DATAPACK_SUMMARY_HASH__,
|
||||
url: vanillaDatapackUrl,
|
||||
},
|
||||
]
|
||||
function mcmeta(version: Version, type: McmetaTypes) {
|
||||
return `${mcmetaUrl}/${version.dynamic ? type : `${version.ref}-${type}`}`
|
||||
}
|
||||
|
||||
export async function fetchData(versionId: string, collectionTarget: CollectionRegistry, blockStateTarget: BlockStateRegistry) {
|
||||
const version = config.versions.find(v => v.id === versionId) as Version | undefined
|
||||
@@ -50,205 +33,79 @@ export async function fetchData(versionId: string, collectionTarget: CollectionR
|
||||
console.error(`[fetchData] Unknown version ${version} in ${JSON.stringify(config.versions)}`)
|
||||
return
|
||||
}
|
||||
console.debug(`[fetchData] ${JSON.stringify(version)}`)
|
||||
|
||||
if (version.dynamic) {
|
||||
await Promise.all(refs
|
||||
.filter(r => localStorage.getItem(`cached_${r.id}`) !== r.hash)
|
||||
.map(async r => {
|
||||
console.debug(`[deleteMatching] ${r.id} '${localStorage.getItem(`cached_${r.id}`)}' < '${r.hash}' ${r.url}/${version.refs[r.id]}`)
|
||||
await deleteMatching(url => url.startsWith(`${r.url}/${version.refs[r.id]}`))
|
||||
console.debug(`[deleteMatching] Done! ${r.id} ${r.hash} '${localStorage.getItem(`cached_${r.id}`)}'`)
|
||||
localStorage.setItem(`cached_${r.id}`, r.hash)
|
||||
console.debug(`[deleteMatching] Set! ${r.id} ${r.hash} '${localStorage.getItem(`cached_${r.id}`)}'`)
|
||||
}))
|
||||
if (localStorage.getItem(CACHE_LATEST_VERSION) !== latestVersion) {
|
||||
await deleteMatching(url => url.startsWith(`${mcmetaUrl}/summary`))
|
||||
localStorage.setItem(CACHE_LATEST_VERSION, latestVersion)
|
||||
}
|
||||
version.ref = latestVersion
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
fetchRegistries(version, collectionTarget),
|
||||
fetchBlockStateMap(version, blockStateTarget),
|
||||
fetchDynamicRegistries(version, collectionTarget),
|
||||
fetchAssetsRegistries(version, collectionTarget),
|
||||
])
|
||||
}
|
||||
|
||||
async function fetchRegistries(version: Version, target: CollectionRegistry) {
|
||||
console.debug(`[fetchRegistries] ${version.id}`)
|
||||
const registries = config.registries
|
||||
.filter(r => !r.dynamic && !r.asset)
|
||||
.filter(r => checkVersion(version.id, r.minVersion, r.maxVersion))
|
||||
|
||||
if (checkVersion(version.id, undefined, '1.15')) {
|
||||
const url = `${mcdataUrl}/${version.refs.mcdata_master}/generated/reports/registries.json`
|
||||
try {
|
||||
const data = await getData(url, (data) => {
|
||||
const res: {[id: string]: string[]} = {}
|
||||
Object.keys(data).forEach(k => {
|
||||
res[k.slice(10)] = Object.keys(data[k].entries)
|
||||
})
|
||||
return res
|
||||
})
|
||||
registries.forEach(r => {
|
||||
target.register(r.id, data[r.id] ?? [])
|
||||
})
|
||||
} catch (e) {
|
||||
console.warn('Error occurred while fetching registries:', message(e))
|
||||
try {
|
||||
const data = await getData(`${mcmeta(version, 'summary')}/registries/data.min.json`)
|
||||
for (const id in data) {
|
||||
target.register(id, data[id].map((e: string) => 'minecraft:' + e))
|
||||
}
|
||||
} else {
|
||||
await Promise.all(registries.map(async r => {
|
||||
try {
|
||||
const url = r.path
|
||||
? `${mcdataUrl}/${version.refs.mcdata_master}/${r.path}/data.min.json`
|
||||
: `${mcdataUrl}/${version.refs.mcdata_master}/processed/reports/registries/${r.id}/data.min.json`
|
||||
target.register(r.id, await getData(url, v => v.values))
|
||||
} catch (e) {
|
||||
console.warn(`Error occurred while fetching registry ${r.id}:`, message(e))
|
||||
}
|
||||
}))
|
||||
} catch (e) {
|
||||
console.warn('Error occurred while fetching registries:', message(e))
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchBlockStateMap(version: Version, target: BlockStateRegistry) {
|
||||
console.debug(`[fetchBlockStateMap] ${version.id}`)
|
||||
if (checkVersion(version.id, undefined, '1.16')) {
|
||||
const url = (checkVersion(version.id, undefined, '1.15'))
|
||||
? `${mcdataUrl}/${version.refs.mcdata_master}/generated/reports/blocks.json`
|
||||
: `${mcdataUrl}/${version.refs.mcdata_master}/processed/reports/blocks/data.min.json`
|
||||
|
||||
try {
|
||||
const data = await getData(url, (data) => {
|
||||
const res: BlockStateRegistry = {}
|
||||
Object.keys(data).forEach(b => {
|
||||
res[b] = {
|
||||
properties: data[b].properties,
|
||||
default: data[b].states.find((s: any) => s.default).properties,
|
||||
}
|
||||
})
|
||||
return res
|
||||
})
|
||||
Object.assign(target, data)
|
||||
} catch (e) {
|
||||
console.warn('Error occurred while fetching block state map:', message(e))
|
||||
}
|
||||
} else {
|
||||
const url = `${mcdataUrl}/${version.refs.mcdata_master}/processed/reports/blocks/simplified/data.min.json`
|
||||
try {
|
||||
const data = await getData(url)
|
||||
Object.assign(target, data)
|
||||
} catch (e) {
|
||||
console.warn('Error occurred while fetching block state map:', message(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchDynamicRegistries(version: Version, target: CollectionRegistry) {
|
||||
console.debug(`[fetchDynamicRegistries] ${version.id}`)
|
||||
const registries = config.registries
|
||||
.filter(r => r.dynamic && !r.asset)
|
||||
.filter(r => checkVersion(version.id, r.minVersion, r.maxVersion))
|
||||
|
||||
if (checkVersion(version.id, '1.16')) {
|
||||
const url = `${vanillaDatapackUrl}/${version.refs.vanilla_datapack_summary}/summary/flattened.min.json`
|
||||
try {
|
||||
const data = await getData(url)
|
||||
registries.forEach(r => {
|
||||
target.register(r.id, data[r.id])
|
||||
})
|
||||
} catch (e) {
|
||||
console.warn('Error occurred while fetching dynamic registries:', message(e))
|
||||
}
|
||||
}
|
||||
if (checkVersion(version.id, '1.18')) {
|
||||
target.register('worldgen/noise', Noises)
|
||||
target.register('worldgen/placed_feature', PlacedFeatures)
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchAssetsRegistries(version: Version, target: CollectionRegistry) {
|
||||
console.debug(`[fetchAssetsRegistries] ${version.id}`)
|
||||
const registries = config.registries
|
||||
.filter(r => r.asset)
|
||||
.filter(r => checkVersion(version.id, r.minVersion, r.maxVersion))
|
||||
|
||||
await Promise.all(registries.map(async r => {
|
||||
try {
|
||||
const fetchFolder = async (path: string): Promise<string[]> => {
|
||||
const url = `${mcassetsUrl}/${version.refs.mcassets}/assets/minecraft/${path}/_list.json`
|
||||
const data = await getData(url)
|
||||
if (data.directories.length === 0) {
|
||||
return data.files
|
||||
}
|
||||
const directories = await Promise.all(data.directories.map(async (d: string) => {
|
||||
const files = await fetchFolder(`${path}/${d}`)
|
||||
return files.map(v => `${d}/${v}`)
|
||||
}))
|
||||
return [...data.files, ...directories.flat()]
|
||||
}
|
||||
const ids = (await fetchFolder(r.path ?? r.id))
|
||||
.filter((v: string) => v.endsWith('.json') || v.endsWith('.png'))
|
||||
.map(v => `minecraft:${v.replace(/\.(json|png)$/, '')}`)
|
||||
target.register(r.id, ids)
|
||||
} catch (e) {
|
||||
console.warn(`Error occurred while fetching assets registry ${r.id}:`, message(e))
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
export async function fetchPreset(version: VersionId, registry: string, id: string) {
|
||||
console.debug(`[fetchPreset] ${registry} ${id}`)
|
||||
const versionData = config.versions.find(v => v.id === version)!
|
||||
try {
|
||||
const url = ['blockstates', 'models'].includes(registry)
|
||||
? `${mcassetsUrl}/${versionData.refs.mcassets}/assets/minecraft/${registry}/${id}.json`
|
||||
: `${vanillaDatapackUrl}/${versionData.refs.vanilla_datapack_data}/data/minecraft/${registry}/${id}.json`
|
||||
const res = await fetch(url)
|
||||
if (registry === 'worldgen/noise_settings' && version === '1.18') {
|
||||
let text = await res.text()
|
||||
text = text.replaceAll('"max_threshold": Infinity', '"max_threshold": 100')
|
||||
const data = JSON.parse(text)
|
||||
if (id !== 'overworld' && id !== 'large_biomes') {
|
||||
data.noise.terrain_shaper = { offset: 0, factor: 0, jaggedness: 0 }
|
||||
const data = await getData(`${mcmeta(version, 'summary')}/blocks/data.min.json`)
|
||||
for (const id in data) {
|
||||
target['minecraft:' + id] = {
|
||||
properties: data[id][0],
|
||||
default: data[id][1],
|
||||
}
|
||||
return data
|
||||
}
|
||||
return await res.json()
|
||||
} catch (e) {
|
||||
console.warn('Error occurred while fetching block state map:', message(e))
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchPreset(versionId: VersionId, registry: string, id: string) {
|
||||
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`
|
||||
const res = await fetch(url)
|
||||
return res.json()
|
||||
} catch (e) {
|
||||
throw new Error(`Error occurred while fetching ${registry} preset ${id}: ${message(e)}`)
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchManifest() {
|
||||
try {
|
||||
const res = await fetch(manifestUrl)
|
||||
return await res.json()
|
||||
} catch (e) {
|
||||
throw new Error(`Error occurred while fetching version manifest: ${message(e)}`)
|
||||
}
|
||||
export type SoundEvents = {
|
||||
[key: string]: {
|
||||
sounds: (string | { name: string })[],
|
||||
},
|
||||
}
|
||||
|
||||
export async function fetchAssets(versionId: VersionId, manifest: VersionManifest) {
|
||||
const version = config.versions.find(v => v.id === versionId)
|
||||
const id = version?.latest ?? manifest.latest.snapshot
|
||||
export async function fetchSounds(versionId: VersionId): Promise<SoundEvents> {
|
||||
const version = config.versions.find(v => v.id === versionId)!
|
||||
try {
|
||||
const versionMeta = await getData(manifest.versions.find(v => v.id === id)!.url)
|
||||
|
||||
return (await getData(versionMeta.assetIndex.url)).objects
|
||||
} catch (e) {
|
||||
throw new Error(`Error occurred while fetching assets for ${version}: ${message(e)}`)
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchSounds(version: VersionId, assets: VersionAssets) {
|
||||
try {
|
||||
const hash = assets['minecraft/sounds.json'].hash
|
||||
return await getData(getResourceUrl(hash))
|
||||
const url = `${mcmeta(version, 'summary')}/sounds/data.min.json`
|
||||
return await getData(url)
|
||||
} catch (e) {
|
||||
throw new Error(`Error occurred while fetching sounds for ${version}: ${message(e)}`)
|
||||
}
|
||||
}
|
||||
|
||||
export function getResourceUrl(hash: string) {
|
||||
return `${corsUrl}${resourceUrl}${hash.slice(0, 2)}/${hash}`
|
||||
export function getSoundUrl(versionId: VersionId, path: string) {
|
||||
const version = config.versions.find(v => v.id === versionId)!
|
||||
return `${mcmeta(version, 'assets')}/assets/minecraft/sounds/${path}.ogg`
|
||||
}
|
||||
|
||||
async function getData<T = any>(url: string, fn: (v: any) => T = (v: any) => v): Promise<T> {
|
||||
@@ -294,275 +151,3 @@ async function deleteMatching(matches: (url: string) => boolean) {
|
||||
console.warn(`[deleteMatching] Failed to open cache ${CACHE_NAME}: ${message(e)}`)
|
||||
}
|
||||
}
|
||||
|
||||
const Noises = [
|
||||
'minecraft:aquifer_barrier',
|
||||
'minecraft:aquifer_fluid_level_floodedness',
|
||||
'minecraft:aquifer_fluid_level_spread',
|
||||
'minecraft:aquifer_lava',
|
||||
'minecraft:badlands_pillar',
|
||||
'minecraft:badlands_pillar_roof',
|
||||
'minecraft:badlands_surface',
|
||||
'minecraft:calcite',
|
||||
'minecraft:cave_cheese',
|
||||
'minecraft:cave_entrance',
|
||||
'minecraft:cave_layer',
|
||||
'minecraft:clay_bands_offset',
|
||||
'minecraft:continentalness',
|
||||
'minecraft:continentalness_large',
|
||||
'minecraft:erosion',
|
||||
'minecraft:erosion_large',
|
||||
'minecraft:gravel',
|
||||
'minecraft:gravel_layer',
|
||||
'minecraft:ice',
|
||||
'minecraft:iceberg_pillar',
|
||||
'minecraft:iceberg_pillar_roof',
|
||||
'minecraft:iceberg_surface',
|
||||
'minecraft:jagged',
|
||||
'minecraft:nether_state_selector',
|
||||
'minecraft:nether_wart',
|
||||
'minecraft:netherrack',
|
||||
'minecraft:noodle',
|
||||
'minecraft:noodle_ridge_a',
|
||||
'minecraft:noodle_ridge_b',
|
||||
'minecraft:noodle_thickness',
|
||||
'minecraft:offset',
|
||||
'minecraft:ore_gap',
|
||||
'minecraft:ore_vein_a',
|
||||
'minecraft:ore_vein_b',
|
||||
'minecraft:ore_veininess',
|
||||
'minecraft:packed_ice',
|
||||
'minecraft:patch',
|
||||
'minecraft:pillar',
|
||||
'minecraft:pillar_rareness',
|
||||
'minecraft:pillar_thickness',
|
||||
'minecraft:powder_snow',
|
||||
'minecraft:ridge',
|
||||
'minecraft:soul_sand_layer',
|
||||
'minecraft:spaghetti_2d',
|
||||
'minecraft:spaghetti_2d_elevation',
|
||||
'minecraft:spaghetti_2d_modulator',
|
||||
'minecraft:spaghetti_2d_thickness',
|
||||
'minecraft:spaghetti_3d_1',
|
||||
'minecraft:spaghetti_3d_2',
|
||||
'minecraft:spaghetti_3d_rarity',
|
||||
'minecraft:spaghetti_3d_thickness',
|
||||
'minecraft:spaghetti_roughness',
|
||||
'minecraft:spaghetti_roughness_modulator',
|
||||
'minecraft:surface',
|
||||
'minecraft:surface_secondary',
|
||||
'minecraft:surface_swamp',
|
||||
'minecraft:temperature',
|
||||
'minecraft:temperature_large',
|
||||
'minecraft:vegetation',
|
||||
'minecraft:vegetation_large',
|
||||
]
|
||||
|
||||
const PlacedFeatures = [
|
||||
'minecraft:acacia_checked',
|
||||
'minecraft:amethyst_geode',
|
||||
'minecraft:bamboo',
|
||||
'minecraft:bamboo_light',
|
||||
'minecraft:bamboo_vegetation',
|
||||
'minecraft:basalt_blobs',
|
||||
'minecraft:basalt_pillar',
|
||||
'minecraft:birch_bees_0002',
|
||||
'minecraft:birch_bees_002',
|
||||
'minecraft:birch_checked',
|
||||
'minecraft:birch_tall',
|
||||
'minecraft:blackstone_blobs',
|
||||
'minecraft:blue_ice',
|
||||
'minecraft:brown_mushroom_nether',
|
||||
'minecraft:brown_mushroom_normal',
|
||||
'minecraft:brown_mushroom_old_growth',
|
||||
'minecraft:brown_mushroom_swamp',
|
||||
'minecraft:brown_mushroom_taiga',
|
||||
'minecraft:cave_vines',
|
||||
'minecraft:chorus_plant',
|
||||
'minecraft:classic_vines_cave_feature',
|
||||
'minecraft:crimson_forest_vegetation',
|
||||
'minecraft:crimson_fungi',
|
||||
'minecraft:dark_forest_vegetation',
|
||||
'minecraft:dark_oak_checked',
|
||||
'minecraft:delta',
|
||||
'minecraft:desert_well',
|
||||
'minecraft:disk_clay',
|
||||
'minecraft:disk_gravel',
|
||||
'minecraft:disk_sand',
|
||||
'minecraft:dripstone_cluster',
|
||||
'minecraft:end_gateway_return',
|
||||
'minecraft:end_island_decorated',
|
||||
'minecraft:end_spike',
|
||||
'minecraft:fancy_oak_bees',
|
||||
'minecraft:fancy_oak_bees_0002',
|
||||
'minecraft:fancy_oak_bees_002',
|
||||
'minecraft:fancy_oak_checked',
|
||||
'minecraft:flower_default',
|
||||
'minecraft:flower_flower_forest',
|
||||
'minecraft:flower_forest_flowers',
|
||||
'minecraft:flower_meadow',
|
||||
'minecraft:flower_plain',
|
||||
'minecraft:flower_swamp',
|
||||
'minecraft:flower_warm',
|
||||
'minecraft:forest_flowers',
|
||||
'minecraft:forest_rock',
|
||||
'minecraft:fossil_lower',
|
||||
'minecraft:fossil_upper',
|
||||
'minecraft:freeze_top_layer',
|
||||
'minecraft:glow_lichen',
|
||||
'minecraft:glowstone',
|
||||
'minecraft:glowstone_extra',
|
||||
'minecraft:grass_bonemeal',
|
||||
'minecraft:ice_patch',
|
||||
'minecraft:ice_spike',
|
||||
'minecraft:iceberg_blue',
|
||||
'minecraft:iceberg_packed',
|
||||
'minecraft:jungle_bush',
|
||||
'minecraft:jungle_tree',
|
||||
'minecraft:kelp_cold',
|
||||
'minecraft:kelp_warm',
|
||||
'minecraft:lake_lava_surface',
|
||||
'minecraft:lake_lava_underground',
|
||||
'minecraft:large_basalt_columns',
|
||||
'minecraft:large_dripstone',
|
||||
'minecraft:lush_caves_ceiling_vegetation',
|
||||
'minecraft:lush_caves_clay',
|
||||
'minecraft:lush_caves_vegetation',
|
||||
'minecraft:mega_jungle_tree_checked',
|
||||
'minecraft:mega_pine_checked',
|
||||
'minecraft:mega_spruce_checked',
|
||||
'minecraft:monster_room',
|
||||
'minecraft:monster_room_deep',
|
||||
'minecraft:mushroom_island_vegetation',
|
||||
'minecraft:nether_sprouts',
|
||||
'minecraft:oak_bees_0002',
|
||||
'minecraft:oak_bees_002',
|
||||
'minecraft:oak_checked',
|
||||
'minecraft:ore_ancient_debris_large',
|
||||
'minecraft:ore_andesite_lower',
|
||||
'minecraft:ore_andesite_upper',
|
||||
'minecraft:ore_blackstone',
|
||||
'minecraft:ore_clay',
|
||||
'minecraft:ore_coal_lower',
|
||||
'minecraft:ore_coal_upper',
|
||||
'minecraft:ore_copper',
|
||||
'minecraft:ore_copper_large',
|
||||
'minecraft:ore_debris_small',
|
||||
'minecraft:ore_diamond',
|
||||
'minecraft:ore_diamond_buried',
|
||||
'minecraft:ore_diamond_large',
|
||||
'minecraft:ore_diorite_lower',
|
||||
'minecraft:ore_diorite_upper',
|
||||
'minecraft:ore_dirt',
|
||||
'minecraft:ore_emerald',
|
||||
'minecraft:ore_gold',
|
||||
'minecraft:ore_gold_deltas',
|
||||
'minecraft:ore_gold_extra',
|
||||
'minecraft:ore_gold_lower',
|
||||
'minecraft:ore_gold_nether',
|
||||
'minecraft:ore_granite_lower',
|
||||
'minecraft:ore_granite_upper',
|
||||
'minecraft:ore_gravel',
|
||||
'minecraft:ore_gravel_nether',
|
||||
'minecraft:ore_infested',
|
||||
'minecraft:ore_iron_middle',
|
||||
'minecraft:ore_iron_small',
|
||||
'minecraft:ore_iron_upper',
|
||||
'minecraft:ore_lapis',
|
||||
'minecraft:ore_lapis_buried',
|
||||
'minecraft:ore_magma',
|
||||
'minecraft:ore_quartz_deltas',
|
||||
'minecraft:ore_quartz_nether',
|
||||
'minecraft:ore_redstone',
|
||||
'minecraft:ore_redstone_lower',
|
||||
'minecraft:ore_soul_sand',
|
||||
'minecraft:ore_tuff',
|
||||
'minecraft:patch_berry_common',
|
||||
'minecraft:patch_berry_rare',
|
||||
'minecraft:patch_cactus_decorated',
|
||||
'minecraft:patch_cactus_desert',
|
||||
'minecraft:patch_crimson_roots',
|
||||
'minecraft:patch_dead_bush',
|
||||
'minecraft:patch_dead_bush_2',
|
||||
'minecraft:patch_dead_bush_badlands',
|
||||
'minecraft:patch_fire',
|
||||
'minecraft:patch_grass_badlands',
|
||||
'minecraft:patch_grass_forest',
|
||||
'minecraft:patch_grass_jungle',
|
||||
'minecraft:patch_grass_normal',
|
||||
'minecraft:patch_grass_plain',
|
||||
'minecraft:patch_grass_savanna',
|
||||
'minecraft:patch_grass_taiga',
|
||||
'minecraft:patch_grass_taiga_2',
|
||||
'minecraft:patch_large_fern',
|
||||
'minecraft:patch_melon',
|
||||
'minecraft:patch_pumpkin',
|
||||
'minecraft:patch_soul_fire',
|
||||
'minecraft:patch_sugar_cane',
|
||||
'minecraft:patch_sugar_cane_badlands',
|
||||
'minecraft:patch_sugar_cane_desert',
|
||||
'minecraft:patch_sugar_cane_swamp',
|
||||
'minecraft:patch_sunflower',
|
||||
'minecraft:patch_tall_grass',
|
||||
'minecraft:patch_tall_grass_2',
|
||||
'minecraft:patch_waterlily',
|
||||
'minecraft:pine_checked',
|
||||
'minecraft:pine_on_snow',
|
||||
'minecraft:pointed_dripstone',
|
||||
'minecraft:red_mushroom_nether',
|
||||
'minecraft:red_mushroom_normal',
|
||||
'minecraft:red_mushroom_old_growth',
|
||||
'minecraft:red_mushroom_swamp',
|
||||
'minecraft:red_mushroom_taiga',
|
||||
'minecraft:rooted_azalea_tree',
|
||||
'minecraft:sea_pickle',
|
||||
'minecraft:seagrass_cold',
|
||||
'minecraft:seagrass_deep',
|
||||
'minecraft:seagrass_deep_cold',
|
||||
'minecraft:seagrass_deep_warm',
|
||||
'minecraft:seagrass_normal',
|
||||
'minecraft:seagrass_river',
|
||||
'minecraft:seagrass_simple',
|
||||
'minecraft:seagrass_swamp',
|
||||
'minecraft:seagrass_warm',
|
||||
'minecraft:small_basalt_columns',
|
||||
'minecraft:spore_blossom',
|
||||
'minecraft:spring_closed',
|
||||
'minecraft:spring_closed_double',
|
||||
'minecraft:spring_delta',
|
||||
'minecraft:spring_lava',
|
||||
'minecraft:spring_lava_frozen',
|
||||
'minecraft:spring_open',
|
||||
'minecraft:spring_water',
|
||||
'minecraft:spruce_checked',
|
||||
'minecraft:spruce_on_snow',
|
||||
'minecraft:super_birch_bees',
|
||||
'minecraft:super_birch_bees_0002',
|
||||
'minecraft:trees_badlands',
|
||||
'minecraft:trees_birch',
|
||||
'minecraft:trees_birch_and_oak',
|
||||
'minecraft:trees_flower_forest',
|
||||
'minecraft:trees_grove',
|
||||
'minecraft:trees_jungle',
|
||||
'minecraft:trees_meadow',
|
||||
'minecraft:trees_old_growth_pine_taiga',
|
||||
'minecraft:trees_old_growth_spruce_taiga',
|
||||
'minecraft:trees_plains',
|
||||
'minecraft:trees_savanna',
|
||||
'minecraft:trees_snowy',
|
||||
'minecraft:trees_sparse_jungle',
|
||||
'minecraft:trees_swamp',
|
||||
'minecraft:trees_taiga',
|
||||
'minecraft:trees_water',
|
||||
'minecraft:trees_windswept_forest',
|
||||
'minecraft:trees_windswept_hills',
|
||||
'minecraft:trees_windswept_savanna',
|
||||
'minecraft:twisting_vines',
|
||||
'minecraft:underwater_magma',
|
||||
'minecraft:vines',
|
||||
'minecraft:void_start_platform',
|
||||
'minecraft:warm_ocean_vegetation',
|
||||
'minecraft:warped_forest_vegetation',
|
||||
'minecraft:warped_fungi',
|
||||
'minecraft:weeping_vines',
|
||||
]
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
import { fetchAssets, fetchManifest, fetchSounds } from './DataFetcher'
|
||||
import type { VersionId } from './Schemas'
|
||||
|
||||
export type VersionManifest = {
|
||||
latest: {
|
||||
release: string,
|
||||
snapshot: string,
|
||||
},
|
||||
versions: {
|
||||
id: string,
|
||||
type: string,
|
||||
url: string,
|
||||
}[],
|
||||
}
|
||||
let Manifest: VersionManifest | Promise<VersionManifest> | null = null
|
||||
|
||||
export type VersionAssets = {
|
||||
[key: string]: {
|
||||
hash: string,
|
||||
},
|
||||
}
|
||||
const VersionAssets: Record<string, VersionAssets | Promise<VersionAssets>> = {}
|
||||
|
||||
export type SoundEvents = {
|
||||
[key: string]: {
|
||||
sounds: (string | { name: string })[],
|
||||
},
|
||||
}
|
||||
const SoundEvents: Record<string, SoundEvents | Promise<SoundEvents>> = {}
|
||||
|
||||
export async function getManifest() {
|
||||
if (!Manifest) {
|
||||
Manifest = fetchManifest()
|
||||
}
|
||||
return Manifest
|
||||
}
|
||||
|
||||
export async function getAssets(version: VersionId) {
|
||||
if (!VersionAssets[version]) {
|
||||
VersionAssets[version] = (async () => {
|
||||
const manifest = await getManifest()
|
||||
return await fetchAssets(version, manifest)
|
||||
})()
|
||||
}
|
||||
return VersionAssets[version]
|
||||
}
|
||||
|
||||
export async function getSounds(version: VersionId) {
|
||||
if (!SoundEvents[version]) {
|
||||
SoundEvents[version] = (async () => {
|
||||
const assets = await getAssets(version)
|
||||
return await fetchSounds(version, assets)
|
||||
})()
|
||||
}
|
||||
return SoundEvents[version]
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
export * from './Changelogs'
|
||||
export * from './DataFetcher'
|
||||
export * from './Manifest'
|
||||
export * from './Schemas'
|
||||
|
||||
103
src/config.json
103
src/config.json
@@ -49,40 +49,18 @@
|
||||
"versions": [
|
||||
{
|
||||
"id": "1.15",
|
||||
"latest": "1.15.2",
|
||||
"refs": {
|
||||
"mcdata_master": "13355f7",
|
||||
"mcassets": "1.15.2"
|
||||
}
|
||||
"ref": "1.15.2"
|
||||
},
|
||||
{
|
||||
"id": "1.16",
|
||||
"latest": "1.16.5",
|
||||
"refs": {
|
||||
"mcdata_master": "1.16.4",
|
||||
"mcassets": "1.16.5",
|
||||
"vanilla_datapack_data": "1.16.4-data",
|
||||
"vanilla_datapack_summary": "1.16.4-summary"
|
||||
}
|
||||
"ref": "1.16.5"
|
||||
},
|
||||
{
|
||||
"id": "1.17",
|
||||
"latest": "1.17.1",
|
||||
"refs": {
|
||||
"mcdata_master": "1.17.1",
|
||||
"mcassets": "1.17.1",
|
||||
"vanilla_datapack_data": "1.17.1-data",
|
||||
"vanilla_datapack_summary": "1.17.1-summary"
|
||||
}
|
||||
"ref": "1.17.1"
|
||||
},
|
||||
{
|
||||
"id": "1.18",
|
||||
"refs": {
|
||||
"mcdata_master": "master",
|
||||
"mcassets": "21w44a",
|
||||
"vanilla_datapack_data": "data",
|
||||
"vanilla_datapack_summary": "summary"
|
||||
},
|
||||
"dynamic": true
|
||||
}
|
||||
],
|
||||
@@ -226,80 +204,5 @@
|
||||
"schema": "model",
|
||||
"minVersion": "1.18"
|
||||
}
|
||||
],
|
||||
"registries": [
|
||||
{ "id": "advancement", "dynamic": true },
|
||||
{ "id": "attribute", "minVersion": "1.16" },
|
||||
{ "id": "block" },
|
||||
{ "id": "block_definition", "path": "blockstates", "asset": true },
|
||||
{ "id": "block_entity_type", "minVersion": "1.18" },
|
||||
{ "id": "block_predicate_type", "minVersion": "1.18" },
|
||||
{ "id": "dimension", "dynamic": true },
|
||||
{ "id": "dimension_type", "dynamic": true },
|
||||
{ "id": "enchantment" },
|
||||
{ "id": "entity_type" },
|
||||
{ "id": "fluid" },
|
||||
{ "id": "function", "dynamic": true },
|
||||
{ "id": "float_provider_type", "minVersion": "1.17" },
|
||||
{ "id": "item" },
|
||||
{ "id": "int_provider_type", "minVersion": "1.17" },
|
||||
{ "id": "height_provider_type", "minVersion": "1.17" },
|
||||
{ "id": "loot_condition_type", "minVersion": "1.16" },
|
||||
{ "id": "loot_condition_type", "minVersion": "1.16" },
|
||||
{ "id": "loot_function_type", "minVersion": "1.16" },
|
||||
{ "id": "loot_nbt_provider_type", "minVersion": "1.17" },
|
||||
{ "id": "loot_number_provider_type", "minVersion": "1.17" },
|
||||
{ "id": "loot_pool_entry_type", "minVersion": "1.16" },
|
||||
{ "id": "loot_score_provider_type", "minVersion": "1.17" },
|
||||
{ "id": "loot_table", "dynamic": true },
|
||||
{ "id": "mob_effect" },
|
||||
{ "id": "model", "path": "models", "asset": true },
|
||||
{ "id": "pos_rule_test", "minVersion": "1.16" },
|
||||
{ "id": "potion", "minVersion": "1.15" },
|
||||
{ "id": "predicate", "dynamic": true },
|
||||
{ "id": "recipe", "dynamic": true },
|
||||
{ "id": "recipe_serializer" },
|
||||
{ "id": "rule_test", "minVersion": "1.16" },
|
||||
{ "id": "sound_event" },
|
||||
{ "id": "stat_type" },
|
||||
{ "id": "structure", "dynamic": true },
|
||||
{ "id": "tag/block", "dynamic": true },
|
||||
{ "id": "tag/entity_type", "dynamic": true },
|
||||
{ "id": "tag/fluid", "dynamic": true },
|
||||
{ "id": "tag/function", "dynamic": true },
|
||||
{ "id": "tag/item", "dynamic": true },
|
||||
{ "id": "texture", "path": "textures", "asset": true },
|
||||
{ "id": "worldgen/biome", "dynamic": true },
|
||||
{ "id": "worldgen/block_state_provider_type", "minVersion": "1.16" },
|
||||
{ "id": "worldgen/block_placer_type", "minVersion": "1.16", "maxVersion": "1.17" },
|
||||
{ "id": "worldgen/biome_source", "minVersion": "1.16" },
|
||||
{ "id": "worldgen/carver", "minVersion": "1.16" },
|
||||
{ "id": "worldgen/chunk_generator", "minVersion": "1.16" },
|
||||
{ "id": "worldgen/configured_carver", "minVersion": "1.16" , "dynamic": true },
|
||||
{ "id": "worldgen/configured_decorator", "minVersion": "1.16" , "dynamic": true },
|
||||
{ "id": "worldgen/configured_feature", "minVersion": "1.16" , "dynamic": true },
|
||||
{ "id": "worldgen/configured_structure_feature", "minVersion": "1.16" , "dynamic": true },
|
||||
{ "id": "worldgen/configured_surface_builder", "minVersion": "1.16" , "dynamic": true },
|
||||
{ "id": "worldgen/decorator", "minVersion": "1.16", "maxVersion": "1.17" },
|
||||
{ "id": "worldgen/feature", "minVersion": "1.16" },
|
||||
{ "id": "worldgen/feature_size_type", "minVersion": "1.16" },
|
||||
{ "id": "worldgen/foliage_placer_type", "minVersion": "1.16" },
|
||||
{ "id": "worldgen/material_condition", "minVersion": "1.18" },
|
||||
{ "id": "worldgen/material_rule", "minVersion": "1.18" },
|
||||
{ "id": "worldgen/noise", "minVersion": "1.18" , "dynamic": true },
|
||||
{ "id": "worldgen/noise_settings", "minVersion": "1.16" , "dynamic": true },
|
||||
{ "id": "worldgen/placed_feature", "minVersion": "1.18" , "dynamic": true },
|
||||
{ "id": "worldgen/placement_modifier_type", "minVersion": "1.18" },
|
||||
{ "id": "worldgen/processor_list", "minVersion": "1.16" , "dynamic": true },
|
||||
{ "id": "worldgen/structure_feature", "minVersion": "1.16" },
|
||||
{ "id": "worldgen/structure_pool_element", "minVersion": "1.16" },
|
||||
{ "id": "worldgen/structure_processor", "minVersion": "1.16" },
|
||||
{ "id": "worldgen/surface_builder", "minVersion": "1.16", "maxVersion": "1.17" },
|
||||
{ "id": "worldgen/template_pool", "minVersion": "1.16" , "dynamic": true },
|
||||
{ "id": "worldgen/tree_decorator_type", "minVersion": "1.16" },
|
||||
{ "id": "worldgen/trunk_placer_type", "minVersion": "1.16" },
|
||||
{ "id": "biome", "maxVersion": "1.15" },
|
||||
{ "id": "worldgen/biome", "minVersion": "1.16", "maxVersion": "1.17", "path": "processed/reports/biomes" },
|
||||
{ "id": "worldgen/biome", "minVersion": "1.18", "path": "processed/reports/worldgen/minecraft/worldgen/biome" }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -255,6 +255,7 @@ main > .controls {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.sounds-controls > *:not(:last-child),
|
||||
.preview-controls > *:not(:last-child),
|
||||
.generator-controls > *:not(:last-child) {
|
||||
margin-right: 8px;
|
||||
@@ -447,6 +448,7 @@ main.has-preview {
|
||||
top: 100%;
|
||||
right: 0;
|
||||
margin-top: 8px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import preact from '@preact/preset-vite'
|
||||
import html from '@rollup/plugin-html'
|
||||
import config from './src/config.json'
|
||||
import { env } from 'process'
|
||||
import copy from 'rollup-plugin-copy'
|
||||
import { defineConfig } from 'vite'
|
||||
import config from './src/config.json'
|
||||
import English from './src/locales/en.json'
|
||||
|
||||
export default defineConfig({
|
||||
@@ -12,27 +12,27 @@ export default defineConfig({
|
||||
rollupOptions: {
|
||||
plugins: [
|
||||
html({
|
||||
fileName: `404.html`,
|
||||
fileName: '404.html',
|
||||
title: '404',
|
||||
template: template,
|
||||
}),
|
||||
html({
|
||||
fileName: `sounds/index.html`,
|
||||
fileName: 'sounds/index.html',
|
||||
title: getTitle({ id: 'title.sounds', page: true }),
|
||||
template: template,
|
||||
}),
|
||||
html({
|
||||
fileName: `changelog/index.html`,
|
||||
fileName: 'changelog/index.html',
|
||||
title: getTitle({ id: 'title.changelog', page: true }),
|
||||
template: template,
|
||||
}),
|
||||
html({
|
||||
fileName: `worldgen/index.html`,
|
||||
fileName: 'worldgen/index.html',
|
||||
title: getTitle({ id: 'worldgen', category: true }),
|
||||
template: template,
|
||||
}),
|
||||
html({
|
||||
fileName: `assets/index.html`,
|
||||
fileName: 'assets/index.html',
|
||||
title: getTitle({ id: 'assets', category: true }),
|
||||
template: template,
|
||||
}),
|
||||
@@ -46,8 +46,8 @@ export default defineConfig({
|
||||
{ src: 'src/sitemap.txt', dest: 'dist' },
|
||||
{ src: 'src/sitemap.txt', dest: 'dist', rename: 'sitemap2.txt' },
|
||||
],
|
||||
hook: 'writeBundle'
|
||||
})
|
||||
hook: 'writeBundle',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -55,8 +55,7 @@ export default defineConfig({
|
||||
stringify: true,
|
||||
},
|
||||
define: {
|
||||
__MCDATA_MASTER_HASH__: env.mcdata_hash,
|
||||
__VANILLA_DATAPACK_SUMMARY_HASH__: env.vanilla_datapack_summary_hash,
|
||||
__LATEST_VERSION__: env.latest_version,
|
||||
},
|
||||
plugins: [preact()],
|
||||
})
|
||||
@@ -68,10 +67,6 @@ function getTitle(m) {
|
||||
return `${English[m.id] ?? ''}${m.page ? '' : ` Generator${m.category === true ? 's' : ''}`} Minecraft ${versions.join(', ')}`
|
||||
}
|
||||
|
||||
function getTitleSuffix(versions ) {
|
||||
|
||||
}
|
||||
|
||||
function template({ files, title }) {
|
||||
const source = files.html.find(f => f.fileName === 'index.html').source
|
||||
return source.replace(/<title>.*<\/title>/, `<title>${title}</title>`)
|
||||
|
||||
Reference in New Issue
Block a user