z_mirror/Tapeline

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

Caleb HeuerImplement tape clear delay223dcef

3.0
5.5 KiB194 linesraw
1local flib_bounding_box = require("__flib__.bounding-box")
2
3--- @class Tape
4--- @field anchor MapPosition
5--- @field box BoundingBox
6--- @field cursor MapPosition
7--- @field entity LuaEntity
8--- @field tick_to_die MapTick
9--- @field id integer
10--- @field player LuaPlayer
11--- @field background LuaRenderObject
12--- @field border LuaRenderObject
13--- @field label_north LuaRenderObject
14--- @field label_west LuaRenderObject
15
16--- @param player LuaPlayer
17--- @param entity LuaEntity
18--- @return Tape
19local function new_tape(player, entity)
20  local id = storage.next_tape_id
21  storage.next_tape_id = id + 1
22  local box = flib_bounding_box.from_position(entity.position, true)
23  local center = flib_bounding_box.center(box)
24  --- @type Tape
25  local self = {
26    anchor = entity.position,
27    box = box,
28    cursor = entity.position,
29    entity = entity,
30    id = id,
31    player = player,
32    tick_to_die = math.huge,
33    background = rendering.draw_rectangle({
34      color = player.mod_settings["tl-tape-background-color"].value --[[@as Color]],
35      filled = true,
36      players = { player },
37      surface = entity.surface,
38      left_top = box.left_top,
39      right_bottom = box.right_bottom,
40    }),
41    border = rendering.draw_rectangle({
42      color = player.mod_settings["tl-tape-border-color"].value --[[@as Color]],
43      filled = false,
44      width = player.mod_settings["tl-tape-line-width"].value --[[@as double]],
45      players = { player },
46      surface = entity.surface,
47      left_top = box.left_top,
48      right_bottom = box.right_bottom,
49    }),
50    label_north = rendering.draw_text({
51      text = flib_bounding_box.width(box),
52      surface = entity.surface,
53      target = { x = center.x, y = box.left_top.y },
54      color = player.mod_settings["tl-tape-label-color"].value --[[@as Color]],
55      scale = 2,
56      alignment = "center",
57      vertical_alignment = "bottom",
58    }),
59    label_west = rendering.draw_text({
60      text = flib_bounding_box.height(box),
61      surface = entity.surface,
62      target = { x = box.left_top.x, y = center.y },
63      color = player.mod_settings["tl-tape-label-color"].value --[[@as Color]],
64      scale = 2,
65      alignment = "center",
66      vertical_alignment = "bottom",
67      orientation = 0.75,
68    }),
69  }
70  storage.tapes[id] = self
71  return self
72end
73
74--- @param self Tape
75local function update_tape(self)
76  self.background.left_top = self.box.left_top
77  self.background.right_bottom = self.box.right_bottom
78  self.border.left_top = self.box.left_top
79  self.border.right_bottom = self.box.right_bottom
80  local center = flib_bounding_box.center(self.box)
81  self.label_north.target = { x = center.x, y = self.box.left_top.y }
82  self.label_north.text = flib_bounding_box.width(self.box)
83  self.label_west.target = { x = self.box.left_top.x, y = center.y }
84  self.label_west.text = flib_bounding_box.height(self.box)
85end
86
87--- @param self Tape
88--- @param entity LuaEntity
89local function resize_tape(self, entity)
90  local old = self.entity
91  if old and old.valid then
92    old.destroy()
93  end
94  self.entity = entity
95  local position = entity.position
96  local box = flib_bounding_box.from_position(self.anchor, true)
97  box = flib_bounding_box.expand_to_contain_position(box, position)
98  box = flib_bounding_box.ceil(box)
99  self.box = box
100  self.cursor = position
101  update_tape(self)
102end
103
104--- @param self Tape
105local function destroy_tape(self)
106  if self.background.valid then
107    self.background.destroy()
108  end
109  if self.border.valid then
110    self.border.destroy()
111  end
112  if self.label_north.valid then
113    self.label_north.destroy()
114  end
115  if self.label_west.valid then
116    self.label_west.destroy()
117  end
118  local entity = self.entity
119  if entity and entity.valid then
120    entity.destroy()
121  end
122  storage.tapes[self.id] = nil
123end
124
125local function on_init()
126  --- @type table<uint, Tape>
127  storage.drawing = {}
128  storage.next_tape_id = 1
129  --- @type table<uint, Tape>
130  storage.tapes = {}
131end
132
133--- @param e EventData.on_built_entity
134local function on_built_entity(e)
135  local entity = e.entity
136  if not entity.valid then
137    return
138  end
139  local name = entity.name
140  if name == "entity-ghost" then
141    name = entity.ghost_name
142  end
143  if name ~= "tl-dummy-entity" then
144    return
145  end
146  local drawing = storage.drawing[e.player_index]
147  local player = game.get_player(e.player_index) --[[@as LuaPlayer]]
148  if drawing then
149    resize_tape(drawing, entity)
150  else
151    drawing = new_tape(player, e.entity)
152    storage.drawing[e.player_index] = drawing
153  end
154end
155
156--- @param e EventData.on_player_selected_area|EventData.on_player_alt_selected_area
157local function on_player_selected_area(e)
158  local tape_data = storage.drawing[e.player_index]
159  if not tape_data then
160    return
161  end
162  storage.drawing[e.player_index] = nil
163  if e.name == defines.events.on_player_selected_area then
164    local time_to_live = tape_data.player.mod_settings["tl-tape-clear-delay"].value --[[@as double]]
165    tape_data.tick_to_die = game.tick + time_to_live * 60
166  end
167  storage.tapes[tape_data.id] = tape_data
168end
169
170--- @param e EventData.on_tick
171local function on_tick(e)
172  for _, tape_data in pairs(storage.tapes or {}) do
173    if tape_data.tick_to_die > e.tick then
174      goto continue
175    end
176
177    destroy_tape(tape_data)
178
179    ::continue::
180  end
181end
182
183local tape = {}
184
185tape.on_init = on_init
186
187tape.events = {
188  [defines.events.on_built_entity] = on_built_entity,
189  [defines.events.on_player_alt_selected_area] = on_player_selected_area,
190  [defines.events.on_player_selected_area] = on_player_selected_area,
191  [defines.events.on_tick] = on_tick,
192}
193
194return tape