minetest
minetest copied to clipboard
Generalized "on map change" callback
Problem
It's nigh impossible to easily be notified of any map change, e.g. to keep track of active blocks of some kind on your own or to implement "replay" mods.
Solutions
Provide a callback that triggers whenever a node changes. Provide a bulk variant for mapblocks / chunks / the like for larger updates (e.g. voxelmanip). The engine should already be keeping track of most of this in order to know when to resend mapblocks.
Alternatives
Keep requiring modders to:
- Override all map-modifying funcs the Lua API provides;
- Register LBMs;
- Register callbacks for player actions (on_placenode and on_dignode);
- Register liquid flow callbacks;
- Register an unreliable ABM to catch whatever you missed
(not exhaustive and probably misses some things)
How about a callback that receives the set of positions of mapblocks that changed every server step? It wouldn't be node-level precision, but I bet it would be easy and cheap to implement. It would give some false positives, but no false negatives. It could be used to implement things similar to Minecraft's "observers".
The only change notifications the engine could currently guarantee is entire mapblocks when they're changed where "changed" can also mean that the timestamp or node times increased (not necessary a node change).
I have a prototype that adds a new MapEventReceiver that's implemented basically like this:
struct OnMapblocksChangedReceiver : public MapEventReceiver {
std::unordered_set<v3s16> modified_blocks; // Cleared periodically.
void onMapEditEvent(const MapEditEvent &event) override {
for (const v3s16 &p : event.modified_blocks) {
modified_blocks.insert(p);
}
}
};