Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Another batch of caravan bugfixes #303

Merged
merged 8 commits into from
Mar 25, 2025
6 changes: 6 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ Version: 3.0.42
Date: ???
Changes:
- Add missing migration for new soot
- Fixed actions being incorrect size in interrupt target gui
- Fixed caravan status indicator being slightly misaligned
- Fixed incorrect self-interrupt behaviour due to accidentally deleted code
- Fixed caravans incorrectly evaluating some interrupt conditions. Resolves https://github.com/pyanodon/pybugreports/issues/914 and https://github.com/pyanodon/pybugreports/issues/905
- Fixed a crash when deleting interrupts in multiplayer. Resolves https://github.com/pyanodon/pybugreports/issues/909
- Fixed a crash when adding schedule to nuclear caravans. Resolves https://github.com/pyanodon/pybugreports/issues/924
---------------------------------------------------------------------------------------------------
Version: 3.0.41
Date: 2025-3-7
Expand Down
36 changes: 24 additions & 12 deletions scripts/caravan/caravan-gui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,25 @@ end
---@param actions CaravanAction[]
---@param caravan_data Caravan
---@param i integer
---@param action_list_type CaravanActionListType
function Caravan.build_action_list_gui(gui, actions, caravan_data, i, action_list_type, interrupt_name)
---@param interrupt_name string
function Caravan.build_action_list_gui(gui, actions, caravan_data, i, interrupt_name)
local unit_number = caravan_data.unit_number
local action_list_type = gui.tags.action_list_type
assert(action_list_type)
for j, action in ipairs(actions) do
local tags = {unit_number = unit_number, action_list_type = action_list_type, schedule_id = i, action_id = j, interrupt_name = interrupt_name}

local action_frame = gui.add {type = "frame", style = "train_schedule_condition_frame"}
action_frame.style.height = 36
action_frame.style.right_padding = 12
action_frame.style.left_margin = 32

-- Factorio mod gui is overcomplicated, hardcoded values is the only solution i found that actually works
action_frame.style.width = interrupt_name and 392 or 392 - 28
if action_list_type == Caravan.action_list_types.standard_schedule or action_list_type == Caravan.action_list_types.interrupt_targets then
action_frame.style.width = 392 - 28
else
action_frame.style.width = 392
end

if action_list_type ~= Caravan.action_list_types.interrupt_condition then
local playbutton = action_frame.add {type = "sprite-button", name = "py_action_play", tags = tags}
Expand Down Expand Up @@ -234,6 +241,7 @@ function Caravan.build_schedule_list_gui(gui, caravan_data, interrupt_data)
local prototype = caravan_prototypes[caravan_data.entity.name]
if interrupt_data then assert(interrupt_data.schedule) end
local schedule = interrupt_data and interrupt_data.schedule or caravan_data.schedule
local action_list_type = gui.tags.action_list_type

local tags = {unit_number = unit_number, action_list_type = action_list_type}
if interrupt_data then
Expand All @@ -246,7 +254,7 @@ function Caravan.build_schedule_list_gui(gui, caravan_data, interrupt_data)
for i, schedule in ipairs(schedule) do
tags.schedule_id = i

local schedule_flow = gui.add {type = "flow", direction = "vertical", name}
local schedule_flow = gui.add {type = "flow", direction = "vertical", tags = {action_list_type = action_list_type}}
schedule_flow.style.horizontal_align = "right"
schedule_flow.style.vertically_stretchable = false

Expand Down Expand Up @@ -299,7 +307,7 @@ function Caravan.build_schedule_list_gui(gui, caravan_data, interrupt_data)
}
end

Caravan.build_action_list_gui(schedule_flow, schedule.actions, caravan_data, i, tags.action_list_type, tags.interrupt_name)
Caravan.build_action_list_gui(schedule_flow, schedule.actions, caravan_data, i, tags.interrupt_name)

local entity = schedule.entity
local valid_actions = Caravan.get_valid_actions_for_entity(caravan_data, entity)
Expand Down Expand Up @@ -470,9 +478,8 @@ function Caravan.build_gui(player, entity, from_remote_manager)
-- open_map_button.style.size = {26, 26}

local status_flow = content_flow.add {type = "flow", name = "status_flow", direction = "horizontal"}
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.style.vertical_align = "center"
local status_sprite = status_flow.add {type = "sprite", name = "status_sprite", style = "status_image"}
status_flow.add {type = "label", name = "status_text"}

local camera_frame = content_flow.add {type = "frame", name = "camera_frame", style = "py_nice_frame"}
Expand Down Expand Up @@ -505,7 +512,9 @@ function Caravan.build_gui(player, entity, from_remote_manager)
local schedule_frame = content_flow.add {type = "frame", name = "schedule_frame", direction = "vertical", style = "py_nice_frame"}
schedule_frame.style.vertically_stretchable = true

local schedule_pane = schedule_frame.add {type = "scroll-pane", name = "schedule_pane", style = "py_schedule_scroll_pane"}
local schedule_pane = schedule_frame.add {type = "scroll-pane", name = "schedule_pane", style = "py_schedule_scroll_pane",
tags = {action_list_type = Caravan.action_list_types.standard_schedule}
}
schedule_pane.horizontal_scroll_policy = "never"
schedule_pane.vertical_scroll_policy = "auto-and-reserve-space"
schedule_pane.style.horizontally_stretchable = true
Expand Down Expand Up @@ -693,7 +702,9 @@ function Caravan.build_interrupt_gui(player, caravan_data, interrupt_name)

local conditions_scroll_pane_frame = window_frame.add {type = "frame", name = "conditions_scroll_pane_frame", direction = "vertical", style = "py_nice_frame"}
conditions_scroll_pane_frame.style.vertically_stretchable = true
local conditions_scroll_pane = conditions_scroll_pane_frame.add {type = "scroll-pane", style = "py_schedule_scroll_pane"}
local conditions_scroll_pane = conditions_scroll_pane_frame.add {type = "scroll-pane", style = "py_schedule_scroll_pane",
tags = {action_list_type = Caravan.action_list_types.interrupt_condition}
}
conditions_scroll_pane.horizontal_scroll_policy = "never"
conditions_scroll_pane.vertical_scroll_policy = "auto-and-reserve-space"
conditions_scroll_pane.style.horizontally_stretchable = true
Expand All @@ -706,7 +717,6 @@ function Caravan.build_interrupt_gui(player, caravan_data, interrupt_name)
interrupt_data.conditions,
caravan_data,
nil,
Caravan.action_list_types.interrupt_condition,
interrupt_data.name
)

Expand All @@ -724,7 +734,9 @@ function Caravan.build_interrupt_gui(player, caravan_data, interrupt_name)

local targets_scroll_pane_frame = window_frame.add {type = "frame", name = "targets_scroll_pane_frame", direction = "vertical", style = "py_nice_frame"}
targets_scroll_pane_frame.style.vertically_stretchable = true
local targets_scroll_pane = targets_scroll_pane_frame.add {name = "targets_scroll_pane", type = "scroll-pane", style = "py_schedule_scroll_pane"}
local targets_scroll_pane = targets_scroll_pane_frame.add {name = "targets_scroll_pane", type = "scroll-pane", style = "py_schedule_scroll_pane",
tags = {action_list_type = Caravan.action_list_types.interrupt_targets}
}
targets_scroll_pane.horizontal_scroll_policy = "never"
targets_scroll_pane.vertical_scroll_policy = "auto-and-reserve-space"
targets_scroll_pane.style.horizontally_stretchable = true
Expand Down
6 changes: 2 additions & 4 deletions scripts/caravan/caravan-prototypes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ Caravan.valid_actions = {
}
}
Caravan.valid_actions.nukavan = table.deepcopy(Caravan.valid_actions.caravan)
Caravan.valid_actions.nukavan["default"] = {"detonate"}
Caravan.valid_actions.nukavan["default"] = table.invert{"detonate"}

Caravan.foods = {
all = {
Expand Down Expand Up @@ -173,9 +173,7 @@ local caravan_prototypes = {
["workers-food-02"] = 30,
["workers-food-03"] = 50
},
actions = {
["default"] = {"detonate"}
},
actions = Caravan.valid_actions.nukavan,
placeable_by = "nukavan",
map_tag = {
type = "virtual",
Expand Down
55 changes: 32 additions & 23 deletions scripts/caravan/caravan.lua
Original file line number Diff line number Diff line change
Expand Up @@ -503,9 +503,11 @@ gui_events[defines.events.on_gui_click]["py_delete_interrupt_button"] = function
storage.interrupts[element.tags.interrupt_name] = nil
for _, player in pairs(game.players) do
local gui = Caravan.get_interrupt_gui(player)
if gui.tags.interrupt_name == element.tags.interrupt_name then
gui.destroy()
Caravan.update_gui(Caravan.get_caravan_gui(player))
if gui then
if gui.tags.interrupt_name == element.tags.interrupt_name then
gui.destroy()
Caravan.update_gui(Caravan.get_caravan_gui(player))
end
end
end
else
Expand Down Expand Up @@ -986,31 +988,26 @@ local function advance_caravan_schedule_by_1(caravan_data)
local schedule = caravan_data.schedule[caravan_data.schedule_id]
assert(schedule)

if schedule.temporary then
table.remove(caravan_data.schedule, caravan_data.schedule_id)
if #caravan_data.schedule == 0 then
caravan_data.schedule_id = -1
else
caravan_data.schedule_id = caravan_data.schedule_id - 1
end
end

local existing_interrupt_name
local is_interrupted = false
for _, sch in pairs(caravan_data.schedule) do
if sch.temporary then
is_interrupted = true
break
if sch ~= schedule then -- It is about to be deleted, so dont count it
is_interrupted = true
existing_interrupt_name = sch.temporary.interrupt_name
break
end
end
end

for _, interrupt in pairs(caravan_data.interrupts) do
local passed_index
for idx, interrupt in pairs(caravan_data.interrupts) do
interrupt = storage.interrupts[interrupt]
if not interrupt then goto continue end

local b = interrupt.inside_interrupt
if is_interrupted and not b then goto continue end
if is_interrupted and b and existing_interrupt_name == interrupt.name then goto continue end
local inside = interrupt.inside_interrupt
if is_interrupted and not inside then goto continue end
if is_interrupted and inside and existing_interrupt_name == interrupt.name then goto continue end

local conditions_passed = true
for _, condition in pairs(interrupt.conditions) do
Expand All @@ -1021,16 +1018,28 @@ local function advance_caravan_schedule_by_1(caravan_data)
end
end
if conditions_passed then
if interrupt.inside_interrupt then
remove_tmp_stops(caravan_data)
end
add_interrupt(caravan_data, interrupt)
is_interrupted = true
passed_index = idx
is_interrupted = true -- Pretend the interrupt succeded but dont add it to the schedule yet
end

::continue::
end

if passed_index then
local interrupt = storage.interrupts[caravan_data.interrupts[passed_index]]
remove_tmp_stops(caravan_data)
add_interrupt(caravan_data, interrupt)
else
if schedule.temporary then
table.remove(caravan_data.schedule, caravan_data.schedule_id)
if #caravan_data.schedule == 0 then
caravan_data.schedule_id = -1
else
caravan_data.schedule_id = caravan_data.schedule_id - 1
end
end
end

begin_schedule(caravan_data, caravan_data.schedule_id % #caravan_data.schedule + 1, #caravan_data.schedule == 1)
end

Expand Down