z_mirror/BlueprintTools

git clone https://git.raiguard.me/z_mirror/BlueprintTools

Caleb HeuerGet control scripting working00b37f1

trunk
3.4 KiB113 linesraw
1local flib_bounding_box = require("__flib__.bounding-box")
2local table = require("__flib__.table")
3
4local constants = require("constants")
5local util = require("scripts.util")
6
7return function(player, tile_name, fill_gaps, margin)
8  local blueprint = util.get_blueprint(player.cursor_stack)
9  if not blueprint then
10    return
11  end
12
13  local entities = blueprint.get_blueprint_entities() or {}
14  local tiles = blueprint.get_blueprint_tiles() or {}
15  local entity_prototypes = prototypes.entity
16
17  local output_tiles = {}
18  local tile_index = 0
19
20  local first_obj = entities[1] or tiles[1]
21
22  if fill_gaps then
23    local box = flib_bounding_box.from_position(first_obj.position)
24
25    -- iterate entities to calculate needed grid size
26    for _, entity in pairs(entities) do
27      local prototype = entity_prototypes[entity.name]
28      if prototype then
29        local entity_box = (
30          prototype.type == "curved-rail"
31            and table.deep_copy(constants.curved_rail_grid_sizes[math.floor((entity.direction or 0) / 2) % 2 + 1])
32          or prototype.collision_box
33        )
34        box = flib_bounding_box.expand_to_contain_box(box, flib_bounding_box.move(entity_box, entity.position))
35      end
36    end
37    -- and tiles
38    for _, tile in pairs(tiles) do
39      box = flib_bounding_box.expand_to_contain_box(box, {
40        left_top = { x = tile.position.x, y = tile.position.y },
41        right_bottom = { x = tile.position.x + 1, y = tile.position.y + 1 },
42      })
43    end
44
45    -- ceil to outside edges and add a margin
46    box = flib_bounding_box.resize(flib_bounding_box.ceil(box), margin)
47
48    -- for the purpose of this function, we don't care about any pre-existing tiles - we will replace all of them
49    util.for_each_position(box, function(position)
50      tile_index = tile_index + 1
51      output_tiles[tile_index] = {
52        position = position,
53        name = tile_name,
54      }
55    end)
56  else
57    local mapping = {}
58    local function add_tile(position)
59      local add = false
60
61      if mapping[position.x] then
62        if not mapping[position.x][position.y] then
63          add = true
64          mapping[position.x][position.y] = true
65        end
66      else
67        add = true
68        mapping[position.x] = { [position.y] = true }
69      end
70
71      if add then
72        tile_index = tile_index + 1
73        output_tiles[tile_index] = {
74          position = position,
75          name = tile_name,
76        }
77      end
78    end
79
80    for _, entity in pairs(entities) do
81      local rail_tiles = util.get_rail_tiles(entity)
82      if rail_tiles then
83        local entity_pos = entity.position
84        for _, src_position in pairs(rail_tiles) do
85          util.for_each_position(
86            flib_bounding_box.resize(flib_bounding_box.from_position(src_position, true), margin),
87            function(position)
88              add_tile({ x = position.x + entity_pos.x, y = position.y + entity_pos.y })
89            end
90          )
91        end
92      else
93        local prototype = entity_prototypes[entity.name]
94        if prototype then
95          util.for_each_position(
96            flib_bounding_box.resize(
97              flib_bounding_box.ceil(flib_bounding_box.move(prototype.collision_box, entity.position)),
98              margin
99            ),
100            function(position)
101              add_tile(position)
102            end
103          )
104        end
105      end
106    end
107    for _, tile in pairs(tiles) do
108      add_tile(tile.position)
109    end
110  end
111
112  blueprint.set_blueprint_tiles(output_tiles)
113end