feat: add highly experimental logic to try to self-restore any issues with chunks loading by automating f3+a action. write debug info into chat for now. can be disabled feat: rework chunks debug screen showing actually useful information now
79 lines
2 KiB
TypeScript
79 lines
2 KiB
TypeScript
import WorldLoader, { world } from 'prismarine-world'
|
|
import ChunkLoader from 'prismarine-chunk'
|
|
|
|
export type BlockFaceType = {
|
|
side: number
|
|
textureIndex: number
|
|
tint?: [number, number, number]
|
|
isTransparent?: boolean
|
|
|
|
// for testing
|
|
face?: string
|
|
neighbor?: string
|
|
light?: number
|
|
}
|
|
|
|
export type BlockType = {
|
|
faces: BlockFaceType[]
|
|
|
|
// for testing
|
|
block: string
|
|
}
|
|
|
|
export const makeError = (str: string) => {
|
|
reportError?.(str)
|
|
}
|
|
export const makeErrorCritical = (str: string) => {
|
|
throw new Error(str)
|
|
}
|
|
|
|
export const getSyncWorld = (version: string): world.WorldSync => {
|
|
const World = (WorldLoader as any)(version)
|
|
const Chunk = (ChunkLoader as any)(version)
|
|
|
|
const world = new World(version).sync
|
|
|
|
const methods = getAllMethods(world)
|
|
for (const method of methods) {
|
|
if (method.startsWith('set') && method !== 'setColumn') {
|
|
const oldMethod = world[method].bind(world)
|
|
world[method] = (...args) => {
|
|
const arg = args[0]
|
|
if (arg.x !== undefined && !world.getColumnAt(arg)) {
|
|
world.setColumn(Math.floor(arg.x / 16), Math.floor(arg.z / 16), new Chunk(undefined as any))
|
|
}
|
|
oldMethod(...args)
|
|
}
|
|
}
|
|
}
|
|
|
|
return world
|
|
}
|
|
|
|
function getAllMethods (obj) {
|
|
const methods = new Set()
|
|
let currentObj = obj
|
|
|
|
do {
|
|
for (const name of Object.getOwnPropertyNames(currentObj)) {
|
|
if (typeof obj[name] === 'function' && name !== 'constructor') {
|
|
methods.add(name)
|
|
}
|
|
}
|
|
} while ((currentObj = Object.getPrototypeOf(currentObj)))
|
|
|
|
return [...methods] as string[]
|
|
}
|
|
|
|
export const delayedIterator = async <T> (arr: T[], delay: number, exec: (item: T, index: number) => Promise<void>, chunkSize = 1) => {
|
|
// if delay is 0 then don't use setTimeout
|
|
for (let i = 0; i < arr.length; i += chunkSize) {
|
|
if (delay) {
|
|
// eslint-disable-next-line no-await-in-loop
|
|
await new Promise(resolve => {
|
|
setTimeout(resolve, delay)
|
|
})
|
|
}
|
|
await exec(arr[i], i)
|
|
}
|
|
}
|