Hot reload plugin that actually works?

General discussion about LÖVE, Lua, game development, puns, and unicorns.
hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Re: Hot reload plugin that actually works?

Post by hasen »

pgimeno wrote: Sun Jan 28, 2018 10:20 am I think that hasen is talking about this plugin: https://marketplace.coronalabs.com/plug ... ive-coding
No it's built into the simulator, that's what I'm talking about.
pgimeno wrote: Sun Jan 28, 2018 10:20 am I don't run software I can't compile myself. It may be free as in beer, but not free as in freedom.
It's free for you to go ahead and test it if you didn't want to put barricades in front of yourself. Nobody is compelling you to write a game with it either, you can just test your theory with it should you want to.
pgimeno wrote: Sun Jan 28, 2018 10:20 am It can't find the other file. Make sure it is placed somewhere where Corona can find it.
Of course both module.lua and main.lua are in the same folder..
Last edited by hasen on Sun Jan 28, 2018 11:39 am, edited 2 times in total.
hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Re: Hot reload plugin that actually works?

Post by hasen »

Tjakka5 wrote: Sun Jan 28, 2018 10:07 am What Corona does is defined at 'Live Reloading'. Which can be pretty easy to setup with either Love or your Editor.
'Hot Reloading' on the other hand only reloads files that where changed, and maintains the state of the program, something that is difficult to achieve which has been explained earlier.
Well how exactly? That's what this whole thread is about. Lick certainly doesn't do the job well at all. How can we do exactly what Corona does but in Love2d? I'd honestly 'love' to know.
hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Re: Hot reload plugin that actually works?

Post by hasen »

I think everyone is confusing 'hot reload' with 'hot update'. Hot reload DOES have to reload the program each time, hence the word 'reload' in the name and the word 'reload' in the title of my thread. 'Hot update' is where I have a guy jumping on screen, I adjust the jump height and he starts jumping higher suddenly with no reload at all.

Hot reload is what the Corona simulator does as standard. That's the functionality I was after in Love2d.
User avatar
zorg
Party member
Posts: 3436
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Hot reload plugin that actually works?

Post by zorg »

Okay, so let's use simple terms; you want to restart the game without exiting it and manually starting it up again.
That is easy.

Code: Select all

function love.load(arg)
    -- Put all require statements and initial code here;
    -- file-local declaractions can go above, into the file scope, as long as you don't assign anything to them.
end

function love.keypressed(k,s)
    if s == 'escape' then
        love.event.quit('restart') -- Works since 0.10.2, recreates the whole lua state from scratch.
    end
end
While it does state in the wiki that the restart variant of love.event.quit shuts down the main lua state instance, there may be some other caveats;
- require's table where it stores already loaded libs is probably emptied, so this isn't an issue that needs to be handled separately
- if you use threads, those use their own lua states, maybe you need to clean up those yourself.
- Löve objects (i think) aren't tied to the lua state, they're on the C++ side, so they may survive this, so they may need to be cleaned up manually too.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Re: Hot reload plugin that actually works?

Post by hasen »

So your code will restart the game if I press escape? It's not really an auto reload like with Corona...? It should reload on changes to the code on any lua files in the project...or to be the same as Corona, any files in the project folder at all but I'd be satisfied with the former.
User avatar
zorg
Party member
Posts: 3436
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Hot reload plugin that actually works?

Post by zorg »

My mistake, this thread is still very confusing to be honest :P
Here, a better code:

Code: Select all

local sourceFiles = {}

function love.load(arg)

	-- Go over all "filesystem objects" löve can detect
	local files = love.filesystem.enumerate(dir)
	for k, file in ipairs(files) do
		-- if it's a file, and it's in the source directory / .love file itself...
		if love.filesystem.isFile(file) and love.filesystem.getRealDirectory(file) == love.filesystem.getSource() then
			-- put the file and its last modified date (restricted to 1 return value with the parentheses) in the file-local table.
			sourceFiles[file] = (love.filesystem.getLastModified(file))
		end
	end

    -- Put all require statements and initial code here;
    -- file-local declaractions can go above, into the file scope, as long as you don't assign anything to them.
end

function love.update(dt)

	-- Go over all "filesystem objects" löve can detect
	local files = love.filesystem.enumerate(dir)
	for k, file in ipairs(files) do
		-- if it's a file, and it's in the source directory / .love file itself...
		if love.filesystem.isFile(file) and love.filesystem.getRealDirectory(file) == love.filesystem.getSource() then
			-- if the file was catalouged, and it has been modified after, restart the whole program.
			if sourceFiles[file] and (love.filesystem.getLastModified(file)) > sourceFiles[file] then
				love.event.quit('restart')
			end
		end
	end

end
Does things automatically, although this still has a few issues;
- it doesn't check for files you might add in later,
- it runs the check each frame, which is overkill; once every second would be sufficient. It can be made to do that, but certainly not with love.timer.sleep
- haven't tested it, so expect it to not work. :3
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Re: Hot reload plugin that actually works?

Post by hasen »

zorg wrote: Sun Jan 28, 2018 1:39 pm Does things automatically, although this still has a few issues;
- it doesn't check for files you might add in later,
- it runs the check each frame, which is overkill; once every second would be sufficient. It can be made to do that, but certainly not with love.timer.sleep
- haven't tested it, so expect it to not work. :3
It's checking every frame? Shouldn't it only check when saving a file? Not sure exactly how the one in Corona works...do you assume it's doing the same thing then?
nander
Prole
Posts: 1
Joined: Sun Jan 28, 2018 3:06 pm

Re: Hot reload plugin that actually works?

Post by nander »

Hot reloading is basically impossible if you want to maintain state*.

The problem is, your data may have been put in a state that doesn't fit your new code as well.
If you only want to be able reload when the data-model doesn't change, then an Entity Component System can help you out. You would need to reload the Systems in that case, while keeping the Entities and Components loaded. I have had experimental code for this, but it broke once Systems needed to keep track of their own (derivative) state.
User avatar
zorg
Party member
Posts: 3436
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Hot reload plugin that actually works?

Post by zorg »

I don't give a squat about how corona does it, to be completely honest. You did explain it clearer in one of the later post of yours:
hasen wrote:I think everyone is confusing 'hot reload' with 'hot update'. Hot reload DOES have to reload the program each time, hence the word 'reload' in the name and the word 'reload' in the title of my thread. 'Hot update' is where I have a guy jumping on screen, I adjust the jump height and he starts jumping higher suddenly with no reload at all.

Hot reload is what the Corona simulator does as standard. That's the functionality I was after in Love2d.
Despite the fact that words can have tons of meanings and terminology like this isn't standardized across everything, i have decided to use "game restart" and "hotswapping" to refer to the two separate things (the latter not making the distinction between code and asset reloading)

The project needs to check in regular time intervals, otherwise, how would löve know that a file has changed? The code i posted is responsible for that. Your text editor or IDE or whatever won't notify another program that you modified a file.

That said, here's the modified code that only checks every 1/4th of a second and adds newly added files to the sourceFiles table.

Code: Select all

local sourceFiles
local fileCheckDelay
local timer

function love.load(arg)

	fileCheckDelay = 0.25 -- 1/4
	timer = 0.0

	sourceFiles = {}

	-- Go over all "filesystem objects" löve can detect
	local files = love.filesystem.enumerate(dir)
	for k, file in ipairs(files) do
		-- if it's a file, and it's in the source directory / .love file itself...
		if love.filesystem.isFile(file) and love.filesystem.getRealDirectory(file) == love.filesystem.getSource() then
			-- put the file and its last modified date (restricted to 1 return value with the parentheses) in the file-local table.
			sourceFiles[file] = (love.filesystem.getLastModified(file))
		end
	end

    -- Put all require statements and initial code here;
    -- file-local declaractions can go above, into the file scope, as long as you don't assign anything to them.
end

function love.update(dt)

	timer = timer + dt
	if timer > fileCheckDelay then

		-- Go over all "filesystem objects" löve can detect
		local files = love.filesystem.enumerate(dir)
		for k, file in ipairs(files) do
			-- if it's a file, and it's in the source directory / .love file itself...
			if love.filesystem.isFile(file) and love.filesystem.getRealDirectory(file) == love.filesystem.getSource() then
				-- if the file was catalouged, and it has been modified after, restart the whole program.
				if sourceFiles[file] then
					if (love.filesystem.getLastModified(file)) > sourceFiles[file] then
						love.event.quit('restart')
					end
				else
					-- add it to the list
					sourceFiles[file] = (love.filesystem.getLastModified(file))
				end
			end
		end
		timer = timer - fileCheckDelay
	end
end
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Hot *restart* plugin that actually works? Feasible.

Post by pgimeno »

hasen wrote: Sun Jan 28, 2018 11:36 am I think everyone is confusing 'hot reload' with 'hot update'. Hot reload DOES have to reload the program each time, hence the word 'reload' in the name and the word 'reload' in the title of my thread. 'Hot update' is where I have a guy jumping on screen, I adjust the jump height and he starts jumping higher suddenly with no reload at all.

Hot reload is what the Corona simulator does as standard. That's the functionality I was after in Love2d.
I call that "hot restart". "Reload" to me applies to individual files, as in, when you modify a file, it is reloaded into the running program. Everyone else has understood it that way. "Restart" implies your application starts again from the beginning.

Hot restart is of course simple to get right for many workflows, starting in 0.10.2 as zorg mentioned.

AFAIK the libraries you mentioned upthread, lick and lovedebug, are aimed at hot swapping (using zorg's terms) or hot update (using your terms). They are not aimed at hot restarting.

I'm wondering if it's possible to call love.event.quit("restart") from a thread. The docs don't mention this, but I don't see why not. So, you could have a dedicated thread monitoring your filesystem. Perhaps even interfacing to a file modification monitor library via FFI if available.

The only problem I see with this way of restarting is that while hot restarting, you should ensure that your program returns false in the love.quit() event if you define it. That's where it may interfere with some workflows and require manual intervention. Maybe Löve could incorporate love.event.quit("forcerestart") to ignore the result of love.quit(), but I'm not sure that's wise. It would be best if Löve was also changed to make love.quit() receive a force parameter that is true if it will ignore the return value and quit straight away.
Post Reply

Who is online

Users browsing this forum: No registered users and 56 guests