The Block.blocksList array is created with 256 elements. The problem is that block IDs are stored in a signed byte array, so when values are popped several arrays try to be accessed with a negative index if you stored a block ID > 127. You can overcome this limitation quite easily with a few fixes here and there and use the full 0-255 range and have up to 256 different blocks without needing more memory or creating incompatibilites with existing saves.
The trick is that you can easily convert signed byte values to unsigned ints ranging 0-255 using casting and a bitwise AND. Type casting a negative byte to an int extends bit 7 (the sign). After that, a & 0xFF
will clear all bits but those in the least significant byte, so you get your 0-255 value back!
You have to change these bits of code:
In getBlockId
cast to int
and & 0xff
this way:
public int getBlockID(int x, int y, int z) {
return (int) this.blocks[x << 11 | z << 7 | y] & 0xff;
}
In setBlockIDWithMetadata
, the converted byte value (signed) is used to access Block.lightOpacity
. Change that to use the original ID:
public boolean setBlockIDWithMetadata(int x, int y, int z, int id, int metadata) {
[...]
if(Block.lightOpacity[id] != 0) {
[...]
Same for setBlockID
:
public boolean setBlockID(int x, int y, int z, int id) {
[...]
if(Block.lightOpacity[id] != 0) {
[...]
In generateHeightMap
the array is also read directly:
public void generateHeightMap() {
[...]
for(int i5 = i2 << 11 | i3 << 7; i4 > 0 && Block.lightOpacity[(int) this.blocks[i5 + i4 - 1] & 0xff] == 0; --i4) {
Also in relightBlock
:
private void relightBlock(int x, int y, int z) {
[...]
for(int i6 = x << 11 | z << 7; i5 > 0 && Block.lightOpacity[(int) this.blocks[i6 + i5 - 1] & 0xff] == 0; --i5) {
There's one instance where the chunk's block array is accessed directly which should be fixed as well: when ticking blocks.
protected void updateBlocksAndPlayCaveSounds() {
[...]
for(int i = 0; i < 80; ++i) {
[...]
blockID = (int) chunk.blocks[x << 11 | z << 7 | y] & 0xff;
And that seems to be it!