Page 1 of 2

Dynamically Reloading Lua Files

Posted: Wed Oct 03, 2012 2:31 pm
by benhumphreys
I read this post by the Legend of Grimrock guys on dynamically loading Lua to speed up their code, build, test iteration cycle.

It got me thinking, if this is possible within a C++ environment that runs Lua, is it possible in a Lua-only environment like a Löve game?
Ideally it'd be great to be able to change some entity definitions in my game, and then have my code re-load that on the fly.

Has anyone tried this already?

Re: Dynamically Reloading Lua Files

Posted: Wed Oct 03, 2012 3:09 pm
by Robin
Yeah, I think people have tried it, though I can't remember specific examples.

You can do it pretty easily if you design your data structures right. Then you can reload your game on the fly without crashing or resetting the game.

... someone with actual experience with this care to comment? :P

Re: Dynamically Reloading Lua Files

Posted: Wed Oct 03, 2012 3:10 pm
by bartbes
Yeah, there's been a couple of these things, like LICK.
Personally, I've used some bash scripts hooked up to inotify to restart love when a file is modified.

Re: Dynamically Reloading Lua Files

Posted: Wed Oct 03, 2012 3:27 pm
by Robin
bartbes wrote:Personally, I've used some bash scripts hooked up to inotify to restart love when a file is modified.
That's simple and doesn't require any changes to the game itself, nice.

Those don't preserve state, though. If you can manage that, it'll be epic. Can we intercept signals? If so, your bash script could send a signal and the game would intercept that and store the state in the savedir.

Re: Dynamically Reloading Lua Files

Posted: Wed Oct 03, 2012 6:29 pm
by jonbro
I am not doing this in love2d, but in my other lua project, I use sockets to send the data over the network and then execute. I have some code that runs on the command line looking for file changes.

It lets me preserve state, which is nice.

Re: Dynamically Reloading Lua Files

Posted: Wed Oct 03, 2012 8:03 pm
by jonbro
Hey (sorry for the double posting), but I just went ahead and wrote a pure lua thing that watches the file system and loads in lua files that change. It preserves state, so you can just go along editing things.

just use it like this:

Code: Select all

local fw = love.filesystem.load("fileWatch.lua")()
fw:start()
function love.update(dt)
	fw:update()
end
I don't think that it works on windows (I am unsure on how to do directory separators in a crossplatform way), and it dumps out errors to the console that opened it, rather than blue screening.

Hope that someone finds this useful, let me know if there are any changes that you want.

Re: Dynamically Reloading Lua Files

Posted: Thu Oct 04, 2012 1:21 am
by benhumphreys
jonbro that looks super-useful! Thanks for posting it!

I'm wondering how I could build this into a larger system.
Calling require() again on a file that's already been require'd won't do anything?

I guess if the files you are watching and reloading are functions and class data, you could find the matching existing instance(s), and replace their properties to point to the modified functions and class data. You'd have to preserve instance data though...

Something like this:

Code: Select all

modifiedStuff -- our asynchronously loaded table
for _, entity in ipairs(entities) do
  foreach key, val in pairs(modifiedStuff) do
    entity[key] = val
  end
end
I'm not sure how to do this cleanly yet using MiddleClass. Hmm.

Re: Dynamically Reloading Lua Files

Posted: Thu Oct 04, 2012 4:22 am
by klembot
I have some code to do this in Zoetrope. The approach it takes is different and more basic. When it initially loads, it takes a snapshot of _G (the table where all globals live) and packages.loaded (which tracks what's already been loaded). To reload, it resets _G and packages.loaded to their previous values and restarts things by requiring main.lua, then calling love.load().

The code that takes the snapshot is here, and here is how I do the reloading.

Re: Dynamically Reloading Lua Files

Posted: Thu Oct 04, 2012 5:00 am
by Inny
I've taken on a pattern (I think kikito may have suggested it, but I could be wrong) where I do the primary list of library loading out of love.load, which makes sure to clear out package.loaded. Then I rig a quick reset button (like F9) to the love.load call. Here's some sample code:

Code: Select all

libraries = {
  "class", "graphics", "color", "input", "util", "statemachine"
}

function loadLibraries()
  for _, lib in ipairs( libraries ) do
    package.loaded[lib] = nil
  end
  for _, lib in ipairs( libraries ) do
    require(lib)
  end
end

function love.load()
  loadLibraries()
end

Re: Dynamically Reloading Lua Files

Posted: Thu Oct 04, 2012 5:16 pm
by bartbes
benhumphreys wrote: Calling require() again on a file that's already been require'd won't do anything?
Correct, but the easy workaround is something like this:

Code: Select all

function rerequire(module)
    package.loaded[module] = nil
    return require(module)
end