z_mirror/flib

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

Caleb HeuerRemove require guardsa9f2be7

trunk
4.9 KiB180 linesraw
1--- Utilities for data stage prototype manipulation.
2--- ```lua
3--- local flib_data_util = require("__flib__.data-util")
4--- ```
5--- @class flib_data_util
6local flib_data_util = {}
7
8--- Copy a prototype, assigning a new name and minable properties.
9--- @param prototype table
10--- @param new_name string string
11--- @param remove_icon? boolean
12--- @return table
13function flib_data_util.copy_prototype(prototype, new_name, remove_icon)
14  if not prototype.type or not prototype.name then
15    error("Invalid prototype: prototypes must have name and type properties.")
16    return --- @diagnostic disable-line
17  end
18  local p = table.deepcopy(prototype)
19  p.name = new_name
20  if p.minable and p.minable.result then
21    p.minable.result = new_name
22  end
23  if p.place_result then
24    p.place_result = new_name
25  end
26  if p.result then
27    p.result = new_name
28  end
29  if p.results then
30    for _, result in pairs(p.results) do
31      if result.name == prototype.name then
32        result.name = new_name
33      end
34    end
35  end
36  if remove_icon then
37    p.icon = nil
38    p.icon_size = nil
39    p.icons = nil
40  end
41
42  return p
43end
44
45--- Copy prototype.icon/icons to a new fully defined icons array, optionally adding new icon layers.
46---
47--- Returns `nil` if the prototype's icons are incorrectly or incompletely defined.
48--- @param prototype table
49--- @param new_layers? data.IconData[]
50--- @return data.IconData[]|nil
51function flib_data_util.create_icons(prototype, new_layers)
52  if new_layers then
53    for _, new_layer in pairs(new_layers) do
54      if not new_layer.icon or not new_layer.icon_size then
55        return nil
56      end
57    end
58  end
59
60  if prototype.icons then
61    local icons = {}
62    for _, v in pairs(prototype.icons) do
63      -- Over define as much as possible to minimize weirdness: https://forums.factorio.com/viewtopic.php?f=25&t=81980
64      icons[#icons + 1] = {
65        icon = v.icon,
66        icon_size = v.icon_size or prototype.icon_size,
67        tint = v.tint,
68        scale = v.scale,
69        shift = v.shift,
70      }
71    end
72    if new_layers then
73      for _, new_layer in pairs(new_layers) do
74        icons[#icons + 1] = new_layer
75      end
76    end
77    return icons
78  elseif prototype.icon then
79    local icons = {
80      {
81        icon = prototype.icon,
82        icon_size = prototype.icon_size,
83        tint = { r = 1, g = 1, b = 1, a = 1 },
84      },
85    }
86    if new_layers then
87      for _, new_layer in pairs(new_layers) do
88        icons[#icons + 1] = new_layer
89      end
90    end
91    return icons
92  else
93    return nil
94  end
95end
96
97local exponent_multipliers = {
98  ["q"] = 0.000000000000000000000000000001,
99  ["r"] = 0.000000000000000000000000001,
100  ["y"] = 0.000000000000000000000001,
101  ["z"] = 0.000000000000000000001,
102  ["a"] = 0.000000000000000001,
103  ["f"] = 0.000000000000001,
104  ["p"] = 0.000000000001,
105  ["n"] = 0.000000001,
106  ["u"] = 0.000001, -- μ is invalid
107  ["m"] = 0.001,
108  ["c"] = 0.01,
109  ["d"] = 0.1,
110  [""] = 1,
111  ["da"] = 10,
112  ["h"] = 100,
113  ["k"] = 1000,
114  ["M"] = 1000000,
115  ["G"] = 1000000000,
116  ["T"] = 1000000000000,
117  ["P"] = 1000000000000000,
118  ["E"] = 1000000000000000000,
119  ["Z"] = 1000000000000000000000,
120  ["Y"] = 1000000000000000000000000,
121  ["R"] = 1000000000000000000000000000,
122  ["Q"] = 1000000000000000000000000000000,
123}
124
125--- Convert an energy string to base unit value + suffix.
126---
127--- Returns `nil` if `energy_string` is incorrectly formatted.
128--- @param energy_string string
129--- @return number?
130--- @return string?
131function flib_data_util.get_energy_value(energy_string)
132  if type(energy_string) == "string" then
133    local v, _, exp, unit = string.match(energy_string, "([%-+]?[0-9]*%.?[0-9]+)((%D*)([WJ]))")
134    local value = tonumber(v)
135    if value and exp and exponent_multipliers[exp] then
136      value = value * exponent_multipliers[exp]
137      return value, unit
138    end
139  end
140  return nil
141end
142
143--- Build a sprite from constituent parts.
144--- @param name? string
145--- @param position? MapPosition
146--- @param filename? string
147--- @param size? Vector
148--- @param mods? table
149--- @return data.Sprite
150function flib_data_util.build_sprite(name, position, filename, size, mods)
151  --- @type data.Sprite
152  local def = {
153    type = "sprite",
154    name = name,
155    filename = filename,
156    position = position,
157    size = size,
158    flags = { "icon" },
159  }
160  if mods then
161    for k, v in pairs(mods) do
162      def[k] = v
163    end
164  end
165  return def
166end
167
168--- An empty image. This image is 8x8 to facilitate usage with GUI styles.
169flib_data_util.empty_image = "__flib__/graphics/empty.png"
170
171--- A black image, for use with tool backgrounds. This image is 1x1.
172flib_data_util.black_image = "__flib__/graphics/black.png"
173
174--- A desaturated planner image. Tint this sprite to easily add your own planners.
175flib_data_util.planner_base_image = "__flib__/graphics/planner.png"
176
177--- A dark red button tileset. Used for the `flib_tool_button_dark_red` style.
178flib_data_util.dark_red_button_tileset = "__flib__/graphics/dark-red-button.png"
179
180return flib_data_util