z_mirror/Krastorio2

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

Caleb HeuerOverride old shelter data if any of its entities are invalid0415cb88

trunk
5.2 KiB184 linesraw
1local util = require("scripts.util")
2
3--- @class ShelterData
4--- @field container LuaEntity
5--- @field electric LuaEntity
6--- @field light LuaEntity
7--- @field former_spawn_point MapPosition
8
9--- @param force LuaForce
10local function init_force(force)
11  if not storage.shelter then
12    return
13  end
14  storage.shelter.forces[force.index] = {}
15end
16
17local function spawn_flying_texts()
18  for unit_number, entity in pairs(storage.shelter.inactive) do
19    if entity.valid then
20      util.entity_flying_text(entity, { "message.kr-shelter-is-inactive" }, { r = 1 })
21    else
22      storage.shelter.inactive[unit_number] = nil
23    end
24  end
25end
26
27--- @param shelter_data ShelterData
28local function all_are_valid(shelter_data)
29  return shelter_data.container.valid and shelter_data.electric.valid and shelter_data.light.valid
30end
31
32--- @param entity LuaEntity
33local function destroy_if_valid(entity)
34  if entity.valid then
35    entity.destroy()
36  end
37end
38
39--- @param e EntityBuiltEvent
40local function on_entity_built(e)
41  local entity = e.entity or e.destination
42  if not entity.valid then
43    return
44  end
45  if entity.name ~= "kr-shelter-container" and entity.name ~= "kr-shelter-plus-container" then
46    return
47  end
48  --- @cast entity LuaEntity
49
50  local force = entity.force
51  local surface = entity.surface
52  local force_shelters = storage.shelter.forces[force.index]
53
54  local existing_shelter_data = force_shelters[surface.index]
55  if existing_shelter_data then
56    if all_are_valid(existing_shelter_data) then
57      local name = entity.name:gsub("kr%-", "kr-inactive-"):gsub("%-container", "")
58      local position = entity.position
59      local force = entity.force
60      local player = entity.last_user
61      local surface = entity.surface
62      entity.destroy()
63
64      local new_entity = surface.create_entity({
65        name = name,
66        position = position,
67        force = force,
68        player = player,
69        create_build_effect_smoke = false,
70        raise_built = true,
71      })
72      if new_entity and new_entity.valid then
73        storage.shelter.inactive[new_entity.unit_number] = new_entity
74      end
75      return
76    else
77      force.set_spawn_position(existing_shelter_data.former_spawn_point, surface)
78      destroy_if_valid(existing_shelter_data.container)
79      destroy_if_valid(existing_shelter_data.electric)
80      destroy_if_valid(existing_shelter_data.light)
81      force_shelters[force.index] = nil
82    end
83  end
84
85  local _, _, base_name = string.find(entity.name, "^(.*)%-container")
86  --- @type ShelterData
87  local shelter_data = { container = entity }
88
89  for key, suffix in pairs({ electric = "", light = "-light" }) do
90    local name = base_name .. suffix
91    shelter_data[key] = surface.create_entity({
92      name = name,
93      position = entity.position,
94      force = force,
95      player = entity.last_user,
96      create_build_effect_smoke = false,
97      raise_built = true,
98    })
99  end
100
101  shelter_data.former_spawn_point = force.get_spawn_position(surface)
102  force.set_spawn_position({ x = entity.position.x, y = entity.position.y + 3.5 }, surface)
103
104  force_shelters[surface.index] = shelter_data
105end
106
107--- @param e EntityDestroyedEvent
108local function on_entity_destroyed(e)
109  local entity = e.entity
110  if not entity or not entity.valid then
111    return
112  end
113  if entity.name ~= "kr-shelter-container" and entity.name ~= "kr-shelter-plus-container" then
114    return
115  end
116
117  local inactive = storage.shelter.inactive[entity.unit_number]
118  if inactive then
119    storage.shelter.inactive[entity.unit_number] = nil
120  else
121    local force = entity.force
122
123    local force_shelters = storage.shelter.forces[force.index]
124    if not force_shelters then
125      return
126    end
127
128    local surface_index = entity.surface.index
129    local shelter_data = force_shelters[surface_index]
130    if not shelter_data then
131      return
132    end
133
134    destroy_if_valid(shelter_data.electric)
135    destroy_if_valid(shelter_data.light)
136    force_shelters[surface_index] = nil
137
138    force.set_spawn_position(shelter_data.former_spawn_point, surface_index)
139  end
140end
141
142--- @param e EventData.on_force_created
143local function on_force_created(e)
144  if e.force.valid then
145    init_force(e.force)
146  end
147end
148
149--- @class ShelterHandler : event_handler
150local shelter = {}
151
152function shelter.on_init()
153  storage.shelter = {
154    --- @type table<uint, table<uint, ShelterData>>
155    forces = {},
156    --- @type table<uint, LuaEntity>
157    inactive = {},
158  }
159
160  for _, force in pairs(game.forces) do
161    init_force(force)
162  end
163end
164
165shelter.events = {
166  [defines.events.on_built_entity] = on_entity_built,
167  [defines.events.on_entity_cloned] = on_entity_built,
168  [defines.events.on_entity_died] = on_entity_destroyed,
169  [defines.events.on_force_created] = on_force_created,
170  [defines.events.on_player_mined_entity] = on_entity_destroyed,
171  [defines.events.on_robot_built_entity] = on_entity_built,
172  [defines.events.on_robot_mined_entity] = on_entity_destroyed,
173  [defines.events.script_raised_built] = on_entity_built,
174  [defines.events.script_raised_destroy] = on_entity_destroyed,
175  [defines.events.script_raised_revive] = on_entity_built,
176  [defines.events.on_space_platform_built_entity] = on_entity_built,
177  [defines.events.on_space_platform_mined_entity] = on_entity_destroyed,
178}
179
180shelter.on_nth_tick = {
181  [180] = spawn_flying_texts,
182}
183
184return shelter