The explosion scan cloned a Location for every block and built five more per block to find attached neighbours, hashing each one on the region thread. It now keys the map by a packed long position and walks the neighbours from an offset table. The same blocks are logged.
Lookup.countLookupRows and LookupRaw.performLookupRaw closed their ResultSet as the last statement of the try, so any error while reading rows left it, and the statement behind it, open until the connection was returned. Both now close it on every path.
populatedChunks had no world in its key, so a chunk generated in one world suppressed water, lava and vine rows at the same chunk coordinates in every other world, and entries were only removed when a later fluid row happened to land there. It is now kept per world and swept after 240 seconds, the longest window BlockPlaceLogger checks.
A tamed animal whose owner has no known name is stored with a null owner, and restoring it throws a NullPointerException at the owner step, which drops the rest of the restore. A null owner name is now skipped like an empty one.
The consumer ran Material.matchMaterial's two regex passes on names they cannot change, and re-encoded the same blockdata strings into ids on every row. Plain enum names now go straight to getMaterial, and stringToByteData caches its results per string, bounded, reset when the id maps reload and skipped on ClickHouse.
The id allocators read the counter, add one and store it without a lock, so two threads that see new names at the same time (region threads on Folia, lookup and API threads everywhere) can give the same id to two different names. Allocation now holds the ConfigHandler monitor reloadAndGetId already uses, with a re-check, and queues the insert after releasing it.
Every dispense copied the dispenser's block entity twice on the region thread (block.getState() in the dispense listeners and inventory.getHolder() in onInventoryInteract), and both copies were only used for their type, location and live inventory. Paper can hand out non-snapshot states for this, so the dispense path now asks for those through a new PaperInterface.getBlockState(Block, boolean), falling back to a normal snapshot on Spigot.