feel free to use the code however you like! I am hoping that my changes are in line with @destroyflyer 's plans and that he can use my changes, since I am sure I will continue to be developing this and would like my code to be easily available.
My guess concerning HashMaps vs native arrays, is that for worlds with relatively small data sets, and/or which require relatively infrequent modification/checking, the speed difference will be negligible, as you stated. As amount of data stored goes up, there are more items in a HashMap which potentially have to be traversed before finding the correct one, and the more times you call getter methods or modify the data (setting new blocks would be particularly costly I believe?), the more times those costly HashMap traversals have to occur.
The other thing to consider is “empty space” vs “block space”. With an array of natives, enough space to hold every single cell is immediately grabbed from the heap and saved for use. This is why you notice that distinct hang at the beginning of many of the test classes, and why it takes up such a large amount of RAM - even if the number of actual blocks is relatively low, the rectangular boundary around them (that is, all the chunks needed to store them) will be much larger, and you are storing space for empty blocks. With a HashMap, you only store data for the Vector3Ints which actually contain something.
For a volume which is entirely populated or close to it, a native array definitely makes sense. But the more empty space you have, the stronger an argument you have to use a HashMap. This is especially true for worlds which have “clusters” of blocks which are spread very far apart - storing all the space inbetween is extremely costly and a huge waste.
I wonder how storing a Java Byte would work though? They are classes, not natives. But if the JRE just creates an array of pointers (very likely) which start out leading to null, and are to be replaced, you’re no better off (actually worse off, since pointers are definitely going to larger then a byte). But maybe if the JRE were made such that it allocated the space dynamically…? I don’t know the technical details.
I think what could DEFINITELY stand to use a HashMap over an array is the main BlockVolume, which contains all the Chunks. In most use cases, you won’t be storing an extraordinary amount of chunks (and if you are, you should maybe consider decreasing it, and instead using larger chunks with smaller sub-chunks in another HashMap) and this means that you can initiate an absolutely massive volume with minimal memory cost, and then dynamically create/delete chunks as needed when blocks are added or removed.
Actually wouldn’t that entirely remove the need for volume borders, creating the grounds for an infinite terrain generator? :o You could then make an extension class with borders if you wanted.
There are a number of possible approaches to storing voxel data in the base level chunks, each with varied pros and cons, as I started to get into. Bitwise single-dimensional arrays are super fast, but still have that memory problem. I’m not even sure exactly how much faster they are then normal 3D arrays. It’s easy to implement in any case. Having said all that, I think playing around with chunk size/storage, as I was describing above, is more interesting and fruitful, especially in these early stages.