From a228e1cc996a22ddf301362d2ea4296357cdfeee Mon Sep 17 00:00:00 2001 From: Vitaly Date: Sat, 2 Sep 2023 03:37:28 +0300 Subject: [PATCH] allow to load worlf from ?map= qs url --- src/browserfs.js | 6 +++--- src/downloadAndOpenWorld.ts | 36 ++++++++++++++++++++++++++++++++++++ src/index.js | 18 ++++-------------- src/loadFolder.ts | 6 ++++-- 4 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 src/downloadAndOpenWorld.ts diff --git a/src/browserfs.js b/src/browserfs.js index f5f34c08..ca51aca3 100644 --- a/src/browserfs.js +++ b/src/browserfs.js @@ -152,7 +152,7 @@ export const openWorldDirectory = async (/** @type {FileSystemDirectoryHandle?} loadFolder() } -export const openWorldZip = async (/** @type {File} */file) => { +export const openWorldZip = async (/** @type {File | ArrayBuffer} */file, name = file['name']) => { await new Promise(async resolve => { browserfs.configure({ // todo @@ -161,8 +161,8 @@ export const openWorldZip = async (/** @type {File} */file) => { "/world": { fs: "ZipFS", options: { - zipData: Buffer.from(await file.arrayBuffer()), - name: file.name + zipData: Buffer.from(file instanceof File ? (await file.arrayBuffer()) : file), + name } } }, diff --git a/src/downloadAndOpenWorld.ts b/src/downloadAndOpenWorld.ts new file mode 100644 index 00000000..e14e4deb --- /dev/null +++ b/src/downloadAndOpenWorld.ts @@ -0,0 +1,36 @@ +import { openWorldZip } from './browserfs' +import { setLoadingScreenStatus } from './utils' +import { filesize } from 'filesize' + +window.addEventListener('load', async (e) => { + const qs = new URLSearchParams(window.location.search) + const mapUrl = qs.get('map') + if (!mapUrl) return + + const menu = document.getElementById('play-screen') + menu.style = 'display: none;' + const name = mapUrl.slice(mapUrl.lastIndexOf('/') + 1).slice(-25) + setLoadingScreenStatus(`Downloading world ${name}...`) + + const response = await fetch(mapUrl) + const contentLength = +response.headers.get('Content-Length') + setLoadingScreenStatus(`Downloading world ${name}: have to download ${filesize(contentLength)}...`) + // const reader = response.body!.getReader() + // let doneValue + // while (true) { + // // done is true for the last chunk + // // value is Uint8Array of the chunk bytes + // const { done, value } = await reader.read() + + // if (done) { + // doneValue = value + // break + // } + + // setLoadingScreenStatus(`Downloading world ${name}: ${filesize(value.length)} / ${filesize(contentLength)}MB...`) + // } + await openWorldZip(await response.arrayBuffer()) +}) + +export default async () => { +} diff --git a/src/index.js b/src/index.js index 91d51bff..659aea6b 100644 --- a/src/index.js +++ b/src/index.js @@ -40,6 +40,8 @@ require('./reactUi.jsx') require('./botControls') require('./dragndrop') require('./browserfs') +require('./eruda') +require('./downloadAndOpenWorld') const net = require('net') const Stats = require('stats.js') @@ -56,7 +58,7 @@ const Cursor = require('./cursor').default global.THREE = require('three') const { initVR } = require('./vr') const { activeModalStack, showModal, hideModal, hideCurrentModal, activeModalStacks, replaceActiveModalStack, isGameActive, miscUiState, gameAdditionalState } = require('./globalState') -const { pointerLock, goFullscreen, toNumber, isCypress } = require('./utils') +const { pointerLock, goFullscreen, toNumber, isCypress, loadScript, toMajorVersion, setLoadingScreenStatus } = require('./utils') const { notification } = require('./menus/notification') const { removePanorama, addPanoramaCubeMap, initPanoramaOptions } = require('./panorama') const { startLocalServer, unsupportedLocalServerFeatures } = require('./createLocalServer') @@ -174,17 +176,6 @@ const hud = document.getElementById('hud') const optionsScrn = document.getElementById('options-screen') const pauseMenu = document.getElementById('pause-screen') -function setLoadingScreenStatus (status, isError = false) { - // todo update in component instead - showModal(loadingScreen) - if (loadingScreen.hasError) { - miscUiState.gameLoaded = false - return - } - loadingScreen.hasError = isError - loadingScreen.status = status -} - let mouseMovePostHandle = (e) => { } let lastMouseCall function onMouseMove (e) { @@ -366,7 +357,7 @@ async function connect (connectOptions) { }) let singlePlayerServer try { - Object.assign(serverOptions, _.defaultsDeep({}, connectOptions.serverOverrides, options.localServerOptions, serverOptions)) + Object.assign(serverOptions, _.defaultsDeep({}, connectOptions.serverOverrides ?? {}, options.localServerOptions, serverOptions)) let version = connectOptions.botVersion ?? serverOptions.version if (version) { setLoadingScreenStatus(`Downloading data for ${version}`) @@ -376,7 +367,6 @@ async function connect (connectOptions) { if (singeplayer) { window.serverDataChannel ??= {} window.worldLoaded = false - Object.assign(serverOptions, _.defaultsDeep({}, connectOptions.serverOverrides, options.localServerOptions, serverOptions)) singlePlayerServer = window.singlePlayerServer = startLocalServer() // todo need just to call quit if started // loadingScreen.maybeRecoverable = false diff --git a/src/loadFolder.ts b/src/loadFolder.ts index 14d7f686..6b7a3e5d 100644 --- a/src/loadFolder.ts +++ b/src/loadFolder.ts @@ -18,6 +18,7 @@ export const fsState = proxy({ const PROPOSE_BACKUP = true +// todo rename to loadWorld export const loadFolder = async (root = '/world') => { // todo do it in singleplayer as well for (const key in forceCachedDataPaths) { @@ -47,7 +48,8 @@ export const loadFolder = async (root = '/world') => { const parsedRaw = await parseNbt(Buffer.from(levelDatContent)) const levelDat: import('./mcTypes').LevelDat = nbt.simplify(parsedRaw).Data - version = levelDat.Version?.Name + const qs = new URLSearchParams(window.location.search) + version = levelDat.Version?.Name ?? qs.get('version') if (!version) { const newVersion = prompt(`In 1.8 and before world save doesn\'t contain version info, please enter version you want to use to load the world.\nSupported versions ${supportedVersions.join(', ')}`, '1.8.8') if (!newVersion) return @@ -69,7 +71,7 @@ export const loadFolder = async (root = '/world') => { if (levelDat.generatorName) { isFlat = levelDat.generatorName === 'flat' } - if (!isFlat) { + if (!isFlat && levelDat.generatorName !== 'default' && levelDat.generatorName !== 'customized') { warnings.push(`Generator ${levelDat.generatorName} may not be supported yet`) }