diff --git a/src/browserfs.ts b/src/browserfs.ts index d38b13a2..41608e30 100644 --- a/src/browserfs.ts +++ b/src/browserfs.ts @@ -14,22 +14,41 @@ import { VALID_REPLAY_EXTENSIONS, openFile } from './packetsReplay/replayPackets import { getFixedFilesize } from './downloadAndOpenFile' import { packetsReplayState } from './react/state/packetsReplayState' import { createFullScreenProgressReporter } from './core/progressReporter' +import { showNotification } from './react/NotificationProvider' const { GoogleDriveFileSystem } = require('google-drive-browserfs/src/backends/GoogleDrive') browserfs.install(window) const defaultMountablePoints = { - '/world': { fs: 'LocalStorage' }, // will be removed in future '/data': { fs: 'IndexedDB' }, '/resourcepack': { fs: 'InMemory' }, // temporary storage for currently loaded resource pack + '/temp': { fs: 'InMemory' } +} +const fallbackMountablePoints = { + '/resourcepack': { fs: 'InMemory' }, // temporary storage for downloaded server resource pack + '/temp': { fs: 'InMemory' } } browserfs.configure({ fs: 'MountableFileSystem', options: defaultMountablePoints, }, async (e) => { - // todo disable singleplayer button - if (e) throw e + if (e) { + browserfs.configure({ + fs: 'MountableFileSystem', + options: fallbackMountablePoints, + }, async (e2) => { + if (e2) { + showNotification('Unknown FS error, cannot continue', e2.message, true) + throw e2 + } + showNotification('Failed to access device storage', `Check you have free space. ${e.message}`, true) + miscUiState.appLoaded = true + miscUiState.singleplayerAvailable = false + }) + return + } await updateTexturePackInstalledState() miscUiState.appLoaded = true + miscUiState.singleplayerAvailable = true }) export const forceCachedDataPaths = {} diff --git a/src/dragndrop.ts b/src/dragndrop.ts index 6c8af856..6be90551 100644 --- a/src/dragndrop.ts +++ b/src/dragndrop.ts @@ -64,7 +64,7 @@ async function handleDroppedFile (file: File) { return } if (file.name.endsWith('.mca')) { - const tempPath = '/data/temp.mca' + const tempPath = '/temp/temp.mca' try { await fs.promises.writeFile(tempPath, Buffer.from(await file.arrayBuffer()) as any) const region = new RegionFile(tempPath) diff --git a/src/globalState.ts b/src/globalState.ts index cc9cd127..74e6c3ff 100644 --- a/src/globalState.ts +++ b/src/globalState.ts @@ -145,6 +145,7 @@ export const miscUiState = proxy({ /** currently trying to load or loaded mc version, after all data is loaded */ loadedDataVersion: null as string | null, appLoaded: false, + singleplayerAvailable: false, usingGamepadInput: false, appConfig: null as AppConfig | null, displaySearchInput: false, diff --git a/src/react/MainMenu.tsx b/src/react/MainMenu.tsx index fc770ad1..09214af2 100644 --- a/src/react/MainMenu.tsx +++ b/src/react/MainMenu.tsx @@ -24,6 +24,7 @@ interface Props { bottomRightLinks?: string versionText?: string onVersionTextClick?: () => void + singleplayerAvailable?: boolean } const httpsRegex = /^https?:\/\// @@ -41,7 +42,8 @@ export default ({ versionStatus, versionTitle, onVersionStatusClick, - bottomRightLinks + bottomRightLinks, + singleplayerAvailable = true }: Props) => { if (!bottomRightLinks?.trim()) bottomRightLinks = undefined // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion @@ -107,6 +109,7 @@ export default ({ style={{ width: 150 }} {...singleplayerLongPress} data-test-id='singleplayer-button' + disabled={!singleplayerAvailable} initialTooltip={{ content: 'Create worlds and play offline', placement: 'left', @@ -183,7 +186,7 @@ export default ({ })} - A Minecraft client in the browser! + A Minecraft client clone in the browser! diff --git a/src/react/MainMenuRenderApp.tsx b/src/react/MainMenuRenderApp.tsx index b12d9ba8..e06ced52 100644 --- a/src/react/MainMenuRenderApp.tsx +++ b/src/react/MainMenuRenderApp.tsx @@ -75,7 +75,7 @@ export const mainMenuState = proxy({ let disableAnimation = false export default () => { const haveModals = useSnapshot(activeModalStack).length - const { gameLoaded, appLoaded, appConfig } = useSnapshot(miscUiState) + const { gameLoaded, appLoaded, appConfig, singleplayerAvailable } = useSnapshot(miscUiState) const noDisplay = haveModals || gameLoaded || !appLoaded @@ -118,6 +118,7 @@ export default () => { return {(state) =>
showModal({ reactType: 'serversList' })} singleplayerAction={async () => { const oldFormatSave = fs.existsSync('./world/level.dat')