Page 1 of 1

Print to server console only

Posted: Fri Jun 11, 2021 5:15 am
by Northsoft
Hello, is there any way to print some message to server console only?
I understand that there is game.write_file which I already use, but I'd like to have a way to see messages immediately, without using period-based tools like watch.

Re: Print to server console only

Posted: Fri Jun 11, 2021 6:27 am
by Pi-C
Northsoft wrote: Fri Jun 11, 2021 5:15 am I understand that there is game.write_file which I already use, but I'd like to have a way to see messages immediately, without using period-based tools like watch.
Wouldn't "tail -f" do what you need?
-f, --follow[={name|descriptor}]
output appended data as the file grows;

an absent option argument means 'descriptor'

-F same as --follow=name --retry

--retry
keep trying to open a file if it is inaccessible
The -F is useful for log files that get rotated away.

Re: Print to server console only

Posted: Fri Jun 11, 2021 9:27 am
by Bilka
Plain print() should do the job.
https://lua-api.factorio.com/latest/Libraries.html wrote:print()

print() outputs to the stdout. For Factorio, this means that it does not end up in the log file, so it can only be read when starting Factorio from the command line.

Re: Print to server console only

Posted: Fri Jun 11, 2021 9:44 am
by Northsoft
Pi-C wrote: Fri Jun 11, 2021 6:27 amWouldn't "tail -f" do what you need?
`Tail -f`, and `watch` work in another console. Also, they don't work on Windows (yes, I am that crazy man who hosts Factorio server on dualboot system). That's why I ask a way to output something to server console.
Bilka wrote: Fri Jun 11, 2021 9:27 amPlain print() should do the job.
I know that `print` gives output to every user connected. I'd like to do not show players some intermediate information from scripts.

Re: Print to server console only

Posted: Fri Jun 11, 2021 9:46 am
by Bilka
Northsoft wrote: Fri Jun 11, 2021 9:44 am I know that `print` gives output to every user connected. I'd like to do not show players some intermediate information from scripts.
The majority of users do not open the game open via the command line, so they will never see stdout.

Re: Print to server console only

Posted: Fri Jun 11, 2021 6:46 pm
by quyxkh
Northsoft wrote: Fri Jun 11, 2021 9:44 am I know that `print` gives output to every user connected. I'd like to do not show players some intermediate information from scripts.
Here's the thing: you can use the native lua `print` from just *one* instance without risking a desync, because stdout is not part of the game state. Local mod state that never affects the game state is perfectly fine, in fact your entire mod state is local, it's what you're (usually) trying to keep in sync with all other instances' states so all their effects on the game state stay in sync.

Best I've been able to tell, there's five locally-discernible situations: setup (which ends when on_load completes or on_init starts), limbo(when ends when any game event other than on_load fires), server, singleplayer, multiplayer.

But the only way I've found to tell whether a multiplayer instance is the first client or the server is if the server chats before any players are connected:

Code: Select all

script.on_event(defines.events.on_console_chat,function(ev)
    if #game.connected_players == 0 then mystate='server'
    end end)
and you must never feed that variable's value to any game function (or almost any, but you're trying to avoid write_to_file here right?). `print` is a native lua function that doesn't call in to the game engine, Factorio doesn't see or care what values it gets or what it does with them.

You could run your server with for instance `(echo hi this is Northsoft\'s server starting up; cat) | ./bin/x64/factorio` etc, then your mod would see the console chat regardless of whether the game ticks with no players connected, and so you can then have

Code: Select all

function serverprint(text) if mystate=='server' then print (type(text)=='string' and text or serpent.line(text)) end
and from anywhere in your mod you can `serverprint 'Kilroy is here!'`, it will only appear on the server console output because no other lua instance will have that `mystate` value.

fair warning: I have smoketested this, implemented it just now on a local server, but it hasn't been tested in the wild.

Re: Print to server console only

Posted: Sat Jun 12, 2021 6:56 am
by Northsoft
quyxkh wrote: Fri Jun 11, 2021 6:46 pm

Code: Select all

script.on_event(defines.events.on_console_chat,function(ev)
    if #game.connected_players == 0 then mystate='server'
    end end)

Code: Select all

function serverprint(text) if mystate=='server' then print (type(text)=='string' and text or serpent.line(text)) end
Looks like a duck tape, but as I can understand, this is the only way. Well, looks like the best way to do this is to use `game.write_file`. Thanks for your solution, I will keep it in mind.

Re: Print to server console only

Posted: Wed Jun 16, 2021 12:58 pm
by eradicator
quyxkh wrote: Fri Jun 11, 2021 6:46 pm But the only way I've found to tell whether a multiplayer instance is the first client or the server is if the server chats before any players are connected:
I've actually written a request for is_headless_server.

Depending on how LuaPlayer.connected behaves during on_load on a players machine, it might be possible to guess this without manually triggering events by storing references to each player in global savedata. This would only work if a player is treated as "connected" while still running their own on_load.