diff --git a/src/downloadAndOpenWorld.ts b/src/downloadAndOpenFile.ts similarity index 62% rename from src/downloadAndOpenWorld.ts rename to src/downloadAndOpenFile.ts index fb0846c5d..6d2a47f9d 100644 --- a/src/downloadAndOpenWorld.ts +++ b/src/downloadAndOpenFile.ts @@ -1,4 +1,5 @@ import { openWorldZip } from './browserfs' +import { installTexturePack } from './texturePack' import { setLoadingScreenStatus } from './utils' import prettyBytes from 'pretty-bytes' @@ -6,21 +7,21 @@ const getConstantFilesize = (bytes: number) => { return prettyBytes(bytes, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) } -export const hasMapUrl = () => { - const qs = new URLSearchParams(window.location.search) - const mapUrl = qs.get('map') - return !!mapUrl -} - export default async () => { const qs = new URLSearchParams(window.location.search) - const mapUrl = qs.get('map') - if (!mapUrl) return + let mapUrl = qs.get('map') + const texturepack = qs.get('texturepack') + // fixme + if (texturepack) mapUrl = texturepack + if (!mapUrl) return false - const menu = document.getElementById('play-screen') - menu.style = 'display: none;' + if (!texturepack) { + const menu = document.getElementById('play-screen') + menu.style = 'display: none;' + } const name = mapUrl.slice(mapUrl.lastIndexOf('/') + 1).slice(-25) - setLoadingScreenStatus(`Downloading world ${name}...`) + const downloadThing = texturepack ? 'texturepack' : 'world' + setLoadingScreenStatus(`Downloading ${downloadThing} ${name}...`) const response = await fetch(mapUrl) const contentType = response.headers.get('Content-Type') @@ -28,7 +29,7 @@ export default async () => { alert('Invalid map file') } const contentLength = +response.headers.get('Content-Length') - setLoadingScreenStatus(`Downloading world ${name}: have to download ${getConstantFilesize(contentLength)}...`) + setLoadingScreenStatus(`Downloading ${downloadThing} ${name}: have to download ${getConstantFilesize(contentLength)}...`) let downloadedBytes = 0 const buffer = await new Response( @@ -51,7 +52,7 @@ export default async () => { // Update your progress bar or display the progress value as needed if (contentLength) { - setLoadingScreenStatus(`Download Progress: ${Math.floor(progress)}% (${getConstantFilesize(downloadedBytes)} / ${getConstantFilesize(contentLength)}))`, false, true) + setLoadingScreenStatus(`Download ${downloadThing} progress: ${Math.floor(progress)}% (${getConstantFilesize(downloadedBytes)} / ${getConstantFilesize(contentLength)}))`, false, true) } // Pass the received data to the controller @@ -60,5 +61,9 @@ export default async () => { }, }) ).arrayBuffer() - await openWorldZip(buffer) + if (texturepack) { + await installTexturePack(buffer) + } else { + await openWorldZip(buffer) + } } diff --git a/src/index.ts b/src/index.ts index f45ad0f32..b7d6ade4d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -31,7 +31,7 @@ import './controls' import './dragndrop' import './browserfs' import './eruda' -import downloadAndOpenWorld, { hasMapUrl } from './downloadAndOpenWorld' +import downloadAndOpenFile from './downloadAndOpenFile' import net from 'net' import Stats from 'stats.js' @@ -63,8 +63,7 @@ import { isCypress, loadScript, toMajorVersion, - setLoadingScreenStatus, - resolveTimeout + setLoadingScreenStatus } from './utils' import { @@ -756,9 +755,9 @@ window.addEventListener('keydown', (e) => { addPanoramaCubeMap() showModal(document.getElementById('title-screen')) main() -if (hasMapUrl()) { - downloadAndOpenWorld() -} else { +downloadAndOpenFile().then((downloadAction) => { + if (downloadAction !== false) return + window.addEventListener('hud-ready', (e) => { // try to connect to peer const qs = new URLSearchParams(window.location.search) @@ -776,4 +775,7 @@ if (hasMapUrl()) { }) } }) -} +}, (err) => { + console.error(err) + alert(`Failed to download file: ${err}`) +}) diff --git a/src/texturePack.ts b/src/texturePack.ts index 15cec53fa..39e39e5c3 100644 --- a/src/texturePack.ts +++ b/src/texturePack.ts @@ -8,6 +8,7 @@ import type { Viewer } from 'prismarine-viewer/viewer/lib/viewer' import { removeFileRecursiveAsync } from './browserfs' import { miscUiState } from './globalState' import { subscribeKey } from 'valtio/utils' +import { showNotification } from './menus/notification' function nextPowerOfTwo(n) { if (n === 0) return 1 @@ -63,7 +64,7 @@ export const installTexturePack = async (file: File | ArrayBuffer) => { await uninstallTexturePack() } catch (err) { } - const status = 'Installing resource pack: copying all files'; + const status = 'Installing resource pack: copying all files' setLoadingScreenStatus(status) // extract the zip and write to fs every file in it const zip = new JSZip() @@ -71,21 +72,28 @@ export const installTexturePack = async (file: File | ArrayBuffer) => { if (!zipFile.file('pack.mcmeta')) throw new Error('Not a resource pack: missing pack.mcmeta') await mkdirRecursive(texturePackBasePath) - const allFilesArr = Object.entries(zipFile.files); - let i = 0 - for (const [path, file] of allFilesArr) { - const writePath = join(texturePackBasePath, path); - if (path.endsWith('/')) continue + const allFilesArr = Object.entries(zipFile.files) + let done = 0 + const upStatus = () => { + setLoadingScreenStatus(`${status} ${Math.round(++done / allFilesArr.length * 100)}%`) + } + await Promise.all(allFilesArr.map(async ([path, file]) => { + const writePath = join(texturePackBasePath, path) + if (path.endsWith('/')) return await mkdirRecursive(dirname(writePath)) await fs.promises.writeFile(writePath, Buffer.from(await file.async('arraybuffer'))) - setLoadingScreenStatus(`${status} ${Math.round(++i / allFilesArr.length * 100)}%`) - } + done++ + upStatus() + })) await fs.promises.writeFile(join(texturePackBasePath, 'name.txt'), file['name'] ?? '??', 'utf8') if (viewer?.world.active) { await genTexturePackTextures(viewer.version) } setLoadingScreenStatus(undefined) + showNotification({ + message: 'Texturepack installed!', + }) } const existsAsync = async (path) => { @@ -144,7 +152,7 @@ const setCustomTexturePackData = (blockTextures, blockStates) => { const getSizeFromImage = async (filePath: string) => { const probeImg = new Image() - const file = await fs.promises.readFile(filePath, 'base64'); + const file = await fs.promises.readFile(filePath, 'base64') probeImg.src = `data:image/png;base64,${file}` await new Promise((resolve, reject) => { probeImg.onload = resolve @@ -155,11 +163,17 @@ const getSizeFromImage = async (filePath: string) => { export const genTexturePackTextures = async (version: string) => { setCustomTexturePackData(undefined, undefined) - const blocksBasePath = '/userData/resourcePacks/default/assets/minecraft/textures/blocks'; + let blocksBasePath = '/userData/resourcePacks/default/assets/minecraft/textures/block' + // todo not clear why this is needed + const blocksBasePathAlt = '/userData/resourcePacks/default/assets/minecraft/textures/blocks' const blocksGenereatedPath = `/userData/resourcePacks/default/${version}.png` const genereatedPathData = `/userData/resourcePacks/default/${version}.json` if (await existsAsync(blocksBasePath) === false) { - return + if (await existsAsync(blocksBasePathAlt) === false) { + return + } else { + blocksBasePath = blocksBasePathAlt + } } if (await existsAsync(blocksGenereatedPath) === true) { applyTexturePackData(version, JSON.parse(await fs.promises.readFile(genereatedPathData, 'utf8')), await fs.promises.readFile(blocksGenereatedPath, 'utf8')) @@ -208,7 +222,7 @@ export const genTexturePackTextures = async (version: string) => { await new Promise(resolve => { _imgCustom.onload = () => { imgCustom = _imgCustom - resolve(); + resolve() } _imgCustom.onerror = () => { console.log('Skipping issued texture', fileName) @@ -227,10 +241,10 @@ export const genTexturePackTextures = async (version: string) => { ctx.drawImage(img, xOrig, yOrig, originalTileSize, originalTileSize, x, y, tileSize, tileSize) } } - const blockDataUrl = canvas.toDataURL('image/png'); + const blockDataUrl = canvas.toDataURL('image/png') const newData: TextureResolvedData = { blockSize: tileSize, - }; + } await fs.promises.writeFile(genereatedPathData, JSON.stringify(newData), 'utf8') await fs.promises.writeFile(blocksGenereatedPath, blockDataUrl, 'utf8') await applyTexturePackData(version, newData, blockDataUrl)