Aleksei-bird 7c9c708c92 Первый фикс
Пачки некоторых позиций увеличены
2024-03-01 20:54:33 +03:00

197 lines
7.8 KiB
Lua

local matrix_engine = require("backend.calculation.matrix_engine")
-- ** LOCAL UTIL **
local function show_linearly_dependent_recipes(modal_data, recipe_protos)
local flow_recipes = modal_data.modal_elements.content_frame.add{type="flow", direction="vertical"}
local label_title = flow_recipes.add{type="label", caption={"fp.matrix_linearly_dependent_recipes"}}
label_title.style.font = "heading-2"
local frame_recipes = flow_recipes.add{type="frame", direction="horizontal", style="slot_button_deep_frame"}
local table_recipes = frame_recipes.add{type="table", column_count=8, style="filter_slot_table"}
for _, recipe_proto in ipairs(recipe_protos) do
table_recipes.add{type="sprite", sprite=recipe_proto.sprite, tooltip=recipe_proto.localised_name}
end
end
local function update_dialog_submit_button(modal_data, matrix_metadata)
local num_needed_free_items = matrix_metadata.num_rows - matrix_metadata.num_cols + #matrix_metadata.free_items
local curr_free_items = #modal_data["free_items"]
local message = nil
if num_needed_free_items > curr_free_items then
message = {"fp.matrix_constrained_items", num_needed_free_items, {"fp.pl_item", num_needed_free_items}}
end
modal_dialog.set_submit_button_state(modal_data.modal_elements, (message == nil), message)
end
local function refresh_item_category(modal_data, type)
local table_items = modal_data.modal_elements[type .. "_table"]
table_items.clear()
-- order items by the natural Factorio order
local display_order = {}
for index, proto in ipairs(modal_data[type .. "_items"]) do
display_order[index] = {
key = { proto.group.order, proto.subgroup.order, proto.order, proto.name, index },
index = index, proto = proto }
end
table.sort(display_order, function (item_1, item_2)
local key_1 = item_1.key
local key_2 = item_2.key
assert(#key_1 == #key_2)
for i = 1, #key_1 do
if key_1[i] ~= key_2[i] then
return key_1[i] < key_2[i]
end
end
return false -- identical items
end)
for _, item in pairs(display_order) do
local index = item.index
local proto = item.proto
local button = table_items.add{type="sprite-button", sprite=proto.sprite, tooltip=proto.localised_name,
tags={mod="fp", on_gui_click="swap_item_category", type=type, index=index}, style="flib_slot_button_default",
mouse_button_filter={"left"}}
button.style.size = 48
end
end
local function create_item_category(modal_data, type, label_arg)
local flow_category = modal_data.modal_elements.content_frame.add{type="flow", direction="vertical"}
local title_string = (type == "free") and {"fp.matrix_free_items"}
or {"fp.matrix_constrained_items", label_arg, {"fp.pl_item", label_arg}}
local label_title = flow_category.add{type="label", caption=title_string}
label_title.style.single_line = false
local frame_items = flow_category.add{type="frame", direction="horizontal", style="slot_button_deep_frame"}
local table_items = frame_items.add{type="table", column_count=8, style="filter_slot_table"}
modal_data.modal_elements[type .. "_table"] = table_items
refresh_item_category(modal_data, type)
end
local function swap_item_category(player, tags, _)
local ui_state = util.globals.ui_state(player)
local subfactory = ui_state.context.subfactory
local modal_data = ui_state.modal_data
-- update the free items here, set the constrained items based on linear dependence data
if tags.type == "free" then
-- note this assumes the gui's list has the same order as the subfactory
table.remove(subfactory.matrix_free_items, tags.index)
else -- "constrained"
local item_proto = modal_data["constrained_items"][tags.index]
table.insert(subfactory.matrix_free_items, item_proto)
end
local matrix_metadata = matrix_engine.get_matrix_solver_metadata(modal_data.subfactory_data)
local linear_dependence_data = matrix_engine.get_linear_dependence_data(modal_data.subfactory_data, matrix_metadata)
modal_data.constrained_items = linear_dependence_data.allowed_free_items
modal_data.free_items = matrix_metadata.free_items
refresh_item_category(modal_data, "constrained")
refresh_item_category(modal_data, "free")
update_dialog_submit_button(modal_data, matrix_metadata)
end
local function matrix_early_abort_check(player, modal_data)
local ui_state = util.globals.ui_state(player)
local subfactory = ui_state.context.subfactory
if subfactory.selected_floor.Line.count == 0 then return true end
local subfactory_data = solver.generate_subfactory_data(player, subfactory)
local matrix_metadata = matrix_engine.get_matrix_solver_metadata(subfactory_data)
modal_data.subfactory_data = subfactory_data
local linear_dependence_data = matrix_engine.get_linear_dependence_data(subfactory_data, matrix_metadata)
if next(linear_dependence_data.linearly_dependent_recipes) then -- too many ways to create the products
modal_data.linearly_dependent_recipes = linear_dependence_data.linearly_dependent_recipes
subfactory.linearly_dependant = true
return false
end
subfactory.linearly_dependant = false -- TODO not the proper way to signal this, but it works
modal_data.constrained_items = linear_dependence_data.allowed_free_items
modal_data.free_items = matrix_metadata.free_items
local num_needed_free_items = matrix_metadata.num_rows - matrix_metadata.num_cols + #matrix_metadata.free_items
if num_needed_free_items == 0 then -- User doesn't need to select any free items, just run the matrix solver
if modal_data.configuration then
util.messages.raise(player, "warning", {"fp.warning_no_matrix_configuration_needed"}, 1)
end
return true
end
-- If it gets to here, the dialog should open normally
modal_data.num_needed_free_items = num_needed_free_items
modal_data.matrix_metadata = matrix_metadata
return false
end
local function open_matrix_dialog(player, modal_data)
if util.globals.context(player).subfactory.linearly_dependant then
show_linearly_dependent_recipes(modal_data, modal_data.linearly_dependent_recipes)
modal_dialog.set_submit_button_state(modal_data.modal_elements, false, {"fp.matrix_linearly_dependent_recipes"})
-- Dispose of the temporary GUI-opening variables
modal_data.linearly_dependent_recipes = nil
else
create_item_category(modal_data, "constrained", modal_data.num_needed_free_items)
create_item_category(modal_data, "free")
update_dialog_submit_button(modal_data, modal_data.matrix_metadata)
-- Dispose of the temporary GUI-opening variables
modal_data.num_needed_free_items = nil
modal_data.matrix_metadata = nil
end
end
local function close_matrix_dialog(player, action)
if action == "submit" then
local ui_state = util.globals.ui_state(player)
local subfactory = ui_state.context.subfactory
subfactory.matrix_free_items = ui_state.modal_data.free_items
solver.update(player, subfactory)
util.raise.refresh(player, "subfactory", nil)
elseif action == "cancel" then
util.raise.refresh(player, "production_detail", nil)
end
end
-- ** EVENTS **
local listeners = {}
listeners.gui = {
on_gui_click = {
{
name = "swap_item_category",
handler = swap_item_category
}
}
}
listeners.dialog = {
dialog = "matrix",
metadata = (function(_) return {
caption = {"fp.matrix_solver"},
create_content_frame = true,
show_submit_button = true
} end),
early_abort_check = matrix_early_abort_check,
open = open_matrix_dialog,
close = close_matrix_dialog
}
return { listeners }