mspielberg / factorio-railloader

Rapidly load and unload trains of bulk materials.
GNU Lesser General Public License v3.0
9 stars 19 forks source link

Rail Loader _always_ invalidates blueprint mapping #25

Closed ghost closed 3 years ago

ghost commented 3 years ago

Currently, the function on_blueprint at the end, always calls set_blueprint_entities(), even when there are no rail (un)loaders in the blueprint. This will always invalidate the mapping of the blueprint for all other mods after itself being called.

A simple flag added would fix this issue update_bp flag:

local function on_blueprint(event)
  local bp = get_blueprint_to_setup(event.player_index)
  if not bp then return end
  local player = game.players[event.player_index]
  local entities = bp.get_blueprint_entities()

  local railloader_chests = find_railloaders_in_area(player.surface, event.area)
  if not next(railloader_chests) then return end

  local chest_index = 1
  local update_bp = false
  for _, bp_entity in pairs(entities) do
    if bp_entity.name == "railloader-chest" or bp_entity.name == "railunloader-chest" then
      local chest_entity = railloader_chests[chest_index]
      chest_index = chest_index + 1

      local rail = player.surface.find_entities_filtered{
        type = "straight-rail",
        area = chest_entity.bounding_box,
      }[1]
      if rail then
        bp_entity.name = (bp_entity.name == "railloader-chest")
          and "railloader-placement-proxy"
          or "railunloader-placement-proxy"
        -- base direction on direction of rail
        bp_entity.direction = rail.direction
        -- preserve chest limit
        bp_entity.tags = { bar = chest_entity.get_inventory(defines.inventory.chest).get_bar() }
    update_bp = true
      end
    end
  end

  if update_bp then bp.set_blueprint_entities(entities) end
end

Edit: formatting

mspielberg commented 3 years ago

This should be taken care of by the if not next(railloader_chests) check, which returns from the function early.

ghost commented 3 years ago

Ok, figured it out (with a lot more logging statements). It's not your rail loader, but the blueprinting. When reusing a blueprint (blue "Select new contents" button), the blueprint retrieved from player.blueprint_to_setup isn't valid_for_read and the blueprint retrieved via player.cursor_stack is missing the blueprint entities (bp.get_blueprint_entities() returns nil).

This may be a bug in the main game... Will make a post on the forum about it, as this hurts mods like yours that need to either replace entities, or store data in tags.

mspielberg commented 3 years ago

Problems with "Select new contents" is a known bug with significant impact and no projected fix: https://forums.factorio.com/88100 The on_gui_closed logic in BRL should work around the bug as long as the blueprint being updated is a character inventory, and not in the blueprint library.

ghost commented 3 years ago

Yea, mk-fg sent me that link last night. I need to learn to not be soo specific in my search terms, otherwise I would've had that one in my search results (I used "reuse" instead of "new contents" in search).

You'd think it'd be trivial to drop the reference into player.blueprint_to_setup during the event.

mspielberg commented 3 years ago

The blueprint library throws a wrench into everything. Blueprints living in the library are not real items, so they don't behave correctly when in the cursor, can't have a reference to them passed into events, can't be inspected or modified from a quickbar slot, etc.