feat: implement fast world loading with file descriptor & http backend! (#182)
This commit is contained in:
parent
9e055ebb09
commit
24fd4d4fc0
4 changed files with 76 additions and 2 deletions
26
README.MD
26
README.MD
|
|
@ -141,7 +141,31 @@ Single player specific:
|
|||
- `?singleplayer=1` - Create empty world on load. Nothing will be saved
|
||||
- `?version=<version>` - Set the version for the singleplayer world (when used with `?singleplayer=1`)
|
||||
- `?noSave=true` - Disable auto save on unload / disconnect / export whenever a world is loaded. Only manual save with `/save` command will work.
|
||||
- `?map=<map_url>` - Load the map from ZIP. You can use any url, but it must be CORS enabled.
|
||||
- `?map=<map_url>` - Load the map from ZIP. You can use any url, but it must be **CORS enabled**.
|
||||
- `?mapDir=<index_file_url>` - Load the map from a file descriptor. It's recommended and the fastest way to load world but requires additional setup. The file must be in the following format:
|
||||
|
||||
```json
|
||||
{
|
||||
"baseUrl": "<url>",
|
||||
"index": {
|
||||
"level.dat": null,
|
||||
"region": {
|
||||
"r.-1.-1.mca": null,
|
||||
"r.-1.0.mca": null,
|
||||
"r.0.-1.mca": null,
|
||||
"r.0.0.mca": null,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note that `mapDir` also accepts base64 encoded JSON like so:
|
||||
`?mapDir=data:application/json;base64,...` where `...` is the base64 encoded JSON of the index file.
|
||||
In this case you must use `?mapDirBaseUrl` to specify the base URL to fetch the files from index.
|
||||
|
||||
- `?mapDirBaseUrl` - See above.
|
||||
|
||||
<!-- - `?mapDirGuess=<base_url>` - Load the map from the provided URL and paths will be guessed with a few additional fetch requests. -->
|
||||
|
||||
General:
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ const app = express()
|
|||
|
||||
const isProd = process.argv.includes('--prod')
|
||||
app.use(compression())
|
||||
// app.use(cors())
|
||||
app.use(netApi({ allowOrigin: '*' }))
|
||||
if (!isProd) {
|
||||
app.use('/sounds', express.static(path.join(__dirname, './generated/sounds/')))
|
||||
|
|
|
|||
|
|
@ -433,6 +433,44 @@ export const copyFilesAsync = async (pathSrc: string, pathDest: string, fileCopi
|
|||
}))
|
||||
}
|
||||
|
||||
export const openWorldFromHttpDir = async (fileDescriptorUrl: string/* | undefined */, baseUrl = fileDescriptorUrl.split('/').slice(0, -1).join('/')) => {
|
||||
// todo try go guess mode
|
||||
let index
|
||||
const file = await fetch(fileDescriptorUrl).then(async a => a.json())
|
||||
if (file.baseUrl) {
|
||||
baseUrl = new URL(file.baseUrl, baseUrl).toString()
|
||||
index = file.index
|
||||
} else {
|
||||
index = file
|
||||
}
|
||||
if (!index) throw new Error(`The provided mapDir file is not valid descriptor file! ${fileDescriptorUrl}`)
|
||||
await new Promise<void>(async resolve => {
|
||||
browserfs.configure({
|
||||
fs: 'MountableFileSystem',
|
||||
options: {
|
||||
...defaultMountablePoints,
|
||||
'/world': {
|
||||
fs: 'HTTPRequest',
|
||||
options: {
|
||||
index,
|
||||
baseUrl
|
||||
}
|
||||
}
|
||||
},
|
||||
}, (e) => {
|
||||
if (e) throw e
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
fsState.saveLoaded = false
|
||||
fsState.isReadonly = true
|
||||
fsState.syncFs = false
|
||||
fsState.inMemorySave = false
|
||||
|
||||
await loadSave()
|
||||
}
|
||||
|
||||
// todo rename method
|
||||
const openWorldZipInner = async (file: File | ArrayBuffer, name = file['name']) => {
|
||||
await new Promise<void>(async resolve => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import prettyBytes from 'pretty-bytes'
|
||||
import { openWorldZip } from './browserfs'
|
||||
import { openWorldFromHttpDir, openWorldZip } from './browserfs'
|
||||
import { getResourcePackNames, installTexturePack, resourcePackState, updateTexturePackInstalledState } from './resourcePack'
|
||||
import { setLoadingScreenStatus } from './utils'
|
||||
|
||||
|
|
@ -9,6 +9,17 @@ export const getFixedFilesize = (bytes: number) => {
|
|||
|
||||
const inner = async () => {
|
||||
const qs = new URLSearchParams(window.location.search)
|
||||
const mapUrlDir = qs.get('mapDir')
|
||||
const mapUrlDirGuess = qs.get('mapDirGuess')
|
||||
const mapUrlDirBaseUrl = qs.get('mapDirBaseUrl')
|
||||
if (mapUrlDir) {
|
||||
await openWorldFromHttpDir(mapUrlDir, mapUrlDirBaseUrl ?? undefined)
|
||||
return true
|
||||
}
|
||||
if (mapUrlDirGuess) {
|
||||
// await openWorldFromHttpDir(undefined, mapUrlDirGuess)
|
||||
return true
|
||||
}
|
||||
let mapUrl = qs.get('map')
|
||||
const texturepack = qs.get('texturepack')
|
||||
// fixme
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue