You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
367 lines
13 KiB
367 lines
13 KiB
local Landingpad = {}
|
|
|
|
-- constants
|
|
Landingpad.name_rocket_landing_pad = mod_prefix.."rocket-landing-pad"
|
|
Landingpad.name_rocket_landing_pad_settings = mod_prefix.."rocket-landing-pad-settings"
|
|
|
|
---@class LandingPad All data necessary to maintain the state of a delivery cannon
|
|
|
|
--- Gets the Landingpad for this unit_number
|
|
---@param unit_number number
|
|
function Landingpad.from_unit_number (unit_number)
|
|
if not unit_number then Log.trace("Landingpad.from_unit_number: invalid unit_number: nil") return end
|
|
unit_number = tonumber(unit_number)
|
|
-- NOTE: only supports container as the entity
|
|
if global.rocket_landing_pads[unit_number] then
|
|
return global.rocket_landing_pads[unit_number]
|
|
else
|
|
Log.trace("Landingpad.from_unit_number: invalid unit_number: " .. unit_number)
|
|
end
|
|
end
|
|
|
|
--- Gets the Landingpad for this entity
|
|
---@param entity LuaEntity
|
|
function Landingpad.from_entity (entity)
|
|
if not(entity and entity.valid) then
|
|
Log.trace("Landingpad.from_entity: invalid entity")
|
|
return
|
|
end
|
|
-- NOTE: only suppors container as the entity
|
|
return Landingpad.from_unit_number(entity.unit_number)
|
|
end
|
|
|
|
-- returns the available struct
|
|
function Landingpad.get_force_landing_pads_availability(force_name, landing_pad_name)
|
|
|
|
local empty_landing_pads = {}
|
|
local filled_landing_pads = {}
|
|
local blocked_landing_pads = {}
|
|
|
|
if global.forces[force_name] and global.forces[force_name].rocket_landing_pad_names and global.forces[force_name].rocket_landing_pad_names[landing_pad_name] then
|
|
local landing_pads = global.forces[force_name].rocket_landing_pad_names[landing_pad_name]
|
|
|
|
for _, landing_pad in pairs(landing_pads) do
|
|
if landing_pad.container and landing_pad.container.valid then
|
|
if landing_pad.inbound_rocket then
|
|
table.insert(blocked_landing_pads, landing_pad)
|
|
elseif landing_pad.container.get_inventory(defines.inventory.chest).is_empty() then
|
|
table.insert(empty_landing_pads, landing_pad)
|
|
else
|
|
table.insert(filled_landing_pads, landing_pad)
|
|
end
|
|
else
|
|
Landingpad.destroy(landing_pad)
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
return {
|
|
empty_landing_pads = empty_landing_pads,
|
|
filled_landing_pads = filled_landing_pads,
|
|
blocked_landing_pads = blocked_landing_pads,
|
|
}
|
|
|
|
end
|
|
|
|
-- returns the available struct
|
|
function Landingpad.get_zone_landing_pads_availability(force_name, zone, landing_pad_name)
|
|
|
|
local empty_landing_pads = {}
|
|
local filled_landing_pads = {}
|
|
local blocked_landing_pads = {}
|
|
|
|
local zone_assets = Zone.get_force_assets(force_name, zone.index)
|
|
if zone_assets.rocket_landing_pad_names and zone_assets.rocket_landing_pad_names[landing_pad_name] then
|
|
local landing_pads = zone_assets.rocket_landing_pad_names[landing_pad_name]
|
|
|
|
|
|
for _, landing_pad in pairs(landing_pads) do
|
|
if landing_pad.container and landing_pad.container.valid then
|
|
if landing_pad.inbound_rocket then
|
|
table.insert(blocked_landing_pads, landing_pad)
|
|
elseif landing_pad.container.get_inventory(defines.inventory.chest).is_empty() then
|
|
table.insert(empty_landing_pads, landing_pad)
|
|
else
|
|
table.insert(filled_landing_pads, landing_pad)
|
|
end
|
|
else
|
|
Landingpad.destroy(landing_pad)
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
return {
|
|
empty_landing_pads = empty_landing_pads,
|
|
filled_landing_pads = filled_landing_pads,
|
|
blocked_landing_pads = blocked_landing_pads,
|
|
}
|
|
|
|
end
|
|
|
|
function Landingpad.on_entity_created(event)
|
|
local entity
|
|
if event.entity and event.entity.valid then
|
|
entity = event.entity
|
|
end
|
|
if event.created_entity and event.created_entity.valid then
|
|
entity = event.created_entity
|
|
end
|
|
if not entity then return end
|
|
if entity.name == Landingpad.name_rocket_landing_pad then
|
|
local zone = Zone.from_surface(entity.surface)
|
|
if not zone then
|
|
return cancel_entity_creation(entity, event.player_index, "Invalid landing pad location")
|
|
end
|
|
local fn = entity.force.name
|
|
|
|
local default_name = zone.name .. " Landing Pad"
|
|
|
|
local struct = {
|
|
type = Landingpad.name_rocket_landing_pad,
|
|
valid = true,
|
|
force_name = fn,
|
|
unit_number = entity.unit_number,
|
|
container = entity,
|
|
name = default_name,
|
|
zone = zone
|
|
}
|
|
global.rocket_landing_pads = global.rocket_landing_pads or {}
|
|
global.rocket_landing_pads[entity.unit_number] = struct
|
|
|
|
-- set settings
|
|
if event.tags and event.tags.name then
|
|
struct.name = event.tags.name
|
|
end
|
|
|
|
Landingpad.name(struct) -- assigns to zone_assets
|
|
|
|
if event.player_index and game.players[event.player_index] and game.players[event.player_index].connected then
|
|
LandingpadGUI.gui_open(game.players[event.player_index], struct)
|
|
end
|
|
end
|
|
end
|
|
Event.addListener(defines.events.on_entity_cloned, Landingpad.on_entity_created)
|
|
Event.addListener(defines.events.on_built_entity, Landingpad.on_entity_created)
|
|
Event.addListener(defines.events.on_robot_built_entity, Landingpad.on_entity_created)
|
|
Event.addListener(defines.events.script_raised_built, Landingpad.on_entity_created)
|
|
Event.addListener(defines.events.script_raised_revive, Landingpad.on_entity_created)
|
|
|
|
function Landingpad.remove_struct_from_tables(struct)
|
|
|
|
-- force
|
|
local force_data = global.forces[struct.force_name]
|
|
force_data.rocket_landing_pad_names = force_data.rocket_landing_pad_names or {}
|
|
local force_type_table = force_data.rocket_landing_pad_names
|
|
|
|
if not force_type_table[struct.name] then return end
|
|
force_type_table[struct.name][struct.unit_number] = nil
|
|
local count_remaining = 0
|
|
for _, remaining in pairs(force_type_table[struct.name]) do
|
|
count_remaining = count_remaining + 1
|
|
end
|
|
if count_remaining == 0 then
|
|
force_type_table[struct.name] = nil
|
|
end
|
|
|
|
-- zone
|
|
local zone_assets = Zone.get_force_assets(struct.force_name, struct.zone.index)
|
|
zone_assets.rocket_landing_pad_names = zone_assets.rocket_landing_pad_names or {}
|
|
local zone_type_table = zone_assets.rocket_landing_pad_names
|
|
|
|
if not zone_type_table[struct.name] then return end
|
|
zone_type_table[struct.name][struct.unit_number] = nil
|
|
local count_remaining = 0
|
|
for _, remaining in pairs(zone_type_table[struct.name]) do
|
|
count_remaining = count_remaining + 1
|
|
end
|
|
if count_remaining == 0 then
|
|
zone_type_table[struct.name] = nil
|
|
end
|
|
|
|
end
|
|
|
|
function Landingpad.destroy_sub(struct, key)
|
|
if struct[key] and struct[key].valid then
|
|
struct[key].destroy()
|
|
struct[key] = nil
|
|
end
|
|
end
|
|
|
|
function Landingpad.destroy(struct)
|
|
if not struct then
|
|
Log.trace("Landingpad.destroy: no struct")
|
|
return
|
|
end
|
|
struct.valid = false
|
|
Landingpad.destroy_sub(struct, 'container')
|
|
|
|
Landingpad.remove_struct_from_tables(struct)
|
|
global.rocket_landing_pads[struct.unit_number] = nil
|
|
|
|
-- if a player has this gui open then close it
|
|
local gui_name = LandingpadGUI.name_rocket_landing_pad_gui_root
|
|
for _, player in pairs(game.connected_players) do
|
|
local root = player.gui.relative[gui_name]
|
|
if root and root.tags and root.tags.unit_number == struct.unit_number then
|
|
player.gui.relative[gui_name].destroy()
|
|
end
|
|
end
|
|
end
|
|
|
|
function Landingpad.name(struct, new_name)
|
|
struct.name = (new_name or struct.name)
|
|
|
|
-- force
|
|
local force_data = global.forces[struct.force_name]
|
|
force_data.rocket_landing_pad_names = force_data.rocket_landing_pad_names or {}
|
|
local force_type_table = force_data.rocket_landing_pad_names
|
|
|
|
force_type_table[struct.name] = force_type_table[struct.name] or {}
|
|
force_type_table[struct.name][struct.unit_number] = struct
|
|
|
|
local zone_assets = Zone.get_force_assets(struct.force_name, struct.zone.index)
|
|
zone_assets.rocket_landing_pad_names = zone_assets.rocket_landing_pad_names or {}
|
|
local zone_type_table = zone_assets.rocket_landing_pad_names
|
|
|
|
zone_type_table[struct.name] = zone_type_table[struct.name] or {}
|
|
zone_type_table[struct.name][struct.unit_number] = struct
|
|
end
|
|
|
|
function Landingpad.rename(struct, new_name)
|
|
local old_name = struct.name
|
|
Landingpad.remove_struct_from_tables(struct)
|
|
Landingpad.name(struct, new_name)
|
|
end
|
|
|
|
function Landingpad.dropdown_list_zone_landing_pad_names(force_name, zone, current)
|
|
local selected_index
|
|
local list = {} -- names with optional [count]
|
|
local values = {} -- raw names
|
|
table.insert(list, "None - General vicinity")
|
|
table.insert(values, "") -- not sure if nil would work
|
|
|
|
if zone and zone.type ~= "spaceship" then
|
|
local zone_assets = Zone.get_force_assets(force_name, zone.index)
|
|
for name, sites in pairs(zone_assets["rocket_landing_pad_names"]) do
|
|
local count = 0
|
|
for _, struct in pairs(sites) do
|
|
count = count + 1
|
|
end
|
|
if count == 1 then
|
|
table.insert(list, name)
|
|
table.insert(values, name)
|
|
if name == current then selected_index = #list end
|
|
elseif count > 1 then
|
|
table.insert(list, name .. " ["..count.."]")
|
|
table.insert(values, name)
|
|
if name == current then selected_index = #list end
|
|
end
|
|
end
|
|
end
|
|
return list, (selected_index or 1), values
|
|
end
|
|
|
|
function Landingpad.dropdown_list_force_landing_pad_names(force_name, current)
|
|
local selected_index
|
|
local list = {} -- names with optional [count]
|
|
local values = {} -- raw names
|
|
table.insert(list, "None - Cannot launch")
|
|
table.insert(values, "") -- not sure if nil would work
|
|
|
|
local force_data = global.forces[force_name]
|
|
if force_data.rocket_landing_pad_names then
|
|
for name, sites in pairs(force_data.rocket_landing_pad_names) do
|
|
local count = 0
|
|
for _, struct in pairs(sites) do
|
|
count = count + 1
|
|
end
|
|
if count == 1 then
|
|
table.insert(list, name)
|
|
table.insert(values, name)
|
|
if name == current then selected_index = #list end
|
|
elseif count > 1 then
|
|
table.insert(list, name .. " ["..count.."]")
|
|
table.insert(values, name)
|
|
if name == current then selected_index = #list end
|
|
end
|
|
end
|
|
end
|
|
return list, (selected_index or 1), values
|
|
end
|
|
|
|
function Landingpad.on_entity_removed(event)
|
|
local entity = event.entity
|
|
if entity and entity.valid and entity.name == Landingpad.name_rocket_landing_pad then
|
|
Landingpad.destroy(Landingpad.from_entity(entity))
|
|
end
|
|
end
|
|
Event.addListener(defines.events.on_entity_died, Landingpad.on_entity_removed)
|
|
Event.addListener(defines.events.on_robot_mined_entity, Landingpad.on_entity_removed)
|
|
Event.addListener(defines.events.on_player_mined_entity, Landingpad.on_entity_removed)
|
|
Event.addListener(defines.events.script_raised_destroy, Landingpad.on_entity_removed)
|
|
|
|
|
|
--- Handles the player creating a blueprint by setting tags to store the state of landing pads
|
|
---@param event any
|
|
function Landingpad.on_player_setup_blueprint(event)
|
|
local player_index = event.player_index
|
|
if player_index and game.players[player_index] and game.players[player_index].connected then
|
|
local player = game.players[player_index]
|
|
|
|
-- this setup code and checks is a workaround for the fact that the event doesn't specify the blueprint on the event
|
|
-- and the player.blueprint_to_setup isn't actually set in the case of copy/paste or blueprint library or select new contents
|
|
local blueprint = nil
|
|
if player and player.blueprint_to_setup and player.blueprint_to_setup.valid_for_read then blueprint = player.blueprint_to_setup
|
|
elseif player and player.cursor_stack.valid_for_read and player.cursor_stack.is_blueprint then blueprint = player.cursor_stack end
|
|
if blueprint and blueprint.is_blueprint_setup() then
|
|
|
|
|
|
local mapping = event.mapping.get()
|
|
local blueprint_entities = blueprint.get_blueprint_entities()
|
|
if blueprint_entities then
|
|
for _, blueprint_entity in pairs(blueprint_entities) do
|
|
if blueprint_entity.name == Landingpad.name_rocket_landing_pad then
|
|
local entity = mapping[blueprint_entity.entity_number]
|
|
if entity then
|
|
local landing_pad = Landingpad.from_entity(entity)
|
|
if landing_pad then
|
|
local tags = {}
|
|
tags.name = landing_pad.name
|
|
blueprint.set_blueprint_entity_tags(blueprint_entity.entity_number, tags)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
Event.addListener(defines.events.on_player_setup_blueprint, Landingpad.on_player_setup_blueprint)
|
|
|
|
--- Handles the player copy/pasting settings between landing pads
|
|
---@param event any
|
|
function Landingpad.on_entity_settings_pasted(event)
|
|
local player_index = event.player_index
|
|
if player_index and game.players[player_index] and game.players[player_index].connected
|
|
and event.source and event.source.valid and event.destination and event.destination.valid then
|
|
if not (event.source.name == Landingpad.name_rocket_landing_pad) then return end
|
|
if not (event.destination.name == Landingpad.name_rocket_landing_pad) then return end
|
|
local player = game.players[player_index]
|
|
local landing_pad_from = Landingpad.from_entity(event.source)
|
|
local landing_pad_to = Landingpad.from_entity(event.destination)
|
|
if landing_pad_from and landing_pad_to then
|
|
-- actual settings copy
|
|
Landingpad.rename(landing_pad_to, landing_pad_from.name)
|
|
end
|
|
end
|
|
end
|
|
Event.addListener(defines.events.on_entity_settings_pasted, Landingpad.on_entity_settings_pasted)
|
|
|
|
function Landingpad.on_init(event)
|
|
global.rocket_landing_pads = {} -- all landing pads sorted by struct[unit_unumber]
|
|
end
|
|
Event.addListener("on_init", Landingpad.on_init, true)
|
|
|
|
return Landingpad
|
|
|