Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Jun 6, 2025. It is now read-only.
This repository was archived by the owner on Jun 6, 2025. It is now read-only.

Blueprint manipulation donation #56

@kryojenik

Description

@kryojenik

This may or may not be useful to this project, but I thought I'd donate it here in case you thought it may be. Attempting to work with blueprints (specifically of the ctrl-c variety being stamped on existing entities) is tough. We don't get many events with a lot of info. Just on_pre_build. So you pretty much have to do your own BP position calculations. These are a couple of functions that I put together to get a bounding box of all the BP entities, and how to find the center of where the BP will be placed. If helpful, feel free to use them freely in flib.

---@param entities BlueprintEntity[] # E.g. from LuaPlayer.get_blueprint_entities()
---@return BoundingBox # Box that contains all blueprint entities
---@return uint # The building grid size needed to build this blueprint
function M.get_blueprint_bounding_box(entities)
  local box = flib_box.from_position(entities[1].position, true)
  local names = {}
  for _, e in ipairs(entities) do
    names[e.name] = true
  end

  local name_filter = {}
  for k, _ in pairs(names) do
    table.insert(name_filter, k)
  end

  -- Define a bounding box the size of the blueprint to be placed
  local grid_size = 1
  ---@diagnostic disable-next-line:missing-fields
  local protos = game.get_filtered_entity_prototypes{{filter = "name", name = name_filter}}
  for _, entity in pairs(entities) do
    local collision_box = protos[entity.name].collision_box
    grid_size = math.max(grid_size, protos[entity.name].building_grid_bit_shift)
    box = flib_box.expand_to_contain_box(
      box,
      flib_box.from_dimensions(
        entity.position,
        flib_box.width(collision_box),
        flib_box.height(collision_box)
      )
    )
  end

  -- Expand bounding box to be full tiles based on the entity with the largest building grid size
  box.left_top.x = grid_size * math.floor(box.left_top.x / grid_size)
  box.left_top.y = grid_size * math.floor(box.left_top.y / grid_size)
  box.right_bottom.x = grid_size * math.ceil(box.right_bottom.x / grid_size)
  box.right_bottom.y = grid_size * math.ceil(box.right_bottom.y / grid_size)
  return box, grid_size
end
---@param box BoundingBox # Bounding box of blueprint to place
---@param pos MapPosition # Position to center new bounding box around
---@param grid_size uint? # Building grid size to base centering.  Default: 1
---@return MapPosition # Center position of where blueprint will be placed
function M.get_placed_blueprint_center(box, pos, grid_size)
  local grid_size = grid_size or 1
  local pos_x = pos.x or pos[1]
  local pos_y = pos.y or pos[2]
  pos_x = (flib_box.width(box) / grid_size) % 2 == 0
          and math.floor(pos_x / grid_size + .5 ) * grid_size
          or math.floor(pos_x / grid_size) * grid_size + grid_size / 2
  pos_y = (flib_box.height(box) / grid_size) % 2 == 0
          and math.floor(pos_y / grid_size + .5 ) * grid_size
          or math.floor(pos_y / grid_size) * grid_size + grid_size / 2
  if pos.x then
    return { x = pos_x, y = pos_y }
  else
    return { pos_x, pos_y }
  end
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions