Files
factorio-scenario-ExpCluster/exp_legacy/module/modules/gui/module.lua
2024-11-19 22:16:34 +00:00

316 lines
10 KiB
Lua

---- module inserter
-- @gui Module
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local config = require("modules.exp_legacy.config.module") --- @dep config.module
local Selection = require("modules.exp_legacy.modules.control.selection") --- @dep modules.control.selection
local SelectionModuleArea = 'ModuleArea'
--- align an aabb to the grid by expanding it
local function aabb_align_expand(aabb)
return {
left_top = {
x = math.floor(aabb.left_top.x),
y = math.floor(aabb.left_top.y)
},
right_bottom = {
x = math.ceil(aabb.right_bottom.x),
y = math.ceil(aabb.right_bottom.y)
}
}
end
local module_container
local machine_name = {}
for k, _ in pairs(config.machine) do
table.insert(machine_name, k)
end
local prod_module_names = {}
local function get_module_name()
for name, item in pairs(prototypes.item) do
if item.module_effects and item.module_effects.productivity and item.module_effects.productivity > 0 then
prod_module_names[#prod_module_names + 1] = name
end
end
end
local elem_filter = {
name = {{
filter = 'name',
name = machine_name
}},
normal = {{
filter = 'type',
type = 'module'
}, {
filter = 'name',
name = prod_module_names,
mode = 'and',
invert = true
}},
prod = {{
filter = 'type',
type = 'module'
}}
}
local function clear_module(player, area, machine)
for _, entity in pairs(player.surface.find_entities_filtered{area=area, name=machine, force=player.force}) do
for _, r in pairs(player.surface.find_entities_filtered{position=entity.position, name='item-request-proxy', force=player.force}) do
if r then
r.destroy{raise_destroy=true}
end
end
local m_current_module = entity.get_module_inventory()
if m_current_module then
local m_current_module_content = m_current_module.get_contents()
if m_current_module_content then
for k, m in pairs(m_current_module_content) do
player.surface.spill_item_stack(entity.bounding_box.left_top, {name=k, count=m}, true, player.force, false)
end
end
m_current_module.clear()
end
end
end
local function apply_module(player, area, machine, modules)
for _, entity in pairs(player.surface.find_entities_filtered{area=area, name=machine, force=player.force}) do
local m_current_recipe
if entity.prototype.crafting_speed then
m_current_recipe= entity.get_recipe()
end
if m_current_recipe then
if config.module_allowed[m_current_recipe.name] then
entity.surface.create_entity{name='item-request-proxy', target=entity, position=entity.position, force=entity.force, modules=modules['n']}
entity.last_user = player
else
entity.surface.create_entity{name='item-request-proxy', target=entity, position=entity.position, force=entity.force, modules=modules['p']}
entity.last_user = player
end
else
entity.surface.create_entity{name='item-request-proxy', target=entity, position=entity.position, force=entity.force, modules=modules['n']}
entity.last_user = player
end
end
end
--- when an area is selected to add protection to the area
Selection.on_selection(SelectionModuleArea, function(event)
local area = aabb_align_expand(event.area)
local player = game.get_player(event.player_index)
local frame = Gui.get_left_element(player, module_container)
local scroll_table = frame.container.scroll.table
for i=1, config.default_module_row_count do
local mma = scroll_table['module_mm_' .. i .. '_0'].elem_value
if mma then
local mm = {
['n'] = {},
['p'] = {}
}
for j=1, prototypes.entity[mma].module_inventory_size, 1 do
local mmo = scroll_table['module_mm_' .. i .. '_' .. j].elem_value
if mmo then
if mm['n'][mmo] then
mm['n'][mmo] = mm['n'][mmo] + 1
mm['p'][mmo] = mm['p'][mmo] + 1
else
mm['n'][mmo] = 1
mm['p'][mmo] = 1
end
end
end
for k, v in pairs(mm['p']) do
if k:find('productivity') then
local module_name = k:gsub('productivity', 'effectivity')
mm['p'][module_name] = (mm['p'][module_name] or 0) + v
mm['p'][k] = nil
end
end
if mm then
clear_module(player, area, mma)
apply_module(player, area, mma, mm)
end
end
end
end)
local function row_set(player, element)
local frame = Gui.get_left_element(player, module_container)
local scroll_table = frame.container.scroll.table
if scroll_table[element .. '0'].elem_value then
for i=1, config.module_slot_max do
if i <= prototypes.entity[scroll_table[element .. '0'].elem_value].module_inventory_size then
if config.machine[scroll_table[element .. '0'].elem_value].prod then
scroll_table[element .. i].elem_filters = elem_filter.prod
else
scroll_table[element .. i].elem_filters = elem_filter.normal
end
scroll_table[element .. i].enabled = true
scroll_table[element .. i].elem_value = config.machine[scroll_table[element .. '0'].elem_value].module
else
scroll_table[element .. i].enabled = false
scroll_table[element .. i].elem_value = nil
end
end
else
local mf = elem_filter.normal
for i=1, config.module_slot_max do
scroll_table[element .. i].enabled = false
scroll_table[element .. i].elem_filters = mf
scroll_table[element .. i].elem_value = nil
end
end
end
local button_apply =
Gui.element{
type = 'button',
caption = 'Apply',
style = 'button'
}:on_click(function(player)
if Selection.is_selecting(player, SelectionModuleArea) then
Selection.stop(player)
else
Selection.start(player, SelectionModuleArea)
end
end)
module_container =
Gui.element(function(definition, parent)
local container = Gui.container(parent, definition.name, (config.module_slot_max + 2) * 36)
Gui.header(container, 'Module Inserter', '', true)
local scroll_table = Gui.scroll_table(container, (config.module_slot_max + 2) * 36, config.module_slot_max + 1)
for i=1, config.default_module_row_count do
scroll_table.add{
name = 'module_mm_' .. i .. '_0',
type = 'choose-elem-button',
elem_type = 'entity',
elem_filters = elem_filter.name,
style = 'slot_button'
}
for j=1, config.module_slot_max do
scroll_table.add{
name = 'module_mm_' .. i .. '_' .. j,
type = 'choose-elem-button',
elem_type = 'item',
elem_filters = elem_filter.normal,
style = 'slot_button',
enabled = false
}
end
end
button_apply(container)
return container.parent
end)
:static_name(Gui.unique_static_name)
:add_to_left_flow()
Gui.left_toolbar_button('item/productivity-module-3', {'module.main-tooltip'}, module_container, function(player)
return Roles.player_allowed(player, 'gui/module')
end)
Event.add(defines.events.on_gui_elem_changed, function(event)
if event.element.name:sub(1, 10) == 'module_mm_' then
if event.element.name:sub(-1) == '0' then
row_set(game.players[event.player_index], 'module_mm_' .. event.element.name:sub(-3):sub(1, 1) .. '_')
end
end
end)
Event.add(defines.events.on_player_joined_game, get_module_name)
Event.add(defines.events.on_entity_settings_pasted, function(event)
local source = event.source
local destination = event.destination
local player = game.players[event.player_index]
if not player then
return
end
if not source or not source.valid then
return
end
if not destination or not destination.valid then
return
end
-- rotate machine also
if config.copy_paste_rotation then
if (source.name == destination.name or source.prototype.fast_replaceable_group == destination.prototype.fast_replaceable_group) then
if source.supports_direction and destination.supports_direction and source.type ~= 'transport-belt' then
local destination_box = destination.bounding_box
local ltx = destination_box.left_top.x
local lty = destination_box.left_top.y
local rbx = destination_box.right_bottom.x
local rby = destination_box.right_bottom.y
local old_direction = destination.direction
destination.direction = source.direction
if ltx ~= destination_box.left_top.x or lty ~= destination_box.left_top.y or rbx ~= destination_box.right_bottom.x or rby ~= destination_box.right_bottom.y then
destination.direction = old_direction
end
end
end
end
if config.copy_paste_module then
if source.name ~= destination.name then
return
end
local source_inventory = source.get_module_inventory()
if not source_inventory then
return
end
local source_inventory_content = source_inventory.get_contents()
if not source_inventory_content then
return
end
clear_module(player, destination.bounding_box, destination.name)
if next(source_inventory_content) ~= nil then
apply_module(player, destination.bounding_box, destination.name, {['n']=source_inventory_content, ['p']=source_inventory_content})
end
end
end)