Files
factorio-scenario-ExpCluster/modules/gui/vlayer.lua
PHIDIAS 46f6215d94 Feature Update (#237)
See PR for details, there are too many to be included here.
2023-08-15 18:47:34 +01:00

277 lines
10 KiB
Lua

--- Adds a virtual layer to store power to save space.
-- @addon Virtual Layer
local Gui = require 'expcore.gui' --- @dep expcore.gui
local Roles = require 'expcore.roles' --- @dep expcore.roles
local Event = require 'utils.event' --- @dep utils.event
local config = require 'config.vlayer' --- @dep config.vlayer
local format_number = require('util').format_number
local vlayer = require 'modules.control.vlayer'
local vlayer_container
local vlayer_display = {}
local function pos_to_gps_string(pos)
return '[gps=' .. tostring(pos.x) .. ',' .. tostring(pos.y) .. ']'
end
for i=1, #config.gui.content do
if config.gui.content[i].type == 'item' or config.gui.content[i].type == 'signal' then
vlayer_display[i] = {
type = config.gui.content[i].type,
name = config.gui.content[i].name,
count = 0
}
end
end
local function vlayer_convert_chest(player)
local entities = player.surface.find_entities_filtered{position=player.position, radius=8, name='steel-chest', force=player.force}
if (not entities or (#entities == 0)) then
return nil
end
local target_chest = player.surface.get_closest(player.position, entities)
if (not target_chest) then
player.print('No Steel Chest Detected')
return nil
end
if (not target_chest.get_inventory(defines.inventory.chest).is_empty()) then
player.print('Chest is not emptied')
return nil
end
local pos = target_chest.position
if (not target_chest.destroy()) then
player.print('Unable to convert chest')
return nil
end
return {x=math.floor(pos.x), y=math.floor(pos.y)}
end
local function vlayer_convert_chest_storage_input(player)
local pos = vlayer_convert_chest(player)
if (pos) then
local vlayer_storage = player.surface.create_entity{name='logistic-chest-storage', position=pos, force='neutral'}
game.print(player.name .. ' built a vlayer input on ' .. pos_to_gps_string(pos))
vlayer_storage.destructible = false
vlayer_storage.minable = false
vlayer_storage.operable = true
vlayer_storage.last_user = player
table.insert(vlayer.storage.input, vlayer_storage)
end
end
local function vlayer_convert_chest_power(player)
local pos = vlayer_convert_chest(player)
if (pos) then
if (player.surface.can_place_entity{name='electric-energy-interface', position=pos})then
local vlayer_power = player.surface.create_entity{name='electric-energy-interface', position=pos, force='neutral'}
game.print(player.name .. ' built a vlayer energy interface on ' .. pos_to_gps_string(pos))
vlayer_power.destructible = false
vlayer_power.minable = false
vlayer_power.operable = false
vlayer_power.last_user = player
vlayer_power.electric_buffer_size = math.floor(config.energy_base_limit / 2)
vlayer_power.power_production = math.floor(config.energy_base_limit / 60)
vlayer_power.power_usage = math.floor(config.energy_base_limit / 60)
vlayer_power.energy = 0
table.insert(vlayer.power.entity, vlayer_power)
else
player.print('Unable to build energy entity')
end
end
end
local function vlayer_convert_chest_circuit(player)
local pos = vlayer_convert_chest(player)
if (pos) then
local circuit_o = player.surface.create_entity{name='constant-combinator', position=pos, force='neutral'}
circuit_o.destructible = false
circuit_o.minable = false
circuit_o.operable = true
circuit_o.last_user = player
local circuit_oc = circuit_o.get_or_create_control_behavior()
circuit_oc.set_signal(1, {signal={type='virtual', name='signal-P'}, count=0})
circuit_oc.set_signal(2, {signal={type='virtual', name='signal-S'}, count=0})
circuit_oc.set_signal(3, {signal={type='virtual', name='signal-M'}, count=0})
circuit_oc.set_signal(4, {signal={type='virtual', name='signal-C'}, count=0})
circuit_oc.set_signal(5, {signal={type='virtual', name='signal-D'}, count=0})
circuit_oc.set_signal(6, {signal={type='virtual', name='signal-T'}, count=0})
circuit_oc.set_signal(7, {signal={type='virtual', name='signal-L'}, count=0})
circuit_oc.set_signal(8, {signal={type='virtual', name='signal-A'}, count=0})
circuit_oc.set_signal(9, {signal={type='virtual', name='signal-B'}, count=0})
circuit_oc.set_signal(10, {signal={type='item', name='solar-panel'}, count=0})
circuit_oc.set_signal(11, {signal={type='item', name='accumulator'}, count=0})
table.insert(vlayer.power.circuit, circuit_o)
game.print(player.name .. ' built a vlayer circuit on ' .. pos_to_gps_string(pos))
end
end
local function vlayer_convert_remove(player)
local entities = player.surface.find_entities_filtered{name={'logistic-chest-storage', 'constant-combinator', 'electric-energy-interface'}, position=player.position, radius=8, force='neutral', limit=1}
if (not entities or #entities == 0) then
player.print('Entity not found')
else
for _, v in pairs(entities) do
local name = v.name
game.print(player.name .. ' removed a vlayer ' .. config.print_out[v.name] .. ' on ' .. pos_to_gps_string(v.position))
v.destroy()
if name == 'logistic-chest-storage' then
for k, vl in pairs(vlayer.storage.input) do
if not vl.valid then
vlayer.storage.input[k] = nil
end
end
elseif name == 'constant-combinator' then
for k, vl in pairs(vlayer.power.circuit) do
if not vl.valid then
vlayer.power.circuit[k] = nil
end
end
elseif name == 'electric-energy-interface' then
for k, vl in pairs(vlayer.power.entity) do
if not vl.valid then
vlayer.power.entity[k] = nil
end
end
end
end
end
end
local vlayer_gui_update
local button_power =
Gui.element{
name = 'button_1',
type = 'button',
caption = 'Power Entity',
style = 'button'
}:on_click(function(player)
vlayer_convert_chest_power(player)
vlayer_gui_update()
end)
local button_storage_input =
Gui.element{
name = 'button_2',
type = 'button',
caption = 'Storage Input',
style = 'button'
}:on_click(function(player)
vlayer_convert_chest_storage_input(player)
vlayer_gui_update()
end)
local button_circuit =
Gui.element{
name = 'button_3',
type = 'button',
caption = 'Circuit',
style = 'button'
}:on_click(function(player)
vlayer_convert_chest_circuit(player)
vlayer_gui_update()
end)
local button_remove =
Gui.element{
name = 'button_4',
type = 'button',
caption = 'Remove',
style = 'button'
}:on_click(function(player)
vlayer_convert_remove(player)
vlayer_gui_update()
end)
function vlayer_gui_update()
local button_power_enabled = #vlayer.power.entity < config.interface_limit.energy
local button_storage_input_enabled = #vlayer.storage.input < config.interface_limit.storage_input
local button_circuit_enabled = #vlayer.power.circuit < config.interface_limit.circuit
for _, player in pairs(game.connected_players) do
local frame = Gui.get_left_element(player, vlayer_container)
frame.container.scroll.table[button_power.name].enabled = button_power_enabled
frame.container.scroll.table[button_storage_input.name].enabled = button_storage_input_enabled
frame.container.scroll.table[button_circuit.name].enabled = button_circuit_enabled
end
end
vlayer_container =
Gui.element(function(event_trigger, parent)
local player = Gui.get_player_from_element(parent)
local container = Gui.container(parent, event_trigger, 300)
Gui.header(container, 'VLAYER', '', true)
local scroll_table = Gui.scroll_table(container, 300, 2)
for i=1, #config.gui.content do
scroll_table.add{
name = 'vlayer_display_' .. i,
caption = config.gui.content[i].title,
type = config.gui.type,
style = config.gui.style
}
end
button_power(scroll_table)
button_storage_input(scroll_table)
button_circuit(scroll_table)
button_remove(scroll_table)
if (config.land.enabled ~= true) then
for i=7, 12 do
scroll_table['vlayer_display_' .. i].visible = false
end
end
if not (Roles.player_allowed(player, 'gui/vlayer-edit')) then
scroll_table['vlayer_display_' .. #config.gui.content - 1].visible = false
scroll_table['vlayer_display_' .. #config.gui.content].visible = false
scroll_table[button_power.name].visible = false
scroll_table[button_storage_input.name].visible = false
scroll_table[button_circuit.name].visible = false
scroll_table[button_remove.name].visible = false
end
scroll_table[button_power.name].enabled = (#vlayer.power.entity < config.interface_limit.energy)
scroll_table[button_storage_input.name].enabled = (#vlayer.storage.input < config.interface_limit.storage_input)
scroll_table[button_circuit.name].enabled = (#vlayer.power.circuit < config.interface_limit.circuit)
return container.parent
end)
:add_to_left_flow()
Gui.left_toolbar_button('entity/solar-panel', {'vlayer.main-tooltip'}, vlayer_container, function(player)
return Roles.player_allowed(player, 'gui/vlayer')
end)
Event.on_nth_tick(config.update_tick, function()
for _, v in pairs(vlayer_display) do
if v.type == 'item' then
v.count = format_number(vlayer.storage.item[v.name])
elseif v.type == 'signal' then
v.count = format_number(vlayer.circuit.output[v.name].count)
end
end
for _, player in pairs(game.connected_players) do
local frame = Gui.get_left_element(player, vlayer_container)
for k, v in pairs(vlayer_display) do
frame.container.scroll.table['vlayer_display_' .. k].caption = v.count
end
end
end)