owned this note
owned this note
Published
Linked with GitHub
# Falling Block - "Easy Method"
This Document provides an overview over the proposed "easy method".
The proposed setup is intended to be fully afkable,
so that we can hit the first race condition even with low chances.
## Naming convention
**Base Chunks (B):**
A certain number of chunks is expected to be always loaded.
This includes spawn chunks, as well as player loaded chunks.
In order to ensure the rest of the process is as reliable as possible,
this number of chunks has to be fixed.
**Cluster Chunks (C\):**
This is a set of chunks where as many chunks positions as
possible have the same or consecutive hashes.
The number of actually consecutive chunks is the variable
most likely modified for retiming.
**Glass Chunks (G):**
These are the chunks that are meant to be reloaded off-thread.
They are named like this because adding/removing glass blocks
is what starts the threads in these chunks.
**Rehash Chunk (R\):**
This chunk triggers the rehashing.
Ideally, this is only a single chunk.
## Process
First, a general overview:
1. **Autosave:** Unloads all but the base chunks
2. **Load cluster:** Load the cluster chunks
3. **Load glass:** Load the glass chunks
4. **Start Threads:** Push glass blocks in glass chunks
5. **Rehash:** Load the rehash chunk
6. **Reset:** Reset all redstone
### Autosave
Since this is intended to be fully automatic,
auto saving is the only way to unload chunks.
After this, the only loaded chunks are the base chunks.
The number of base chunks has to be chosen such that
the hash-map resizes to it's lower size, i.e. between
10% and 18% of it's full size.
### Load Cluster & Load Glass
After the autosave, the cluster and glass chunks are loaded.
The cluster chunks can be loaded in arbitrary order, but the
glass chunks should be loaded after as many cluster chunks as possible.
The number of base + cluster + glass chunks should be one
short of causing a rehash.
### Start Threads
Now that all but one chunk are loaded, the glass threads are started.
Inside the glass chunks, pistons start pushing stained glass blocks.
We likely want as many glass blocks as possible,
as high up in the world as possible.
### Rehash
Immediately after all glass pistons start moving, the rehash chunk
is loaded, causing a rehash of the underlying hash-map.
If the entire process was successful,
at least one of the beacon threads will reload their own chunk and
an observer chain can relay asynchronous block-updates indefinitely.
Note that this observer-chain is unload protected.
This means that the rest of the system keep running without ruining
the success.
### Reset
After an (unsuccessful) attempt, all the restone in the system resets.
Glass blocks must be pushed back in their original positions and
redstone must be depowered.
## Chunk Layout
### Base Chunks
These can be any chunks that are ensured to stay loaded during the
described process.
Most likely, these are simple the spawn-chunks plus the player loaded
chunks.
I'd recommend to chunk load the area around the player so that they
don't acidentally load any more chunks.
### Cluster Chunks
This should be a local groups of chunks, where as many of these chunks
as possible share the lower bits of the hashed chunk position,
or are at least consecutive.
Note that the locality isn't strictly necessary, but likely makes
the loading process easier.
### Glass Chunks
This should be unpopulated chunks with the same hash
as the cluster chunk, or at least consecutive.
The goal here is to make the hashmap lookup of the glass chunks as
slow as possible. This can be achieved by inserting other chunks
with the same hash before them.
Note that the only requirement for these chunks is that they are
unpopulated. Therefore, it makes sense to simply search for a
convenient cluster and then pick the glass chunks from that.
Inside of these chunks will be a contraption that moves a lot of
stained glass blocks as well as an observer chain detecting the
generation of water fountains.
Note that these chunks will have to be protected against population.
### Rehash Chunk
This can be any chunk easily loadable via a signal.
### Numbers
Which exact numbers of chunks has to be loaded is uncertain,
but here are some possible scenarios and some arguments for
choosing our final layout.
| Base Size | Mask | Base Chunks | Cluster Chunks |
|---------- | ------ | ------------- | -------------- |
| 2048 | 11 bit | 27x27 | 26x31 |
| 4096 | 12 bit | 27x27 + 27x27 | 26x62 + 1 |
#### Base Size
The total size of the hashmap.
At 75% fullness the map rehashes, resizing upwards.
Below ~20% the map rehashes, resizing downwards.
This has to be a power of two, limiting our options a lot.
We probably don't want to go too big since we'll quickly have
to load an unreasonable amount of chunks.
8k or maybe 16k should be the limit.
Lower than 1024 is impossible due to spawn chunks,
with a player online lower than 2048 is impossible.
#### Mask
The bigger the base size, the bigger the mask.
A bigger mask means a bigger distance between valid cluster chunks.
However, a bigger mask also allows to load more chunks.
#### Base chunks
Needs to be als least 10% of the base size to prevent downsizing twice.
> Is that even true?
Can be at most ~18% (3/16) of the base size to ensure autosave resizes down.
#### Cluster Chunks
## Uncertain things
- Make sure Long2ObjectopenHashMap.get() doesn't crash if the mask changes
- It's fine cause the n+1-th entry in the keys is always 0
- Make sure Long2ObjectopenHashMap.get() returns null after resize
- If get() wraps around, it's fine
- If it doesn't, we need to make sure to not have an entry in the new
value array at the old key position
- All the timings