feather
feather copied to clipboard
Block state ids greater than 256 are converted to 256 in chunk sections that use the global palette
Description
If a chunk section has just switched to use the global palette and an additional block with block-state id > 256 is added, it will instead be registered as the block state with id 256 (BlockId { kind: NoteBlock, state: 6 }
)
Reproduction Steps
Run the following test in base/src/chunk.rs
#[test]
fn fill_chunk_section_with_unique_states() {
let mut section = ChunkSection::default();
//maximum amount of blocks before the global palette is used
let max_block_states = (1 << MAX_BITS_PER_BLOCK) - 1;
//place unique block states
for i in 0..max_block_states {
section.set_block_at(0, 0, 0, BlockId::from_vanilla_id(i + 1)).unwrap()
}
//the chunk section should still use a local palette.
assert!(section.blocks.palette().is_some());
//the next block should cause this chunk to use the global palette
let highest_block_state = BlockId::from_vanilla_id(257);
section.set_block_at(0,0,0, highest_block_state);
assert_eq!(section.block_at(0, 0,0).unwrap(), highest_block_state);
}
Output:
Left: BlockId { kind: NoteBlock, state: 6 }
Right: BlockId { kind: NoteBlock, state: 9 }
The reason for this is that when the chunk section switches to the global palette, it still returns the old index: https://github.com/feather-rs/feather/blob/6f9e96f9805368006dae31429edec17f1ae0a617/feather/base/src/chunk/blocks.rs#L132-L134
An easy fix would be:
let index = p.index_or_insert(block);
self.resize_if_needed();
if self.palette.is_none() {
block.vanilla_id() as usize
} else {
index
}
It would probably be good, if the palette returned a slice instead of an index, because then the compiler would have caught this error, but I don't have enough experience with rust to say whether this is really a better approach.