diff --git a/scripts/cargo-pods.lua b/scripts/cargo-pods.lua index 16eb4ee..db49695 100644 --- a/scripts/cargo-pods.lua +++ b/scripts/cargo-pods.lua @@ -1,19 +1,54 @@ local warn_color = { r = 255, g = 90, b = 54 } +-- 获取白名单物品列表 +local function get_whitelist_items(planet_name) + local whitelist = {} + local storage_lib = storage.planets_lib + local seen = {} + + -- 收集星球特定白名单 + if storage_lib.whitelisted_names and storage_lib.whitelisted_names[planet_name] then + for item_name in pairs(storage_lib.whitelisted_names[planet_name]) do + if not seen[item_name] then + seen[item_name] = true + table.insert(whitelist, item_name) + end + end + end + + -- 收集全局白名单 + if storage_lib.whitelisted_names_all_planets then + for item_name in pairs(storage_lib.whitelisted_names_all_planets) do + if not seen[item_name] then + seen[item_name] = true + table.insert(whitelist, item_name) + end + end + end + + return whitelist +end + +-- 格式化白名单显示文本(不换行,用间隔符分隔) +local function format_whitelist_text(whitelist_items) + if #whitelist_items == 0 then + return nil + end + local formatted = {} + for _, item_name in ipairs(whitelist_items) do + table.insert(formatted, "[item=" .. item_name .. "]") + end + return table.concat(formatted, "、") +end + local function init_storage() storage.planets_lib = storage.planets_lib or {} - storage.planets_lib.cargo_pods_seen_on_platforms = storage.planets_lib.cargo_pods_seen_on_platforms or {} storage.planets_lib.cargo_pod_canceled_whisper_ticks = storage.planets_lib.cargo_pod_canceled_whisper_ticks or {} end -script.on_init(function() - init_storage() -end) - -script.on_configuration_changed(function() - init_storage() -end) +script.on_init(init_storage) +script.on_configuration_changed(init_storage) local cargo_drops_technology_names = {} for _, planet in pairs(prototypes.space_location) do @@ -22,40 +57,27 @@ end local function pod_contents_is_allowed(pod_contents, planet_name) local whitelists = prototypes.mod_data.Planetslib.data.planet_cargo_drop_whitelists - - local old_whitelisted_names_all_planets = storage.planets_lib.whitelisted_names_all_planets or {} - local old_whitelisted_names = storage.planets_lib.whitelisted_names or {} - local old_whitelisted_types_all_planets = storage.planets_lib.whitelisted_types_all_planets or {} - local old_whitelisted_types = storage.planets_lib.whitelisted_types or {} + local old_names_all = storage.planets_lib.whitelisted_names_all_planets or {} + local old_names = storage.planets_lib.whitelisted_names or {} + local old_types_all = storage.planets_lib.whitelisted_types_all_planets or {} + local old_types = storage.planets_lib.whitelisted_types or {} for _, item in pairs(pod_contents) do local entity = prototypes.entity[item.name] - local whitelisted_by_item_name = whitelists.all.item_names[item.name] or (whitelists[planet_name] and whitelists[planet_name].item_names[item.name]) - local whitelisted_by_entity_type = entity - and ( - whitelists.all.entity_types[entity.type] - or (whitelists[planet_name] and whitelists[planet_name].entity_types[entity.type]) - ) + and (whitelists.all.entity_types[entity.type] + or (whitelists[planet_name] and whitelists[planet_name].entity_types[entity.type])) - -- Check the legacy whitelist: - local old_whitelist_condition = old_whitelisted_names_all_planets[item.name] - and not (old_whitelisted_names[planet_name] and old_whitelisted_names[planet_name][item.name]) - and not ( - entity - and ( - old_whitelisted_types_all_planets[entity.type] - or (old_whitelisted_types[planet_name] and old_whitelisted_types[planet_name][entity.type]) - ) - ) + local old_condition = old_names_all[item.name] + or (old_names[planet_name] and old_names[planet_name][item.name]) + or (entity and (old_types_all[entity.type] or (old_types[planet_name] and old_types[planet_name][entity.type]))) - if not whitelisted_by_item_name and not whitelisted_by_entity_type and not old_whitelist_condition then + if not whitelisted_by_item_name and not whitelisted_by_entity_type and not old_condition then return false end end - return true end @@ -64,7 +86,6 @@ local function destroy_pod_on_platform(pod, platform, planet_name) if hub and hub.valid then local pod_inventory = pod.get_inventory(defines.inventory.cargo_unit) local hub_inventory = hub.get_inventory(defines.inventory.hub_main) - if pod_inventory and hub_inventory then for _, item in pairs(pod_inventory.get_contents()) do hub_inventory.insert(item) @@ -72,63 +93,58 @@ local function destroy_pod_on_platform(pod, platform, planet_name) end end + -- 获取白名单展示 + local whitelist_items = get_whitelist_items(planet_name) + local formatted_whitelist = format_whitelist_text(whitelist_items) + local tech_name = "planetslib-" .. planet_name .. "-cargo-drops" + for _, player in pairs(game.connected_players) do - if - player.valid - and player.surface - and player.surface.valid - and player.surface.index == platform.surface.index - then + if player.valid and player.surface and player.surface.valid and player.surface.index == platform.surface.index then local whisper_hash = platform.index .. "-" .. player.name - local last_whisper_tick = storage.planets_lib.cargo_pod_canceled_whisper_ticks[whisper_hash] - if (not last_whisper_tick) or (game.tick - last_whisper_tick >= 60 * 10) then - player.print({ - "planetslib.cargo-pod-canceled", - "[space-platform=" .. platform.index .. "]", - "[technology=" .. "planetslib-" .. planet_name .. "-cargo-drops" .. "]", - }, { color = warn_color }) - + if formatted_whitelist then + player.print({ + "beomyo-string.string2", + "[space-platform=" .. platform.index .. "]", + "[technology=" .. tech_name .. "]", + formatted_whitelist + }, { color = warn_color }) + else + player.print({ + "beomyo-string.string3", + "[space-platform=" .. platform.index .. "]", + "[technology=" .. tech_name .. "]" + }, { color = warn_color }) + end storage.planets_lib.cargo_pod_canceled_whisper_ticks[whisper_hash] = game.tick end end end local pod_unit_number = pod.unit_number - pod.destroy() - storage.planets_lib.cargo_pods_seen_on_platforms[pod_unit_number] = nil end local function examine_cargo_pods(platform, planet_name) local cargo_pods = platform.surface.find_entities_filtered({ type = "cargo-pod" }) - - if #cargo_pods == 0 then - return - end - + if #cargo_pods == 0 then return end for _, pod in pairs(cargo_pods) do if pod and pod.valid and not storage.planets_lib.cargo_pods_seen_on_platforms[pod.unit_number] then local pod_contents = pod.get_inventory(defines.inventory.cargo_unit).get_contents() - local has_only_allowed_cargo = pod_contents_is_allowed(pod_contents, planet_name) - local nearby_hubs = platform.surface.find_entities_filtered({ name = { "space-platform-hub", "cargo-bay" }, position = pod.position, radius = 4, }) - local launched_from_platform = #nearby_hubs > 0 - storage.planets_lib.cargo_pods_seen_on_platforms[pod.unit_number] = { launched_from_platform = launched_from_platform, entity = pod, platform_index = platform.index, } - if launched_from_platform and not has_only_allowed_cargo then destroy_pod_on_platform(pod, platform, planet_name) end @@ -136,138 +152,68 @@ local function examine_cargo_pods(platform, planet_name) end end -script.on_event(defines.events.on_cargo_pod_started_ascending, function(event) - local cargo_pod = event.cargo_pod - if not (cargo_pod and cargo_pod.valid) then - return - end - - local surface = cargo_pod.surface - if not (surface and surface.valid) then - return - end - - local platform = surface.platform - if not (platform and platform.valid) then - return - end - - local planet_name = nil - if platform.space_location and platform.space_location.valid and platform.space_location.name then - planet_name = platform.space_location.name - end - - if not planet_name then - return - end - - local force = cargo_pod.force - if not (force and force.valid) then - return - end - - local cargo_drops_tech = force.technologies[cargo_drops_technology_names[planet_name]] - - if (not cargo_drops_tech) or cargo_drops_tech.researched then - return - end - - local has_nothing_effect = false - for _, effect in pairs(cargo_drops_tech.prototype.effects) do - if effect.type == "nothing" then - has_nothing_effect = true - break +script.on_nth_tick(20, function() + for _, force in pairs(game.forces) do + for _, platform in pairs(force.platforms) do + if platform and platform.valid and platform.surface and platform.surface.valid then + local planet_name = platform.space_location and platform.space_location.valid and platform.space_location.name or nil + if planet_name then + local cargo_drops_tech = force.technologies[cargo_drops_technology_names[planet_name]] + if cargo_drops_tech and not cargo_drops_tech.researched then + local has_nothing_effect = false + for _, effect in pairs(cargo_drops_tech.prototype.effects) do + if effect.type == "nothing" then + has_nothing_effect = true + break + end + end + if has_nothing_effect then + examine_cargo_pods(platform, planet_name) + end + end + end + end end end - - if not has_nothing_effect then - return - end - - examine_cargo_pods(platform, planet_name) end) --- Deprecated whitelist API, not sure if we'll ever remove it? +-- 兼容旧版白名单接口 remote.add_interface("planetslib", { add_to_cargo_drop_item_name_whitelist = function(name, planet_name) - if type(name) ~= "string" then - error("name must be a string") - end - + if type(name) ~= "string" then error("name must be a string") end + storage.planets_lib.whitelisted_names = storage.planets_lib.whitelisted_names or {} + storage.planets_lib.whitelisted_names_all_planets = storage.planets_lib.whitelisted_names_all_planets or {} if planet_name then - if not storage.planets_lib.whitelisted_names then - storage.planets_lib.whitelisted_names = {} - end - - if not storage.planets_lib.whitelisted_names[planet_name] then - storage.planets_lib.whitelisted_names[planet_name] = {} - end + storage.planets_lib.whitelisted_names[planet_name] = storage.planets_lib.whitelisted_names[planet_name] or {} storage.planets_lib.whitelisted_names[planet_name][name] = true else - if not storage.planets_lib.whitelisted_names_all_planets then - storage.planets_lib.whitelisted_names_all_planets = {} - end - storage.planets_lib.whitelisted_names_all_planets[name] = true end end, remove_from_cargo_drop_item_name_whitelist = function(name, planet_name) - if type(name) ~= "string" then - error("name must be a string") - end - if planet_name then - if not storage.planets_lib.whitelisted_names then - storage.planets_lib.whitelisted_names = {} - end - - if not storage.planets_lib.whitelisted_names[planet_name] then - storage.planets_lib.whitelisted_names[planet_name] = {} - end + if type(name) ~= "string" then error("name must be a string") end + if planet_name and storage.planets_lib.whitelisted_names and storage.planets_lib.whitelisted_names[planet_name] then storage.planets_lib.whitelisted_names[planet_name][name] = nil - else - if not storage.planets_lib.whitelisted_names_all_planets then - storage.planets_lib.whitelisted_names_all_planets = {} - end + elseif storage.planets_lib.whitelisted_names_all_planets then storage.planets_lib.whitelisted_names_all_planets[name] = nil end end, add_to_cargo_drop_item_type_whitelist = function(type_name, planet_name) - if type(type_name) ~= "string" then - error("type_name must be a string") - end + if type(type_name) ~= "string" then error("type_name must be a string") end + storage.planets_lib.whitelisted_types = storage.planets_lib.whitelisted_types or {} + storage.planets_lib.whitelisted_types_all_planets = storage.planets_lib.whitelisted_types_all_planets or {} if planet_name then - if not storage.planets_lib.whitelisted_types then - storage.planets_lib.whitelisted_types = {} - end - - if not storage.planets_lib.whitelisted_types[planet_name] then - storage.planets_lib.whitelisted_types[planet_name] = {} - end + storage.planets_lib.whitelisted_types[planet_name] = storage.planets_lib.whitelisted_types[planet_name] or {} storage.planets_lib.whitelisted_types[planet_name][type_name] = true else - if not storage.planets_lib.whitelisted_types_all_planets then - storage.planets_lib.whitelisted_types_all_planets = {} - end storage.planets_lib.whitelisted_types_all_planets[type_name] = true end end, remove_from_cargo_drop_item_type_whitelist = function(type_name, planet_name) - if type(type_name) ~= "string" then - error("type_name must be a string") - end - if planet_name then - if not storage.planets_lib.whitelisted_types then - storage.planets_lib.whitelisted_types = {} - end - - if not storage.planets_lib.whitelisted_types[planet_name] then - storage.planets_lib.whitelisted_types[planet_name] = {} - end + if type(type_name) ~= "string" then error("type_name must be a string") end + if planet_name and storage.planets_lib.whitelisted_types and storage.planets_lib.whitelisted_types[planet_name] then storage.planets_lib.whitelisted_types[planet_name][type_name] = nil - else - if not storage.planets_lib.whitelisted_types_all_planets then - storage.planets_lib.whitelisted_types_all_planets = {} - end + elseif storage.planets_lib.whitelisted_types_all_planets then storage.planets_lib.whitelisted_types_all_planets[type_name] = nil end end,