Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

World save worker #103

Open
wants to merge 3 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions buildWorkers.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// main worker file intended for computing world geometry is built using prismarine-viewer/buildWorker.mjs
import { build, context } from 'esbuild'
import fs from 'fs'
import { sharedPlugins } from './scripts/esbuildPlugins.mjs'

const watch = process.argv.includes('-w')

const result = await (watch ? context : build)({
bundle: true,
platform: 'browser',
entryPoints: [/* 'prismarine-viewer/examples/webglRendererWorker.ts', */'src/worldSaveWorker.ts'],
outdir: 'prismarine-viewer/public/',
sourcemap: watch ? 'inline' : 'external',
minify: !watch,
treeShaking: true,
logLevel: 'info',
alias: {
'three': './node_modules/three/src/Three.js',
events: 'events', // make explicit
buffer: 'buffer',
'fs': 'browserfs/dist/shims/fs.js',
http: 'http-browserify',
perf_hooks: './src/perf_hooks_replacement.js',
crypto: './src/crypto.js',
stream: 'stream-browserify',
net: 'net-browserify',
assert: 'assert',
dns: './src/dns.js'
},
inject: [
'./src/shims.js'
],
plugins: [
{
name: 'writeOutput',
setup (build) {
build.onEnd(({ outputFiles }) => {
for (const file of outputFiles) {
for (const dir of ['prismarine-viewer/public', 'dist']) {
const baseName = file.path.split('/').pop()
fs.writeFileSync(`${dir}/${baseName}`, file.contents)
}
}
})
}
},
...sharedPlugins
],
loader: {
'.vert': 'text',
'.frag': 'text'
},
mainFields: [
'browser', 'module', 'main'
],
keepNames: true,
write: false,
})

if (watch) {
await result.watch()
}
95 changes: 50 additions & 45 deletions scripts/esbuildPlugins.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const watchExternal = [
]

/** @type {import('esbuild').Plugin[]} */
const plugins = [
const sharedPlugins = [
{
name: 'strict-aliases',
setup (build) {
Expand Down Expand Up @@ -65,6 +65,53 @@ const plugins = [
})
}
},
{
name: 'fix-dynamic-require',
setup (build) {
build.onResolve({
filter: /1\.14\/chunk/,
}, async ({ resolveDir, path }) => {
if (!resolveDir.includes('prismarine-provider-anvil')) return
return {
namespace: 'fix-dynamic-require',
path,
pluginData: {
resolvedPath: `${join(resolveDir, path)}.js`,
resolveDir
},
}
})
build.onLoad({
filter: /.+/,
namespace: 'fix-dynamic-require',
}, async ({ pluginData: { resolvedPath, resolveDir } }) => {
const resolvedFile = await fs.promises.readFile(resolvedPath, 'utf8')
return {
contents: resolvedFile.replace("require(`prismarine-chunk/src/pc/common/BitArray${noSpan ? 'NoSpan' : ''}`)", "noSpan ? require(`prismarine-chunk/src/pc/common/BitArray`) : require(`prismarine-chunk/src/pc/common/BitArrayNoSpan`)"),
resolveDir,
loader: 'js',
}
})
}
},
polyfillNode({
polyfills: {
fs: false,
dns: false,
crypto: false,
events: false,
http: false,
stream: false,
buffer: false,
perf_hooks: false,
net: false,
assert: false,
},
})
]

/** @type {import('esbuild').Plugin[]} */
const plugins = [
{
name: 'data-assets',
setup (build) {
Expand Down Expand Up @@ -256,35 +303,6 @@ const plugins = [
})
}
},
{
name: 'fix-dynamic-require',
setup (build) {
build.onResolve({
filter: /1\.14\/chunk/,
}, async ({ resolveDir, path }) => {
if (!resolveDir.includes('prismarine-provider-anvil')) return
return {
namespace: 'fix-dynamic-require',
path,
pluginData: {
resolvedPath: `${join(resolveDir, path)}.js`,
resolveDir
},
}
})
build.onLoad({
filter: /.+/,
namespace: 'fix-dynamic-require',
}, async ({ pluginData: { resolvedPath, resolveDir } }) => {
const resolvedFile = await fs.promises.readFile(resolvedPath, 'utf8')
return {
contents: resolvedFile.replace("require(`prismarine-chunk/src/pc/common/BitArray${noSpan ? 'NoSpan' : ''}`)", "noSpan ? require(`prismarine-chunk/src/pc/common/BitArray`) : require(`prismarine-chunk/src/pc/common/BitArrayNoSpan`)"),
resolveDir,
loader: 'js',
}
})
}
},
{
name: 'react-displayname',
setup (build) {
Expand All @@ -310,20 +328,7 @@ const plugins = [
})
}
},
polyfillNode({
polyfills: {
fs: false,
dns: false,
crypto: false,
events: false,
http: false,
stream: false,
buffer: false,
perf_hooks: false,
net: false,
assert: false,
},
})
...sharedPlugins
]

export { plugins, connectedClients as clients }
export { plugins, connectedClients as clients, sharedPlugins }
35 changes: 34 additions & 1 deletion src/flyingSquidEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,38 @@ export default () => {
chatInputValueGlobal.value = '/warp '
showModal({ reactType: 'chat' })
})
})
});

(localServer as any).loadChunksOptimized = (chunks) => {
const workersNum = 5
const workers = [] as Worker[]

for (let i = 0; i < workersNum; i++) {
const worker = new Worker('./worldSaveWorker.js')
workers.push(worker)
}

console.time('chunks-main')
for (const [i, worker] of workers.entries()) {
worker.postMessage({
type: 'readChunks',
chunks: chunks.slice(i * chunks.length / workersNum, (i + 1) * chunks.length / workersNum),
folder: localServer!.options.worldFolder + '/region'
})
}

let finishedWorkers = 0

for (const worker of workers) {
// eslint-disable-next-line @typescript-eslint/no-loop-func
worker.onmessage = (msg) => {
if (msg.data.type === 'done') {
finishedWorkers++
if (finishedWorkers === workersNum) {
console.timeEnd('chunks-main')
}
}
}
}
}
}
1 change: 0 additions & 1 deletion src/react/IndicatorEffects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ export default ({ indicators, effects }: {indicators: typeof defaultIndicatorsSt
}, [effects])

useEffect(() => {
// todo use more precise timer for each effect
const interval = setInterval(() => {
for (const [index, effect] of effectsRef.current.entries()) {
if (effect.time === 0) {
Expand Down
3 changes: 3 additions & 0 deletions src/workerWorkaround.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
global = globalThis
globalThis.window = globalThis
window.mcData = {}
72 changes: 72 additions & 0 deletions src/worldSaveWorker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import './workerWorkaround'
import fs from 'fs'
import './fs2'
import { Anvil } from 'prismarine-provider-anvil'
import WorldLoader from 'prismarine-world'

import * as browserfs from 'browserfs'
import { generateSpiralMatrix } from 'flying-squid/dist/utils'
import '../dist/mc-data/1.14'
import { oneOf } from '@zardoy/utils'

console.log('install')
browserfs.install(window)
window.fs = fs

onmessage = (msg) => {
globalThis.readSkylight = false
if (msg.data.type === 'readChunks') {
browserfs.configure({
fs: 'MountableFileSystem',
options: {
'/data': { fs: 'IndexedDB' },
},
}, async () => {
const version = '1.14.4'
const AnvilLoader = Anvil(version)
const World = WorldLoader(version)
// const folder = '/data/worlds/Greenfield v0.5.3-3/region'
const { folder } = msg.data
const world = new World(() => {
throw new Error('Not implemented')
}, new AnvilLoader(folder))
// const chunks = generateSpiralMatrix(20)
const { chunks } = msg.data
// const spawn = {
// x: 113,
// y: 64,

// }
console.log('starting...')
console.time('columns')
const loadedColumns = [] as any[]
const columnToTransfarable = (chunk) => {
return {
biomes: chunk.biomes,
// blockEntities: chunk.blockEntities,
// sectionMask: chunk.sectionMask,
sections: chunk.sections,
// skyLightMask: chunk.skyLightMask,
// blockLightMask: chunk.blockLightMask,
// skyLightSections: chunk.skyLightSections,
// blockLightSections: chunk.blockLightSections
}
}

for (const chunk of chunks) {
const column = await world.getColumn(chunk[0], chunk[1])
if (!column) throw new Error(`Column ${chunk[0]} ${chunk[1]} not found`)
postMessage({
column: columnToTransfarable(column)
})
}
postMessage({
type: 'done',
})

console.timeEnd('columns')
})
}
}

// window.fs = fs
Loading