[2.0.62] Wrong value in LuaPlayer:render_mode

Bugs that are actually features.
Hireama
Manual Inserter
Manual Inserter
Posts: 1
Joined: Fri Aug 01, 2025 8:13 pm
Contact:

[2.0.62] Wrong value in LuaPlayer:render_mode

Post by Hireama »

I noticed, that LuaPlayer:render_mode is not updated in the same tick as LuaPlayer:controller_type.
Based on my understanding of what those two values represent, I would consider this a bug.
Although it has no adverse effects on gameplay, it heavily disrupted my script layout (very biased, fell free to judge).
What happened?
The console output of the example mod. With values of every tick.
The console output of the example mod. With values of every tick.
tick prints.PNG (175.96 KiB) Viewed 159 times
 
The above screenshot should say enough already, but here are steps to get a first-hand experience:
  • Tested on versions: 2.0.60 / 2.0.62
  • Install and enable the mod provided in Attachments for a visual output of the problem (occurs with any or no mods installed).
  • Load any Freeplay Save / Create any new Freeplay Game (should occur in any gamemode).
  • In-game, press the M key, or use any other method, to switch in and out of the remote view.
  • Look at the console or factorio-current.log output (if the mod provided in Attachments was enabled).
  • Alternatively, observe any source-code behaviour in and around the raising of the on_player_controller_changed event, related to changes made to LuaPlayer:controller_type & LuaPlayer:render_mode.
  1. Up until tick [244] we are in the remote view and looking at the chart - the detailed game world is not visible.
  2. Tick [245]: The controller change happens here. From remote to character view.
  3. Tick [245]: LuaPlayer:controller_type is updated but LuaPlayer:render_mode stays in chart mode.
  4. Tick [245]: The on_player_controller_changed event is raised.
  5. Tick [246]: Only now LuaPlayer:render_mode is updated. From chart to game view. Probably by the same (internal) event.
  6. Only on tick [246] and beyond are both correct values available - as a result of a controller change.
This "update-lag" is also observed in other controller type changes, but for any practical purposes, the change to and from the remote controller has the most impact, as described in: Why is this important.
What did you expect to happen?
When accessing the values during the on_player_controller_changed event (tick [245] in the screenshot above),
I expected to get the following outputs:
Old:  LuaPlayer:controller_type == defines.controllers.remote
New: LuaPlayer:controller_type == defines.controllers.character
New: LuaPlayer:render_mode == defines.render_mode.game
Instead of:
Old:  LuaPlayer:controller_type == defines.controllers.remote
New: LuaPlayer:controller_type == defines.controllers.character
New: LuaPlayer:render_mode == defines.render_mode.chart

Since the player cannot look at the chart / chart_zoomed_in view when they are in the character controller, my assumption is, that LuaPlayer:controller_type dictates the value of LuaPlayer:render_mode.
That means, if I know the controller type, I know what render values to expect. One depends on the other.
Why is this important?
Factorio makes heavy use of events (at least for modding) and discourages the use of code that runs every / every other tick. LuaPlayer:render_mode has no events associated with it directly and relies on other events to figure out if a change has occurred. To my knowledge, the only event usable for that purpose is: on_player_controller_changed.
The problem is, the value is wrong.

To get the right value, one has to write an event handler for the n+1 tick after the controller changed and delete it afterwards. Or other shenanigans.
This is my anti-definition of readable code.
What did you do?
Here is the code that lead me to this discovery, as I was trying to calculate a view bounding area around the player.
Maybe you, dear bug report reader, know of a better way to achieve my goal here and can point me the right way:

Code: Select all

function bounding_area.calculate_player_view_bounding_area(player)
    if player.render_mode == defines.render_mode.chart then
        -- (0,0) is the chunk the player is occupying
        return vec2.new(0, 0)
    end

    local tiles_on_axis_x = player.display_resolution.width / (tile_size * player.zoom)
    local tiles_on_axis_y = player.display_resolution.height / (tile_size * player.zoom)

    local player_visible_chunks_x_half = math.ceil(tiles_on_axis_x / chunk_size / 2)
    local player_visible_chunks_y_half = math.ceil(tiles_on_axis_y / chunk_size / 2)

    return vec2.new(player_visible_chunks_x_half, player_visible_chunks_y_half)
end

function callbacks.update_player_view_bounding_area(event)
    local player         = game.get_player(event.player_index)
    local bounding_areas = player_storage.get_bounding_areas(event.player_index)

    if not player
    or not player.valid
    or not bounding_areas
    then return end

    local current_bounding_area = bounding_area.calculate_player_view_bounding_area(player)

    bounding_areas.old = bounding_areas.new
    bounding_areas.new = current_bounding_area

    debug.print("chunks visible on X axis: half: "..current_bounding_area.x)
    debug.print("chunks visible on Y axis: half: "..current_bounding_area.y)
    
    -- And here it would continue if it were finished...
end

-- event_manager is just a wrapper for script.on_whatever()
event_manager.on_event(
    {
        defines.events.on_player_controller_changed,
        defines.events.on_player_display_resolution_changed,
        custom_zoom_events.on_player_changed_zoom_level,    -- << Expect to read about this in a modding API suggestion :)
    },
    callbacks.update_player_view_bounding_area
)
My Recommendations
I don't know the source-code implementation, so these might be not easy or possible:
  1. Set the new LuaPlayer:render_mode value before on_player_controller_changed is raised.
  2. Add a new event: on_player_render_mode_changed, which will be raised after LuaPlayer:render_mode is written to.
  3. Do nothing; and let me suffer. I know it's very niche.
Attachments
update-lag-demo_1.0.0.zip
A "minimum-code" mod to visualize the problem.
(1.82 KiB) Downloaded 13 times
factorio-current.log
A log generated using the example mod.
(9.33 KiB) Downloaded 10 times
Rseding91
Factorio Staff
Factorio Staff
Posts: 16050
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: [2.0.62] Wrong value in LuaPlayer:render_mode

Post by Rseding91 »

From looking at the code I don't consider this to be a bug. We never implied these two values would be updated in any order, let alone within the same tick when one or the other changes.

render_mode is updated at the beginning of the tick, and then if in that tick the controller changes it won't be updated again until the next tick.

render_mode updates at most once per tick at the beginning of the tick and the controller can change an infinite number of times within a given tick. They aren't tied to each other and no guarantees are made about the state of one meaning anything about the other.
If you want to get ahold of me I'm almost always on Discord.
Post Reply

Return to “Not a bug”