Block: XOR state data with type ID, improve hash distribution

since most blocks have no state data, their lower 8 bits of state data were all zero.
This makes state IDs a bit more distributed for minimal cost.

I considered flipping these around and using type ID in the lower bits directly, but this worsened distribution for walls.

In the worst case, largest number of collisions drops from 11 to 5 with this change, and the number of states with unique hash keys increased from 3518 to 4461 (out of 7638). This is still a long way from perfect, but it's a decent improvement, improving the overall load factor from 1.6 to 1.3.

related to #5604
This commit is contained in:
Dylan K. Taylor 2023-05-25 16:35:45 +01:00
parent 2ebf8757c1
commit ffe3556be1
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
2 changed files with 3 additions and 2 deletions

View File

@ -140,7 +140,8 @@ class Block{
* {@link RuntimeBlockStateRegistry::fromStateId()}.
*/
public function getStateId() : int{
return ($this->getTypeId() << self::INTERNAL_STATE_DATA_BITS) | $this->encodeFullState();
$typeId = $this->getTypeId();
return ($typeId << self::INTERNAL_STATE_DATA_BITS) | ($this->encodeFullState() ^ ($typeId & self::INTERNAL_STATE_DATA_MASK));
}
/**

View File

@ -123,7 +123,7 @@ class RuntimeBlockStateRegistry{
$block = clone $this->fullList[$stateId];
}else{
$typeId = $stateId >> Block::INTERNAL_STATE_DATA_BITS;
$stateData = $stateId & Block::INTERNAL_STATE_DATA_MASK;
$stateData = ($stateId ^ $typeId) & Block::INTERNAL_STATE_DATA_MASK;
$block = new UnknownBlock(new BID($typeId), new BlockTypeInfo(BreakInfo::instant()), $stateData);
}