pages235/src/builtinCommands.ts
2024-02-12 08:11:07 +03:00

126 lines
3.5 KiB
TypeScript

import fs from 'fs'
import { join } from 'path'
import JSZip from 'jszip'
import { readLevelDat } from './loadSave'
import { closeWan, openToWanAndCopyJoinLink } from './localServerMultiplayer'
import { copyFilesAsync, uniqueFileNameFromWorldName } from './browserfs'
import { saveServer } from './flyingSquidUtils'
import { setLoadingScreenStatus } from './utils'
const notImplemented = () => {
return 'Not implemented yet'
}
async function addFolderToZip (folderPath, zip, relativePath) {
const entries = await fs.promises.readdir(folderPath)
for (const entry of entries) {
const entryPath = join(folderPath, entry)
const stats = await fs.promises.stat(entryPath)
const zipEntryPath = join(relativePath, entry)
if (stats.isDirectory()) {
const subZip = zip.folder(zipEntryPath)
await addFolderToZip(entryPath, subZip, zipEntryPath)
} else {
const fileData = await fs.promises.readFile(entryPath)
zip.file(entry, fileData)
}
}
}
export const exportWorld = async (path: string, type: 'zip' | 'folder', zipName = 'world-prismarine-exported') => {
try {
if (type === 'zip') {
setLoadingScreenStatus('Generating zip, this may take a few minutes')
const zip = new JSZip()
await addFolderToZip(path, zip, '')
// Generate the ZIP archive content
const zipContent = await zip.generateAsync({ type: 'blob' })
// Create a download link and trigger the download
const downloadLink = document.createElement('a')
downloadLink.href = URL.createObjectURL(zipContent)
// todo use loaded zip/folder name
downloadLink.download = `${zipName}.zip`
downloadLink.click()
// Clean up the URL object after download
URL.revokeObjectURL(downloadLink.href)
} else {
setLoadingScreenStatus('Preparing export folder')
let dest = '/'
if ((await fs.promises.readdir('/export')).length) {
const { levelDat } = (await readLevelDat(path))!
dest = await uniqueFileNameFromWorldName(levelDat.LevelName, path)
}
setLoadingScreenStatus(`Copying files to ${dest} of selected folder`)
await copyFilesAsync(path, '/export' + dest)
}
} finally {
setLoadingScreenStatus(undefined)
}
}
// todo include in help
const exportLoadedWorld = async () => {
await saveServer()
let { worldFolder } = localServer!.options
if (!worldFolder.startsWith('/')) worldFolder = `/${worldFolder}`
await exportWorld(worldFolder, 'zip')
}
window.exportWorld = exportLoadedWorld
const writeText = (text) => {
bot._client.emit('chat', {
message: JSON.stringify({ text })
})
}
const commands: Array<{
command: string[],
invoke (): Promise<void> | void
//@ts-format-ignore-region
}> = [
{
command: ['/download', '/export'],
invoke: exportLoadedWorld
},
{
command: ['/publish', '/share'],
async invoke () {
const text = await openToWanAndCopyJoinLink(writeText)
if (text) writeText(text)
}
},
{
command: ['/close'],
invoke () {
const text = closeWan()
if (text) writeText(text)
}
},
{
command: ['/save'],
async invoke () {
await saveServer(false)
}
}
]
//@ts-format-ignore-endregion
export const getBuiltinCommandsList = () => commands.flatMap(command => command.command)
export const tryHandleBuiltinCommand = (message) => {
if (!localServer) return
for (const command of commands) {
if (command.command.includes(message)) {
void command.invoke() // ignoring for now
return true
}
}
}