Fractal Block World
Version 1.02.00
Back
The engine has been expanded to include
"Icarus mode".
Updates
Version 1.02.01:
- Date: Not released yet
- It used to be that the depth buffer was cleared after
rendering each level.
Now the depth buffer is cleared after rendering 2 levels.
This implies that the viewer level L
as well as level L-1 are rendered together without clearing the depth buffer
in between them.
This decreases the number of depth buffer related render glitches.
You can specify how many levels are rendered before the depth buffer
is cleared by setting the variable
engine.render.depth_buffer.num_levels.
However, setting to anything higher than 2 causes Z-fighting
(because the game uses a 24 bit depth buffer).
You can try to change over to a 32 bit depth buffer
by setting the variable display.depth_buffer.num_bits to 32
(but on many computers, including the developer's computer,
a 32 bit depth buffer is not supported and the game will exit
on startup).
- It is now possible to create a mod that has a skybox.
See the skybox guide.
The key is that before every level is rendered, the function
p.__render_before_level is called.
It is passed the level that is being rendered (which is an integer)
as well as a bool which specifies whether the depth buffer was just cleared.
- In addition to the
p.__render_before_level function there is still the
p.__render_augmented function.
This function is now called at every level,
not just the viewer level (and the level is passed as an integer argument
to the function).
The p.__render_augmented function is called just before the alpha
component of the level is rendered.
- Env rects work differently now.
Before, we would intersect the bounding box of the player with
env rects once per frame.
Now, when we move the player during every discrete update
(which happens 25 times per second), we see if the path of the
player's camera crosses any env rect.
As a result, it should basically be impossible to move the player
0.1 block lengths or more through an env rect without triggering it.
For speed, we do not consider a block position (on any level) more than
once during a discrete update.
However, it is possible to trigger an env rect more than once per frame
if that involves multiple block positions inside the env rect.
- There is now a way to use blocks in place of env rects.
If a block script has the function
p.__on_viewer_lp_inside(level, bp),
then this will be called whenever the viewer's level position
(the camera position) is inside the block.
This will be called at most once per discrete update for any given block.
If the player tries to move through the block, the function will be called.
This function is recursive, in that it will be called even if the block
is on a coarser level than the viewer level.
- Now when the engine loads a game, it clears ALL keys (input events).
Before, it only cleared keys which the engines thought were down.
Note that saved games do not store which keys are down,
but a package might have a global bool var like "moving forward"
which is saved (which is why we need to clear ALL keys when loading a game).
- Here is something for advanced modding.
If a mod has a game Lua script with a function called
p.__get_should_interrupt_save,
this function will be called when a save is requested.
If that function returns false, then the save will be
halted.
Nothing will be saved
(hence no chunk files will be written
to the chunk file database).
- Recall that every block is actually a "stack of frames".
When you change the type of a block, you are actually pushing a new frame
on top of the block stack for that block position.
Prior to this update, block variables generated from worldgen
were stored in frame zero.
This was wrong, because frame zero can "revert" after a certain amount of time.
In this update, we store block variables from worldgen
in an appropriate place.
We store them as part of the chunk but not part of block stacks.
We can say that they are stored in "negative one frames".
These negative one frames are read only and are NOT saved when
the game is saved.
- Made the update cycle of moving entities slightly faster
by adding
built-in moving entity variable callback functions.
Let us explain with an example.
There is a moving entity engine variable
called
__tex_typical, and each frame it needs
to be recomputed from the variables __mesh
and __tex_override.
Originally, this computation happened in the moving entity rendering code
(each frame).
In a later version of the engine, we instead recalculated __tex_typical
in the update phase
(which happens 25 time per second, even if the entity was not rendered).
Now, we use the optimal method: we recalculate
__tex_typical immediately when either
of the variables __mesh or __tex_override change.
This new method is faster, but is more complicated.
- Now when a moving entity fully turns towards the player,
it will wait one second before turning again (to make the code faster).
- Now when a child chunk is added or removed from a chunk,
certain "dirty bits" are set.
This improves the speed of the particle system update code as well as the moving entity
movement code (in the trivial case).
- In general, the moving entity update code is faster
(but more complicated).
- There are now only half as many rats in the Mylantis caves
(but there is still a huge number of them).
Version 1.02.00:
- Date: July 2026
- Added a
truly amazing secret area
which required rewriting core parts of the engine!
The community can have fun searching for and exploring this area.
- Now certain "infertile" chunks are not created at all.
This is an example of "pruning the chunk tree".
For example, consider the block type
XAR_YING_FOREST_AIR.
This consists of a single gray block in the middle,
with sometimes a grower, a shrinker, or a goblin.
Now this block type has been set to
"prune when infertile" (PWI).
When a XAR_YING_FOREST_AIR chunk exists and is fertile,
it looks normal.
However, as soon as the chunk becomes infertile,
the chunk is removed.
If we had not set it to be PWI,
then when it is infertile it would just have its single
block in the middle but no growers, shrinkers, or goblins.
We would like to thank the user enzo for suggesting
a change like this.
One might even want to remove certain fertile chunks,
but there is a problem with doing this in general.
For example, we shouldn't be allowed to remove chunks on level L
if they intersect the "envelope" of level L+1.
The envelope of level L+1 is the bounding box of that
level but extended in all directions by 2 chunks.
This new pruning feature required changing parts of the engine.
For example, there was an old rule that when a chunk C is
created, if an adjacent chunk does not exist, then we
do not create any external squares on that side of C.
We have had to modify that rule.
Also, the visray algorithm has been modified.
It is true that you can have solid blocks
be PWI, but this might result in rendering artifacts because
the depth buffer is cleared after rendering each level.
To see how to create Lua block scripts that are PWI,
see the file Data/Packages/base/WorldNodes/Nodes/block_e.lua
which is the standard Lua block script for an empty block.
- The way moving entities (ments) are rendered has changed.
Before, when it was time to render an ment, we would compute
a bunch of variables.
Now, we compute them every discrete update (which happens 25
times per second).
The downside of this new approach is we are computing vars
for ments which might not intersect the view frustum
over the next few frames. Such ments will not be rendered
(but we cannot tell in advance because we don't know if the player will
suddenly move their head).
In a future update, the plan is to NOT update these vars 25 times
per second but instead only update them when a relevant change
is made to the ment.
- Now there is a menu to turn on/off the in game
memory counter.
It can be found at Options -> Engine -> Debug -> Memory Counter.
Once set, the program must be restarted for it to take effect.
The total memory used by the program is displayed in the main menu
in the upper left.
There is also a side display to display total memory.
- In addition to the memory counter there is a new tool
for memory debugging: the memory mom.
Every smart pointer in this program has a string name
describing the object that is pointed to.
When the memory mom is enabled, if you run the command
debug_mom_dump, it will dump to
stdout.txt the names of
all these objects and how many there are of each type.
When this mode is enabled, it will slow down the game slightly.
The memory mom will also dump twice during program shutdown
(if it is enabled).
Once set to enabled, you must restart the program for it to work.
- The xar block overrides
system has been improved.
Now when you override a xar block with a Lua block,
the texture of the Lua block will replace
the texture of the xar block.
Also, the "is solid" parameters of the Lua block
will replace those of the xar block.
To make sure that this new system is not tedious,
there is a way to copy the basic parameters
of a xar block into a Lua block.
What you do in the Lua block script is define
a function
__get_bt_to_copy
and have it return something like
"XAR_SMALL_YELLOW_FLOWER".
Then, you do not need to define the
__get_is_solid
and __get_tex function of the Lua block
(but you can if you want).
If you have the __get_bt_to_copy
function, it is required to return a string that starts with
""XAR_".
- For advanced modding there is a new body mode called "custom".
You enable this by calling the function
ga_move_set_body_custom.
When this mode is enabled, the engine does not perform any collision
detection to the player whatsoever, but the world is still rendered.