Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
benhumphreys
Prole
Posts: 31
Joined: Thu Sep 13, 2012 2:10 am

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.

Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

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?

bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

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.

Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

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.

jonbro
Prole
Posts: 8
Joined: Tue Oct 02, 2012 10:18 am

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.

jonbro
Prole
Posts: 8
Joined: Tue Oct 02, 2012 10:18 am

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.
Attachments
filewatch.zip

benhumphreys
Prole
Posts: 31
Joined: Thu Sep 13, 2012 2:10 am

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.

klembot
Prole
Posts: 30
Joined: Tue Apr 24, 2012 12:41 am

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.

Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

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"
}

for _, lib in ipairs( libraries ) do
end
for _, lib in ipairs( libraries ) do
require(lib)
end
end

end


bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

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)