diff --git a/changelog.txt b/changelog.txt index 06439d0b9..27be70117 100644 --- a/changelog.txt +++ b/changelog.txt @@ -77,6 +77,7 @@ Date: 2025-08-23 - When selecting view on map with an outpost selected, the map view now centers on the outpost rather than the caravan. Resolves https://github.com/pyanodon/pybugreports/issues/1170 - Reduce actual vatbrain radius by one tile match visible vatbrain radius. See https://github.com/pyanodon/pybugreports/issues/1062 - Fix actual vatbrain radius being offset by one tile to the east and south. See https://github.com/pyanodon/pybugreports/issues/1062 + - Biofluid networks now support provider priority - Caravans: when selecting view on map with an outpost selected, the map view now centers on the outpost rather than the caravan. Resolves https://github.com/pyanodon/pybugreports/issues/1170 - Caravans: fixed that ESC/E wouldn't close a caravan menu when opened from a caravan outpost. - Caravans: fixed scroll pane overlapping buttons in outpost's caravan view diff --git a/scripts/biofluid/biofluid-gui.lua b/scripts/biofluid/biofluid-gui.lua index f519e2e9f..1d047d37d 100644 --- a/scripts/biofluid/biofluid-gui.lua +++ b/scripts/biofluid/biofluid-gui.lua @@ -9,7 +9,7 @@ py.on_event(defines.events.on_gui_opened, function(event) elseif connection_type == Biofluid.REQUESTER then Biofluid.build_requester_gui(entity, player) elseif connection_type == Biofluid.PROVIDER then - player.opened = nil + Biofluid.build_provider_gui(entity, player) end end) @@ -105,8 +105,8 @@ function Biofluid.build_bioport_gui(entity, player) anchor = { gui = defines.relative_gui_type.assembling_machine_gui, position = defines.relative_gui_position.right - } - } + } + } main_frame.style.width = 448 main_frame.style.vertically_stretchable = false main_frame.style.vertically_squashable = true @@ -246,7 +246,7 @@ function Biofluid.build_requester_gui(entity, player) type = "sprite-button", name = "py_change_priority_1", style = "py_schedule_move_button", tags = {unit_number = unit_number, up = false}, sprite = "down-white", hovered_sprite = "down-black", clicked_sprite = "down-black" - }.style.height = 35 + }.style.height = 35 local priority = config_flow.add {type = "textfield", name = "py_requester_priority_input", tags = tags} priority.numeric = true priority.allow_decimal = false @@ -257,7 +257,7 @@ function Biofluid.build_requester_gui(entity, player) type = "sprite-button", name = "py_change_priority_2", style = "py_schedule_move_button", tags = {unit_number = unit_number, up = true}, sprite = "up-white", hovered_sprite = "up-black", clicked_sprite = "up-black" - }.style.height = 35 + }.style.height = 35 content_flow.add {type = "line"} content_flow.add {type = "label", caption = {"gui.temperature-filter"}}.style.font = "default-semibold" @@ -283,14 +283,99 @@ function Biofluid.build_requester_gui(entity, player) Biofluid.update_requester_gui(player, main_frame) end +function Biofluid.build_provider_gui(entity, player) + if player.gui.screen.biofluid_provider_gui then player.gui.screen.biofluid_provider_gui.destroy() end + local unit_number = entity.unit_number + + local main_frame = player.gui.screen.add {type = "frame", name = "biofluid_provider_gui", caption = entity.prototype.localised_name, direction = "vertical"} + main_frame.auto_center = true + player.opened = main_frame + main_frame.style.width = 436 + local tags = {unit_number = unit_number} + main_frame.tags = tags + + local content_frame = main_frame.add {type = "frame", name = "content_frame", direction = "vertical", style = "inside_shallow_frame_with_padding"} + content_frame.style.vertically_stretchable = true + local content_flow = content_frame.add {type = "flow", name = "content_flow", direction = "vertical"} + content_flow.style.vertical_spacing = 8 + content_flow.style.margin = {-4, 0, -4, 0} + content_flow.style.vertical_align = "center" + + local status_flow = content_flow.add {type = "flow", name = "status_flow", direction = "horizontal"} + status_flow.style.vertical_align = "center" + local status_sprite = status_flow.add {type = "sprite", name = "status_sprite"} + status_sprite.resize_to_sprite = false + status_sprite.style.size = {16, 16} + status_flow.add {type = "label", name = "status_text"} + status_flow.add {type = "empty-widget", style = "py_empty_widget"} + + local camera_frame = content_flow.add {type = "frame", name = "camera_frame", style = "py_nice_frame"} + local camera = camera_frame.add {type = "camera", name = "camera", position = entity.position, style = "py_caravan_camera", surface_index = entity.surface.index} + camera.visible = true + camera.style.height = 155 + camera.zoom = 2 + + local label_flow = content_flow.add {type = "flow", direction = "horizontal"} + label_flow.add {type = "label", caption = {"gui.priority"}}.style.font = "default-semibold" + + local config_flow = content_flow.add {type = "flow", direction = "horizontal", name = "config_flow"} + config_flow.add { + type = "sprite-button", name = "py_change_priority_1", style = "py_schedule_move_button", + tags = {unit_number = unit_number, up = false}, + sprite = "down-white", hovered_sprite = "down-black", clicked_sprite = "down-black" + }.style.height = 35 + local priority = config_flow.add {type = "textfield", name = "py_provider_priority_input", tags = tags} + priority.numeric = true + priority.allow_decimal = false + priority.allow_negative = false + priority.style.width = 55 + priority.style.height = 35 + config_flow.add { + type = "sprite-button", name = "py_change_priority_2", style = "py_schedule_move_button", + tags = {unit_number = unit_number, up = true}, + sprite = "up-white", hovered_sprite = "up-black", clicked_sprite = "up-black" + }.style.height = 35 + + Biofluid.update_provider_gui(player, main_frame) +end + +function Biofluid.update_provider_gui(player, gui) + local unit_number = gui.tags.unit_number + local provider_data = storage.biofluid_providers[unit_number] + if not provider_data then + player.opened = nil; return + end + local entity = provider_data.entity + if not entity or not entity.valid then + player.opened = nil; return + end + local network = storage.biofluid_networks[provider_data.network_id] + if not network then + player.opened = nil; return + end + + local status = "entity-status.working" + if not next(network.biofluid_bioports) then status = "entity-status.no-biofluid-network" end + local img = Biofluid.failure_reasons[status] + local content_flow = gui.content_frame.content_flow + content_flow.status_flow.status_text.caption = {status} + content_flow.status_flow.status_sprite.sprite = img + + local config_flow = content_flow.config_flow + config_flow.py_provider_priority_input.text = tostring(provider_data.priority) +end + py.on_event({defines.events.on_gui_closed, defines.events.on_player_changed_surface}, function(event) local player = game.get_player(event.player_index) --[[@as LuaPlayer]] if event.gui_type == defines.gui_type.entity then local gui = player.gui.relative.bioport_gui if gui then gui.destroy() end elseif event.gui_type == defines.gui_type.custom then - local gui = player.gui.screen.biofluid_requester_gui - if gui then gui.destroy() end + local requester_gui = player.gui.screen.biofluid_requester_gui + if requester_gui then requester_gui.destroy() end + + local provider_gui = player.gui.screen.biofluid_provider_gui + if provider_gui then provider_gui.destroy() end end end) @@ -348,11 +433,18 @@ end gui_events[defines.events.on_gui_click]["py_change_priority_."] = function(event) local element = event.element local unit_number = element.tags.unit_number + local requester_data = storage.biofluid_requesters[unit_number] - if not requester_data then return end - local change = element.tags.up and 1 or -1 - requester_data.priority = requester_data.priority + change - element.parent.py_requester_priority_input.text = tostring(requester_data.priority) + local provider_data = storage.biofluid_providers[unit_number] + if requester_data then + local change = element.tags.up and 1 or -1 + requester_data.priority = requester_data.priority + change + element.parent.py_requester_priority_input.text = tostring(requester_data.priority) + elseif provider_data then + local change = element.tags.up and 1 or -1 + provider_data.priority = provider_data.priority + change + element.parent.py_provider_priority_input.text = tostring(provider_data.priority) + end end gui_events[defines.events.on_gui_text_changed]["py_requester_priority_input"] = function(event) @@ -363,6 +455,14 @@ gui_events[defines.events.on_gui_text_changed]["py_requester_priority_input"] = requester_data.priority = tonumber(element.text) or 0 end +gui_events[defines.events.on_gui_text_changed]["py_provider_priority_input"] = function(event) + local element = event.element + local unit_number = element.tags.unit_number + local provider_data = storage.biofluid_providers[unit_number] + if not provider_data then return end + provider_data.priority = tonumber(element.text) or 0 +end + gui_events[defines.events.on_gui_switch_state_changed]["py_biofluid_temperature_switch"] = function(event) local element = event.element local unit_number = element.tags.unit_number diff --git a/scripts/biofluid/biofluid.lua b/scripts/biofluid/biofluid.lua index e6af265a7..63d8f598c 100644 --- a/scripts/biofluid/biofluid.lua +++ b/scripts/biofluid/biofluid.lua @@ -60,7 +60,7 @@ local function migrate_network_data(fluids) force = entity.force_index, stack = {name = entity.name, count = 1}, marked_for_deconstruction = true - } + } storage.biofluid_robots[k] = nil num_migrated = num_migrated + 1 @@ -78,12 +78,15 @@ local function migrate_network_data(fluids) end if num_migrated ~= 0 then - local fluids_deleted = serpent.block(fluids_deleted):gsub("\"] = \"", " used to be => \""):gsub("%[\"", "biofluid robot at ") - local fluids_deleted_full = serpent.block(fluids_deleted_full):gsub("\"] = \"", " used to be => \""):gsub("%[\"", "biofluid robot at ") + local fluids_deleted = serpent.block(fluids_deleted):gsub("\"] = \"", " used to be => \""):gsub("%[\"", + "biofluid robot at ") + local fluids_deleted_full = serpent.block(fluids_deleted_full):gsub("\"] = \"", " used to be => \""):gsub("%[\"", + "biofluid robot at ") game.print {"messages.warning-biofluid-migration", num_migrated, fluids_deleted} if num_migrated > MAX_MESSAGE_SIZE then - game.print("\t... " .. (num_migrated - MAX_MESSAGE_SIZE) .. " more not shown. Check factorio-current.log for full list.") + game.print("\t... " .. + (num_migrated - MAX_MESSAGE_SIZE) .. " more not shown. Check factorio-current.log for full list.") log "FULL LIST: " log {"messages.warning-biofluid-migration", num_migrated, fluids_deleted_full} end @@ -112,7 +115,7 @@ py.on_event(py.events.on_built(), function(event) entity.custom_status = { diode = defines.entity_status_diode.green, label = {"entity-status.working"}, - } + } local unit_number = entity.unit_number if connection_type == Biofluid.REQUESTER then local tags = event.tags or {} @@ -125,7 +128,7 @@ py.on_event(py.events.on_built(), function(event) target_temperature = tags.target_temperature or 15, temperature_operator = tags.temperature_operator or 1, priority = tags.priority or 0 - } + } elseif connection_type == Biofluid.ROBOPORT then storage.biofluid_bioports[unit_number] = { entity = entity, @@ -140,7 +143,11 @@ py.on_event(py.events.on_built(), function(event) elseif entity.type == "pipe-to-ground" then entity.operable = false elseif connection_type == Biofluid.PROVIDER then - storage.biofluid_providers[unit_number] = {entity = entity} + local tags = event.tags or {} + storage.biofluid_providers[unit_number] = { + entity = entity, + priority = tags.priority or 0 + } end ::continue:: @@ -172,7 +179,8 @@ function Biofluid.built_pipe() for _, network in pairs(storage.biofluid_networks) do for provider_unit_number, amount in pairs(network.allocated_fluids_from_providers or {}) do - allocated_fluids_from_providers[provider_unit_number] = amount + (allocated_fluids_from_providers[provider_unit_number] or 0) + allocated_fluids_from_providers[provider_unit_number] = amount + + (allocated_fluids_from_providers[provider_unit_number] or 0) end end @@ -194,7 +202,7 @@ function Biofluid.built_pipe() biofluid_requesters = {}, biofluid_providers = {}, allocated_fluids_from_providers = {}, - } + } networks[network_id] = network network[biofluid_connectable_name][unit_number] = true if allocated_fluids_from_providers[unit_number] then @@ -231,7 +239,7 @@ function Biofluid.update_bioport_animation(bioport_data) target = entity, surface = entity.surface, animation_speed = creature_name == "chorkok" and 0.25 or 0.5 - }.id + }.id end end end @@ -260,12 +268,22 @@ end local allocated_fluids_from_providers local function provider_sort_function(entity_a, entity_b) local a = entity_a.fluidbox[1] + local priority_a = storage.biofluid_providers[entity_a.unit_number].priority if not a then a = 0 else a = a.amount end a = a - (allocated_fluids_from_providers[entity_a.unit_number] or 0) + local b = entity_b.fluidbox[1] + local priority_b = storage.biofluid_providers[entity_b.unit_number].priority if not b then b = 0 else b = b.amount end b = b - (allocated_fluids_from_providers[entity_b.unit_number] or 0) - return a > b + + if (priority_a > priority_b) then + return true + elseif (priority_a < priority_b) then + return false + else + return a > b + end end @@ -327,6 +345,7 @@ local function build_providers_by_contents(network_data, relavant_fluids) if not provider_data then goto continue end local provider = provider_data.entity if not provider.valid then goto continue end + local provider_priority = provider_data.priority local contents = provider.fluidbox[1] if not contents then goto continue end @@ -455,9 +474,9 @@ local function set_target(biorobot_data, target) low_priority = true, allow_paths_through_own_entities = true, allow_destroy_friendly_entities = true, - }, + }, distraction = defines.distraction.none - } + } end function Biofluid.start_journey(unfulfilled_request, provider, bioport_data) @@ -486,7 +505,7 @@ function Biofluid.start_journey(unfulfilled_request, provider, bioport_data) position = position, create_build_effect_smoke = false, direction = floor((atan2(position[2] - provider_position.y, position[1] - provider_position.x) / pi - 0.5) / 2 % 1 * 8) - } + } local biorobot_data = { entity = robot, status = PICKING_UP, @@ -497,7 +516,7 @@ function Biofluid.start_journey(unfulfilled_request, provider, bioport_data) delivery_amount = delivery_amount, name = unfulfilled_request.name, network_id = bioport_data.network_id - } + } set_target(biorobot_data, provider.position) storage.biofluid_robots[robot.unit_number] = biorobot_data Biofluid.update_bioport_animation(bioport_data) @@ -569,7 +588,7 @@ local function make_homeless(biorobot_data) surface = biorobot_data.entity.surface, x_scale = 0.4, y_scale = 0.4 - } + } end local function find_new_home(biorobot_data, network_data) @@ -676,7 +695,7 @@ local function pickup(biorobot_data) only_in_alt_mode = true, x_scale = 0.5, y_scale = 0.5, - }.id + }.id biorobot_data.alt_mode_sprite = rendering.draw_sprite { sprite = "fluid/" .. name, target = entity, @@ -684,7 +703,7 @@ local function pickup(biorobot_data) only_in_alt_mode = true, x_scale = 0.8, y_scale = 0.8, - }.id + }.id end local function dropoff(biorobot_data) @@ -703,7 +722,7 @@ local function dropoff(biorobot_data) name = name, amount = contents.amount + amount, temperature = combine_tempatures(contents.amount, contents.temperature, amount, temperature) - } + } elseif amount > 0 then requester.fluidbox[2] = {name = name, amount = amount, temperature = temperature} end @@ -798,7 +817,7 @@ function Biofluid.get_unfulfilled_requests() entity = requester, priority = requester_data.priority, network_id = network_id - } + } if requester_data.care_about_temperature then result[#result].target_temperature = requester_data.target_temperature result[#result].temperature_operator = requester_data.temperature_operator @@ -888,7 +907,7 @@ py.on_event(defines.events.on_player_setup_blueprint, function(event) target_temperature = requester_data.target_temperature, temperature_operator = requester_data.temperature_operator, priority = requester_data.priority - }) + }) end end end) @@ -961,7 +980,7 @@ py.on_event(defines.events.on_selected_entity_changed, function(event) entity.custom_status = { diode = Biofluid.diode_colors[Biofluid.failure_reasons[entity_status]], label = {entity_status}, - } + } end end)