Milestones

by Wiwiweb

Keep track of your progress in a fun way by finding out how fast you created key items. Look back on your factory's history, compare with your friends, or challenge yourself. Compatible out-of-the-box with most overhaul mods, and can be customized to work with any mod. Can be added to existing games.

Utilities
a month ago
1.1 - 2.1
334K

g [Fixed] Crash when playing with Brave New Oarc

2 years ago
(updated 2 years ago)

I'm dev for BNO, this is a mod that supports multiplayer. Milestones crashes in on_player_changed_force while updating the gui, since the global.player array is not updated, due to how BNO works.

I did some debugging and at on_init time no player has joined yet, so the game.players list is empty.

on_init:

     for _, player in pairs(game.players) do
        initialize_player(player)
    end

does nothing because the number of players is 0 at this point.

Then an event for on_player_changed_force triggers which initializes the force, but not the global.players array. The call to refresh_gui_for_player accesses global.players without initializing and results in a crash in gui.lua function get_frame, where it loads the global.players[player_index] - which is nil.

Easiest way to see this is just run brave new oarc with milestones and start a single player game in the debugger. Put a break in on_player_changed_force.

Maybe initialize_force_if_needed could also initialize players as you do in on_init.

Nice work !

2 years ago
(updated 2 years ago)

I did a bit more digging, MileStones expected on_player_created to be called first, but BNO forces on_player_changed_force to be called first since it removes a player and changes it's force if the host created the game from a single player save. Here is a fix that works:

This is a copy from your code - with initialize_player added for both events mentioned above:

script.on_event(defines.events.on_player_changed_force, function(event)
    local player = game.get_player(event.player_index)
    if not global.players[player.index] then           -- <- added block
        initialize_player(player)
    end
    initialize_force_if_needed(player.force)
    refresh_gui_for_player(player)
end)

script.on_event(defines.events.on_forces_merged, function(event)
    clear_force(event.source_name)
end)

script.on_event(defines.events.on_player_created, function(event)
    local player = game.players[event.player_index]
    if not global.players[player.index] then            -- <- added if 
        initialize_player(player)
    end
    if global.forces[player.force.name] == nil then -- Possible if new player is added to empty force e.g. vanilla freeplay
        initialize_force_if_needed(player.force)
    end
end)
1 year, 6 months ago

This will be fixed next release. Better late than never!

New response