Skip to content

Commit 6422abc

Browse files
frej4189Frej Alexander Nielsen
and
Frej Alexander Nielsen
authored
Fix direct palettes (#232)
* Fix direct palette parsing * Fix mcData parsing * Fix chunk dumping for 1.18+ * Generalize readBuffer and writeBuffer methods in bitArray * Fix dumping/loading issues * Fix lint * Remove version filter from test * Apply fixes to earlier versions * Update readOffset to skip entire long array * Add hypixel chunk dumps * Fix lint --------- Co-authored-by: Frej Alexander Nielsen <[email protected]>
1 parent bed7867 commit 6422abc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+170
-100
lines changed

src/pc/1.13/ChunkColumn.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const constants = require('../common/constants')
44
const BitArray = require('../common/BitArray')
55
const varInt = require('../common/varInt')
66
const CommonChunkColumn = require('../common/CommonChunkColumn')
7+
const neededBits = require('../common/neededBits')
78

89
// wrap with func to provide version specific Block
910
module.exports = (Block, mcData) => {
@@ -17,6 +18,7 @@ module.exports = (Block, mcData) => {
1718
this.biomes = Array(
1819
constants.SECTION_WIDTH * constants.SECTION_WIDTH
1920
).fill(1)
21+
this.maxBitsPerBlock = neededBits(Object.values(mcData.blocks).reduce((high, block) => Math.max(high, block.maxStateId), 0))
2022
}
2123

2224
toJson () {
@@ -139,7 +141,9 @@ module.exports = (Block, mcData) => {
139141
if (stateId === 0) {
140142
return
141143
}
142-
section = new ChunkSection()
144+
section = new ChunkSection({
145+
maxBitsPerBlock: this.maxBitsPerBlock
146+
})
143147
this.sectionMask |= 1 << sectionIndex
144148
this.sections[sectionIndex] = section
145149
}
@@ -235,11 +239,10 @@ module.exports = (Block, mcData) => {
235239
}
236240

237241
// number of items in data array
238-
const numLongs = varInt.read(reader)
239242
const dataArray = new BitArray({
240-
bitsPerValue: Math.ceil((numLongs * 64) / 4096),
243+
bitsPerValue: bitsPerBlock > constants.MAX_BITS_PER_BLOCK ? this.maxBitsPerBlock : bitsPerBlock,
241244
capacity: 4096
242-
}).readBuffer(reader)
245+
}).readBuffer(reader, varInt.read(reader) * 2)
243246

244247
const blockLight = new BitArray({
245248
bitsPerValue: 4,
@@ -257,6 +260,7 @@ module.exports = (Block, mcData) => {
257260
data: dataArray,
258261
palette,
259262
blockLight,
263+
maxBitsPerBlock: this.maxBitsPerBlock,
260264
...(skyLightSent ? { skyLight } : { skyLight: null })
261265
})
262266
this.sections[y] = section

src/pc/1.13/ChunkSection.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const BitArray = require('../common/BitArray')
22
const neededBits = require('../common/neededBits')
33
const constants = require('../common/constants')
44
const varInt = require('../common/varInt')
5+
const GLOBAL_BITS_PER_BLOCK = 13
56

67
function getBlockIndex (pos) {
78
return (pos.y << 8) | (pos.z << 4) | pos.x
@@ -55,6 +56,7 @@ class ChunkSection {
5556
this.blockLight = options.blockLight
5657
this.skyLight = options.skyLight
5758
this.solidBlockCount = options.solidBlockCount
59+
this.maxBitsPerBlock = options.maxBitsPerBlock || GLOBAL_BITS_PER_BLOCK
5860
}
5961

6062
toJson () {
@@ -116,7 +118,7 @@ class ChunkSection {
116118
} else {
117119
// switches to the global palette
118120
const newData = new BitArray({
119-
bitsPerValue: constants.GLOBAL_BITS_PER_BLOCK,
121+
bitsPerValue: this.maxBitsPerBlock,
120122
capacity: constants.BLOCK_SECTION_VOLUME
121123
})
122124
for (let i = 0; i < constants.BLOCK_SECTION_VOLUME; i++) {
@@ -177,10 +179,8 @@ class ChunkSection {
177179
})
178180
}
179181

180-
// write the number of longs to be written
181-
varInt.write(smartBuffer, this.data.length())
182-
183182
// write block data
183+
varInt.write(smartBuffer, this.data.length())
184184
this.data.writeBuffer(smartBuffer)
185185

186186
// write block light data

src/pc/1.14/ChunkColumn.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const ChunkSection = require('../common/CommonChunkSection')(BitArray)
44
const CommonChunkColumn = require('../common/CommonChunkColumn')
55
const constants = require('../common/constants')
66
const varInt = require('../common/varInt')
7+
const neededBits = require('../common/neededBits')
78

89
// wrap with func to provide version specific Block
910
module.exports = (Block, mcData) => {
@@ -20,6 +21,7 @@ module.exports = (Block, mcData) => {
2021
this.blockLightMask = 0
2122
this.skyLightSections = Array(constants.NUM_SECTIONS + 2).fill(null)
2223
this.blockLightSections = Array(constants.NUM_SECTIONS + 2).fill(null)
24+
this.maxBitsPerBlock = neededBits(Object.values(mcData.blocks).reduce((high, block) => Math.max(high, block.maxStateId), 0))
2325
}
2426

2527
toJson () {
@@ -150,7 +152,9 @@ module.exports = (Block, mcData) => {
150152
if (stateId === 0) {
151153
return
152154
}
153-
section = new ChunkSection()
155+
section = new ChunkSection({
156+
maxBitsPerBlock: this.maxBitsPerBlock
157+
})
154158
this.sectionMask |= 1 << sectionIndex
155159
this.sections[sectionIndex] = section
156160
}
@@ -257,16 +261,16 @@ module.exports = (Block, mcData) => {
257261
}
258262

259263
// number of items in data array
260-
const numLongs = varInt.read(reader)
261264
const dataArray = new BitArray({
262-
bitsPerValue: Math.ceil((numLongs * 64) / 4096),
265+
bitsPerValue: bitsPerBlock > constants.MAX_BITS_PER_BLOCK ? this.maxBitsPerBlock : bitsPerBlock,
263266
capacity: 4096
264-
}).readBuffer(reader)
267+
}).readBuffer(reader, varInt.read(reader) * 2)
265268

266269
const section = new ChunkSection({
267270
data: dataArray,
268271
palette,
269-
solidBlockCount
272+
solidBlockCount,
273+
maxBitsPerBlock: this.maxBitsPerBlock
270274
})
271275
this.sections[y] = section
272276
}

src/pc/1.15/ChunkColumn.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const ChunkSection = require('../common/CommonChunkSection')(BitArray)
44
const CommonChunkColumn = require('../common/CommonChunkColumn')
55
const constants = require('../common/constants')
66
const varInt = require('../common/varInt')
7+
const neededBits = require('../common/neededBits')
78

89
// wrap with func to provide version specific Block
910
module.exports = (Block, mcData) => {
@@ -18,6 +19,7 @@ module.exports = (Block, mcData) => {
1819
this.blockLightMask = 0
1920
this.skyLightSections = Array(constants.NUM_SECTIONS + 2).fill(null)
2021
this.blockLightSections = Array(constants.NUM_SECTIONS + 2).fill(null)
22+
this.maxBitsPerBlock = neededBits(Object.values(mcData.blocks).reduce((high, block) => Math.max(high, block.maxStateId), 0))
2123
}
2224

2325
toJson () {
@@ -144,7 +146,9 @@ module.exports = (Block, mcData) => {
144146
if (stateId === 0) {
145147
return
146148
}
147-
section = new ChunkSection()
149+
section = new ChunkSection({
150+
maxBitsPerBlock: this.maxBitsPerBlock
151+
})
148152
this.sectionMask |= 1 << sectionIndex
149153
this.sections[sectionIndex] = section
150154
}
@@ -254,16 +258,16 @@ module.exports = (Block, mcData) => {
254258
}
255259

256260
// number of items in data array
257-
varInt.read(reader) // numLongs
258261
const dataArray = new BitArray({
259-
bitsPerValue: bitsPerBlock,
262+
bitsPerValue: bitsPerBlock > constants.MAX_BITS_PER_BLOCK ? this.maxBitsPerBlock : bitsPerBlock,
260263
capacity: 4096
261-
}).readBuffer(reader)
264+
}).readBuffer(reader, varInt.read(reader) * 2)
262265

263266
const section = new ChunkSection({
264267
data: dataArray,
265268
palette,
266-
solidBlockCount
269+
solidBlockCount,
270+
maxBitsPerBlock: this.maxBitsPerBlock
267271
})
268272
this.sections[y] = section
269273
}

src/pc/1.16/ChunkColumn.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const ChunkSection = require('../common/CommonChunkSection')(BitArray)
44
const CommonChunkColumn = require('../common/CommonChunkColumn')
55
const constants = require('../common/constants')
66
const varInt = require('../common/varInt')
7+
const neededBits = require('../common/neededBits')
78

89
// wrap with func to provide version specific Block
910
module.exports = (Block, mcData) => {
@@ -18,6 +19,7 @@ module.exports = (Block, mcData) => {
1819
this.blockLightMask = 0
1920
this.skyLightSections = Array(constants.NUM_SECTIONS + 2).fill(null)
2021
this.blockLightSections = Array(constants.NUM_SECTIONS + 2).fill(null)
22+
this.maxBitsPerBlock = neededBits(Object.values(mcData.blocks).reduce((high, block) => Math.max(high, block.maxStateId), 0))
2123
}
2224

2325
toJson () {
@@ -144,7 +146,9 @@ module.exports = (Block, mcData) => {
144146
if (stateId === 0) {
145147
return
146148
}
147-
section = new ChunkSection()
149+
section = new ChunkSection({
150+
maxBitsPerBlock: this.maxBitsPerBlock
151+
})
148152
this.sectionMask |= 1 << sectionIndex
149153
this.sections[sectionIndex] = section
150154
}
@@ -254,16 +258,16 @@ module.exports = (Block, mcData) => {
254258
}
255259

256260
// number of items in data array
257-
varInt.read(reader) // numLongs
258261
const dataArray = new BitArray({
259-
bitsPerValue: bitsPerBlock,
262+
bitsPerValue: bitsPerBlock > constants.MAX_BITS_PER_BLOCK ? this.maxBitsPerBlock : bitsPerBlock,
260263
capacity: 4096
261-
}).readBuffer(reader)
264+
}).readBuffer(reader, varInt.read(reader) * 2)
262265

263266
const section = new ChunkSection({
264267
data: dataArray,
265268
palette,
266-
solidBlockCount
269+
solidBlockCount,
270+
maxBitsPerBlock: this.maxBitsPerBlock
267271
})
268272
this.sections[y] = section
269273
}

src/pc/1.17/ChunkColumn.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const ChunkSection = require('../common/CommonChunkSection')(BitArray)
44
const CommonChunkColumn = require('../common/CommonChunkColumn')
55
const constants = require('../common/constants')
66
const varInt = require('../common/varInt')
7+
const neededBits = require('../common/neededBits')
78

89
// wrap with func to provide version specific Block
910
module.exports = (Block, mcData) => {
@@ -14,6 +15,7 @@ module.exports = (Block, mcData) => {
1415
this.minY = options?.minY ?? 0
1516
this.worldHeight = options?.worldHeight ?? constants.CHUNK_HEIGHT
1617
this.numSections = this.worldHeight >> 4
18+
this.maxBitsPerBlock = neededBits(Object.values(mcData.blocks).reduce((high, block) => Math.max(high, block.maxStateId), 0))
1719

1820
this.sectionMask = new BitArray({
1921
bitsPerValue: 1,
@@ -181,7 +183,7 @@ module.exports = (Block, mcData) => {
181183
if (stateId === 0) {
182184
return
183185
}
184-
section = new ChunkSection()
186+
section = new ChunkSection({ maxBitsPerBlock: this.maxBitsPerBlock })
185187
if (sectionIndex > this.sectionMask.capacity) {
186188
this.sectionMask = this.sectionMask.resize(sectionIndex)
187189
}
@@ -296,16 +298,16 @@ module.exports = (Block, mcData) => {
296298
}
297299

298300
// number of items in data array
299-
varInt.read(reader) // numLongs
300301
const dataArray = new BitArray({
301-
bitsPerValue: bitsPerBlock,
302+
bitsPerValue: bitsPerBlock > constants.MAX_BITS_PER_BLOCK ? this.maxBitsPerBlock : bitsPerBlock,
302303
capacity: 4096
303-
}).readBuffer(reader)
304+
}).readBuffer(reader, varInt.read(reader) * 2)
304305

305306
this.sections[y] = new ChunkSection({
306307
data: dataArray,
307308
palette,
308-
solidBlockCount
309+
solidBlockCount,
310+
maxBitsPerBlock: this.maxBitsPerBlock
309311
})
310312
}
311313
}

src/pc/1.18/ChunkColumn.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const ChunkSection = require('../common/PaletteChunkSection')
44
const BiomeSection = require('../common/PaletteBiome')
55
const CommonChunkColumn = require('../common/CommonChunkColumn')
66
const constants = require('../common/constants')
7+
const neededBits = require('../common/neededBits')
78

89
// wrap with func to provide version specific Block
910
module.exports = (Block, mcData) => {
@@ -14,9 +15,11 @@ module.exports = (Block, mcData) => {
1415
this.minY = options?.minY ?? 0
1516
this.worldHeight = options?.worldHeight ?? constants.CHUNK_HEIGHT
1617
this.numSections = this.worldHeight >> 4
18+
this.maxBitsPerBlock = neededBits(Object.values(mcData.blocks).reduce((high, block) => Math.max(high, block.maxStateId), 0))
19+
this.maxBitsPerBiome = neededBits(Object.values(mcData.biomes).length)
1720

1821
this.sections = options?.sections ?? Array.from(
19-
{ length: this.numSections }, _ => new ChunkSection()
22+
{ length: this.numSections }, _ => new ChunkSection({ maxBitsPerBlock: this.maxBitsPerBlock })
2023
)
2124
this.biomes = options?.biomes ?? Array.from(
2225
{ length: this.numSections }, _ => new BiomeSection()
@@ -243,8 +246,8 @@ module.exports = (Block, mcData) => {
243246
load (data) {
244247
const reader = SmartBuffer.fromBuffer(data)
245248
for (let i = 0; i < this.numSections; ++i) {
246-
this.sections[i] = ChunkSection.read(reader)
247-
this.biomes[i] = BiomeSection.read(reader)
249+
this.sections[i] = ChunkSection.read(reader, this.maxBitsPerBlock)
250+
this.biomes[i] = BiomeSection.read(reader, this.maxBitsPerBiome)
248251
}
249252
}
250253

src/pc/1.9/ChunkColumn.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const constants = require('../common/constants')
44
const BitArray = require('../common/BitArray')
55
const varInt = require('../common/varInt')
66
const CommonChunkColumn = require('../common/CommonChunkColumn')
7+
const neededBits = require('../common/neededBits')
78

89
const exists = val => val !== undefined
910

@@ -19,6 +20,7 @@ module.exports = (Block, mcData) => {
1920
this.biomes = Array(
2021
constants.SECTION_WIDTH * constants.SECTION_WIDTH
2122
).fill(1)
23+
this.maxBitsPerBlock = neededBits(Object.values(mcData.blocks).reduce((high, block) => Math.max(high, block.maxStateId), 0))
2224
}
2325

2426
toJson () {
@@ -123,7 +125,9 @@ module.exports = (Block, mcData) => {
123125
if (stateId === 0) {
124126
return
125127
}
126-
section = new ChunkSection()
128+
section = new ChunkSection({
129+
maxBitsPerBlock: this.maxBitsPerBlock
130+
})
127131
this.sectionMask |= 1 << sectionIndex
128132
this.sections[sectionIndex] = section
129133
}
@@ -221,11 +225,10 @@ module.exports = (Block, mcData) => {
221225
}
222226

223227
// number of items in data array
224-
const numLongs = varInt.read(reader)
225228
const dataArray = new BitArray({
226-
bitsPerValue: Math.ceil((numLongs * 64) / 4096),
229+
bitsPerValue: bitsPerBlock > constants.MAX_BITS_PER_BLOCK ? this.maxBitsPerBlock : bitsPerBlock,
227230
capacity: 4096
228-
}).readBuffer(reader)
231+
}).readBuffer(reader, varInt.read(reader) * 2)
229232

230233
const blockLight = new BitArray({
231234
bitsPerValue: 4,
@@ -243,7 +246,8 @@ module.exports = (Block, mcData) => {
243246
data: dataArray,
244247
palette,
245248
blockLight,
246-
...(skyLightSent ? { skyLight } : { skyLight: null })
249+
...(skyLightSent ? { skyLight } : { skyLight: null }),
250+
maxBitsPerBlock: this.maxBitsPerBlock
247251
})
248252
this.sections[y] = section
249253
}

src/pc/1.9/ChunkSection.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class ChunkSection {
5656
this.blockLight = options.blockLight
5757
this.skyLight = options.skyLight
5858
this.solidBlockCount = options.solidBlockCount
59+
this.maxBitsPerBlock = options.maxBitsPerBlock || GLOBAL_BITS_PER_BLOCK
5960
}
6061

6162
toJson () {
@@ -117,7 +118,7 @@ class ChunkSection {
117118
} else {
118119
// switches to the global palette
119120
const newData = new BitArray({
120-
bitsPerValue: GLOBAL_BITS_PER_BLOCK,
121+
bitsPerValue: this.maxBitsPerBlock,
121122
capacity: constants.BLOCK_SECTION_VOLUME
122123
})
123124
for (let i = 0; i < constants.BLOCK_SECTION_VOLUME; i++) {
@@ -181,10 +182,8 @@ class ChunkSection {
181182
varInt.write(smartBuffer, 0)
182183
}
183184

184-
// write the number of longs to be written
185-
varInt.write(smartBuffer, this.data.length())
186-
187185
// write block data
186+
varInt.write(smartBuffer, this.data.length())
188187
this.data.writeBuffer(smartBuffer)
189188

190189
// write block light data

0 commit comments

Comments
 (0)