Page 1 of 1

Reload Lua files on the fly.

PostPosted: Tue Jun 02, 2015 21:27
by BobbyBonsaimind
While thinking about how to better test my mapgen, I had the idea that it would be neat if I'd be able to reload parts of it on the fly, without the need to exit the subgame and restart it. There is no direct facility in Minetest that allows it, but we can work around it with a chatcommand and by encapsulating the important code in a function or object. Obviously you can't reload everything, as there are things that just need to be known when the mod starts, but other parts can be reloaded.

Let's have a look at the basics on how to accomplish this, assume this to be in the init.lua:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local base_path = minetest.get_modpath(minetest.get_current_modname())

minetest.register_chatcommand("reload", {
    description = "Reloads all we need.",
    params = "",
    func = function(name, params)
        dofile(base_path .. "/dynamic.lua")
        return true, "Done"
    end
})


And that's the basic framework, now you can run the command "reload" from within Minetest and "dynamic.lua" will be reloaded, you can make changes to "dynamic.lua" and simply reload it without having to exit Minetest.

You could also do that with a mapgen system, for example (note that the code assumes my utils mod to shorten it):

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local base_path = minetest.get_modpath(minetest.get_current_modname())
dofile(base_path .. "/mapgen.lua")

-- MapGen object is defined in mapgen.lua.
local mapgen = MapGen.create()

minetest.register_chatcommand("reload", {
    description = "Reloads all we need.",
    params = "",
    func = function(name, params)
        -- Reload the file.
        dofile(base_path .. "/mapgen.lua")
        -- Now we have the "new" MapGen object that we can use.
        mapgen = MapGen.create()
        return true, "Done"
    end
})

minetest.register_on_generated(function(minp, maxp, seed)
    local manipulator = MapManipulator:new()
   
    mapgen:run(minp, maxp, manipulator)
   
    manipulator:set_data()
end)


Now you can make changes to the system, type "reload" in Minetest and the next piece of the world is generated the new, reloaded system will be used.

Re: Reload Lua files on the fly.

PostPosted: Wed Jun 03, 2015 00:01
by prestidigitator
Right. Reloading the code isn't the problem. Dealing with the effects of the old code is what can screw things up. Any code module that gets reloaded needs to be carefully structured to take care of side effects. If it registers objects or callbacks, can they be replaced, or overridden somehow? Will old objects and functions still be referenced, essentially creating memory leaks and unexpected behavior? Those are the difficult sort of questions to answer, not whether or not dofile() can be called again. They make the "can" and "should" question very specific to the particular context in a mod.

Re: Reload Lua files on the fly.

PostPosted: Wed Jun 03, 2015 06:59
by rubenwardy
It will work perfectly fine if the dynamic file only declared functions. The main init file could then register these in a callback through wrapping.

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
mt.register_on_callback(function(one, two)
    dynamic.on_callback(one, two)
end)


I came up with a practically identical idea last year, but I've never used it other than in dev tch demos.

Of course you'd have to restart minetest if you want to add new call backs, unless you make a mechanism for it.

Re: Reload Lua files on the fly.

PostPosted: Mon Jun 08, 2015 03:12
by Sokomine
Dynamicly changing the code while working on a mapgen sounds like a very good idea. I just wonder how practical it actually is. There'd still be the need to fly into new terrain in order to get it generated. Or is there a way to get the current chunk beeing regenerated anew, without restarting the game?

Re: Reload Lua files on the fly.

PostPosted: Mon Jun 08, 2015 19:55
by BobbyBonsaimind
@Sokomine If it is probably encapsulated you'd only need to call it again for already existing blocks, either invoked by moving into it or when being invoked by a command. But no, I don't think that there is an automatic way.

Re: Reload Lua files on the fly.

PostPosted: Tue Jun 09, 2015 07:57
by rubenwardy
You can use minetest.delete_block or whatever to delete mapblocks. They should then be remade in a few seconds. Also see /delete_block

Re: Reload Lua files on the fly.

PostPosted: Tue Jun 09, 2015 17:09
by BobbyBonsaimind
@rubenwardy I guess you mean "delete_area"? If yes, I have to try that, that sounds intriguing.

And it works, obviously. Pretty neat.

Re: Reload Lua files on the fly.

PostPosted: Sat Dec 17, 2016 17:54
by Nyarg
More fun - prevent interrupt load script if error present on run.
Hmm but runtime errors still crash game.

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local callResult, result = pcall(dofile, modPath .. "/dynamic_test.lua")
if callResult then
    print(" \n\n---------------- SUCCESS dynLoad   ---- ")   
else
    print("\n\n ---------------- ERR dynLoad   ---- \n"..result)
    chatSend("\n\n ---------------- ERR dynLoad   ---- \n"..result)
end