Skip to content

Commit

Permalink
Actually expose getChunk
Browse files Browse the repository at this point in the history
  • Loading branch information
Bradley Watton committed Oct 21, 2020
1 parent d9797c9 commit 8025d72
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 10 deletions.
40 changes: 32 additions & 8 deletions src/Anvil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { CompoundTag } from '@strdst/utils.nbt'
import fs from 'fs-extra'
import path from 'path'
import zlib from 'zlib'
import { Region } from './Region'
import { Region, ChunkNBT } from './Region'

export interface ILocationTableItem {
offset: number,
Expand All @@ -15,7 +15,13 @@ export type LocationTable = Array<ILocationTableItem | null>

export class Anvil {

constructor(private levelPath: string) {}
private regions: Map<string, Region> = new Map()

private constructor(private levelPath: string) {}

private static getRegionId(x: number, z: number) {
return `region:${x}:${z}`
}

private get levelDatPath() {
return path.join(this.levelPath, 'level.dat')
Expand Down Expand Up @@ -64,7 +70,11 @@ export class Anvil {

const table = this.readLocationTable(data)

return new Region(x, z, table, buf)
const region = new Region(x, z, table, buf)

this.regions.set(Anvil.getRegionId(x, z), region)

return region
}

private readLocationTable(data: Buffer): LocationTable {
Expand All @@ -89,12 +99,26 @@ export class Anvil {
return table
}

public async parse(): Promise<void> {
const levelData = new BinaryData(fs.readFileSync(this.levelDatPath))
const regionCoords = await this.getRegions()
const levelDat = await this.parseLevelDat(levelData)
public getChunk(x: number, z: number): null | ChunkNBT {
const [rX, rZ] = Region.getChunkRegion(x, z)

const region = this.regions.get(Anvil.getRegionId(x, z))

if(!region) throw new Error(`Tried getting chunk from an unloaded region: Chunk ${x}:${z}, Region ${rX}:${rZ}`)

return region.getChunkAbsolute(x, z)
}

public static async parse(levelPath: string): Promise<Anvil> {
const anvil = new Anvil(levelPath)

const levelData = new BinaryData(fs.readFileSync(levelPath))
const regionCoords = await anvil.getRegions()
const levelDat = await anvil.parseLevelDat(levelData)

await Promise.all(regionCoords.map(([x, z]) => anvil.getRegion(x, z)))

const regions = await Promise.all(regionCoords.map(([x, z]) => this.getRegion(x, z)))
return anvil
}

}
10 changes: 8 additions & 2 deletions src/Region.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export enum ChunkCompression {
ZLIB = 2,
}

type ChunkNBT = CompoundTag<{
export type ChunkNBT = CompoundTag<{
Level: CompoundTag<{
LightPopulated: ByteTag,
zPos: IntTag,
Expand Down Expand Up @@ -41,8 +41,14 @@ export class Region {
protected chunkData: BinaryData,
) {}

public static getChunkRegion(x: number, z: number): [number, number] {
return [x >> 5, z >> 5]
}

public getChunkAbsolute(x: number, z: number) {
if(x >> 5 !== this.x || z >> 5 !== this.z) throw new Error('Attempted to load chunk from incorrect region')
const [rX, rZ] = Region.getChunkRegion(x, z)

if(rX !== this.x || rZ !== this.z) throw new Error('Attempted to load chunk from incorrect region')

return this.getChunk(x & 0x1F, z & 0x1F)
}
Expand Down

0 comments on commit 8025d72

Please sign in to comment.