1
1
import type { NbtChunk } from 'deepslate'
2
- import { getOptional , getTag , loadChunk , readNbt , readRegion , saveChunk , writeNbt , writeRegion } from 'deepslate'
2
+ import { NbtFile , NbtRegion , NbtType } from 'deepslate'
3
3
import * as vscode from 'vscode'
4
4
import { applyEdit , reverseEdit } from './common/Operations'
5
- import type { Logger , NbtEdit , NbtFile } from './common/types'
5
+ import type { Logger , NbtEdit } from './common/types'
6
6
import { Disposable } from './dispose'
7
7
8
8
export class NbtDocument extends Disposable implements vscode . CustomDocument {
@@ -18,41 +18,31 @@ export class NbtDocument extends Disposable implements vscode.CustomDocument {
18
18
return new NbtDocument ( uri , fileData , logger )
19
19
}
20
20
21
- private static async readFile ( uri : vscode . Uri , logger : Logger ) : Promise < NbtFile > {
21
+ private static async readFile ( uri : vscode . Uri , logger : Logger ) : Promise < NbtFile | NbtRegion > {
22
22
const array = await vscode . workspace . fs . readFile ( uri )
23
23
24
24
logger . info ( `Read file [length=${ array . length } , scheme=${ uri . scheme } , extension=${ uri . path . match ( / (?: \. ( [ ^ . ] + ) ) ? $ / ) ?. [ 1 ] } ]` )
25
25
26
26
if ( uri . scheme === 'git' && array . length === 0 ) {
27
- return {
28
- region : false ,
29
- name : '' ,
30
- value : { } ,
31
- }
27
+ return NbtFile . create ( )
32
28
}
33
29
34
30
if ( uri . fsPath . endsWith ( '.mca' ) ) {
35
- return {
36
- region : true ,
37
- chunks : readRegion ( array ) ,
38
- }
31
+ return NbtRegion . read ( array )
39
32
}
40
33
41
34
const littleEndian = uri . fsPath . endsWith ( '.mcstructure' )
42
- const result = readNbt ( array , { littleEndian } )
35
+ const file = NbtFile . read ( array , { littleEndian } )
43
36
44
- logger . info ( `Parsed NBT [compression=${ result . compression ?? 'none' } , littleEndian=${ result . littleEndian ?? false } , bedrockHeader=${ result . bedrockHeader ?? 'none' } ]` )
37
+ logger . info ( `Parsed NBT [compression=${ file . compression ?? 'none' } , littleEndian=${ file . littleEndian ?? false } , bedrockHeader=${ file . bedrockHeader ?? 'none' } ]` )
45
38
46
- return {
47
- region : false ,
48
- ...result ,
49
- }
39
+ return file
50
40
}
51
41
52
42
53
43
private readonly _uri : vscode . Uri
54
44
55
- private _documentData : NbtFile
45
+ private _documentData : NbtFile | NbtRegion
56
46
private readonly _isStructure : boolean
57
47
private readonly _isMap : boolean
58
48
private readonly _isReadOnly : boolean
@@ -61,7 +51,7 @@ export class NbtDocument extends Disposable implements vscode.CustomDocument {
61
51
62
52
private constructor (
63
53
uri : vscode . Uri ,
64
- initialContent : NbtFile ,
54
+ initialContent : NbtFile | NbtRegion ,
65
55
private readonly logger : Logger ,
66
56
) {
67
57
super ( )
@@ -85,13 +75,11 @@ export class NbtDocument extends Disposable implements vscode.CustomDocument {
85
75
86
76
public get dataVersion ( ) {
87
77
const file = this . _documentData
88
- if ( file . region ) {
89
- const firstChunk = file . chunks . find ( c => c . data || c . nbt )
90
- if ( ! firstChunk ) return undefined
91
- loadChunk ( firstChunk )
92
- return getOptional ( ( ) => getTag ( firstChunk . nbt ! . value , 'DataVersion' , 'int' ) , undefined )
78
+ if ( file instanceof NbtRegion ) {
79
+ const firstChunk = file . getFirstChunk ( )
80
+ return firstChunk ?. getRoot ( ) . getNumber ( 'DataVersion' ) ?? 0
93
81
} else {
94
- return getOptional ( ( ) => getTag ( file . value , 'DataVersion' , 'int' ) , undefined )
82
+ return file . root . getNumber ( 'DataVersion' ) ?? 0
95
83
}
96
84
}
97
85
@@ -140,30 +128,26 @@ export class NbtDocument extends Disposable implements vscode.CustomDocument {
140
128
}
141
129
142
130
private isStructureData ( ) {
143
- if ( this . _documentData . region ) return false
144
- const root = this . _documentData . value
145
- return root [ 'size' ] ?. type === 'list'
146
- && root [ 'size' ] . value . type === 'int'
147
- && root [ 'size' ] . value . value . length === 3
148
- && root [ 'blocks' ] ?. type === 'list'
149
- && root [ 'palette' ] ?. type === 'list'
131
+ if ( this . _documentData instanceof NbtRegion ) return false
132
+ const root = this . _documentData . root
133
+ return root . hasList ( 'size' , NbtType . Int , 3 )
134
+ && root . hasList ( 'blocks' ) && root . hasList ( 'palette' )
150
135
}
151
136
152
137
private isMapData ( ) {
153
138
return this . _uri . fsPath . match ( / (?: \\ | \/ ) m a p _ \d + \. d a t $ / ) !== null
154
139
}
155
140
156
141
async getChunkData ( x : number , z : number ) : Promise < NbtChunk > {
157
- if ( ! this . _documentData . region ) {
142
+ if ( ! ( this . _documentData instanceof NbtRegion ) ) {
158
143
throw new Error ( 'File is not a region file' )
159
144
}
160
145
161
- const chunks = this . _documentData . chunks
162
- const chunk = chunks . find ( c => c . x === x && c . z === z )
146
+ const chunk = this . _documentData . findChunk ( x , z )
163
147
if ( ! chunk ) {
164
148
throw new Error ( `Cannot find chunk [${ x } , ${ z } ]` )
165
149
}
166
- return loadChunk ( chunk )
150
+ return chunk
167
151
}
168
152
169
153
async save ( cancellation : vscode . CancellationToken ) : Promise < void > {
@@ -184,16 +168,7 @@ export class NbtDocument extends Disposable implements vscode.CustomDocument {
184
168
return
185
169
}
186
170
187
- if ( nbtFile . region ) {
188
- nbtFile . chunks . filter ( c => c . dirty ) . forEach ( chunk => {
189
- saveChunk ( chunk )
190
- chunk . dirty = false
191
- } )
192
- }
193
-
194
- const fileData = nbtFile . region
195
- ? writeRegion ( nbtFile . chunks )
196
- : writeNbt ( nbtFile . value , nbtFile )
171
+ const fileData = nbtFile . write ( )
197
172
198
173
await vscode . workspace . fs . writeFile ( targetResource , fileData )
199
174
}
@@ -202,14 +177,7 @@ export class NbtDocument extends Disposable implements vscode.CustomDocument {
202
177
const diskContent = await NbtDocument . readFile ( this . uri , this . logger )
203
178
this . _documentData = diskContent
204
179
this . _edits = this . _savedEdits
205
- this . _onDidChangeDocument . fire ( {
206
- ops : [ {
207
- type : 'set' ,
208
- path : [ ] ,
209
- old : null ,
210
- new : this . _documentData ,
211
- } ] ,
212
- } )
180
+ // TODO: notify listeners that document has reset
213
181
}
214
182
215
183
async backup ( destination : vscode . Uri , cancellation : vscode . CancellationToken ) : Promise < vscode . CustomDocumentBackup > {
0 commit comments