240 lines
8.9 KiB
Lua
240 lines
8.9 KiB
Lua
--[Helper Functions]--
|
|
-- Currently mostly picker specific with plans to flesh out and add to appropriate places
|
|
|
|
local lib = {}
|
|
local Area = require('__stdlib__/stdlib/area/area')
|
|
local Position = require('__stdlib__/stdlib/area/position')
|
|
|
|
function lib.get_or_create_main_left_flow(player, flow_name)
|
|
local main_flow = player.gui.left[flow_name .. '_main_flow']
|
|
if not main_flow then
|
|
main_flow =
|
|
player.gui.left.add {
|
|
type = 'flow',
|
|
name = flow_name .. '_main_flow',
|
|
direction = 'vertical',
|
|
style = 'slot_table_spacing_vertical_flow'
|
|
}
|
|
main_flow.style.top_padding = 4
|
|
main_flow.style.right_padding = 0
|
|
main_flow.style.left_padding = 0
|
|
main_flow.style.bottom_padding = 0
|
|
end
|
|
return main_flow
|
|
end
|
|
|
|
lib.ghosts = {
|
|
['entity-ghost'] = true,
|
|
['tile-ghost'] = true
|
|
}
|
|
|
|
--Return localised name, entity_prototype, and item_prototype
|
|
function lib.get_placeable_item(entity)
|
|
local locname, ep
|
|
if entity.name == 'entity-ghost' or entity.name == 'tile-ghost' then
|
|
locname = entity.ghost_localised_name
|
|
ep = entity.ghost_prototype
|
|
else
|
|
locname = entity.localised_name
|
|
ep = entity.prototype
|
|
end
|
|
if ep and ep.mineable_properties and ep.mineable_properties.minable and ep.mineable_properties.products and ep.mineable_properties.products[1].type == 'item' then -- If the entity has mineable products.
|
|
local ip = game.item_prototypes[ep.mineable_properties.products[1].name] -- Retrieve first available item prototype
|
|
if ip and (ip.place_result or ip.place_as_tile_result) then -- If the entity has an item with a placeable prototype,
|
|
return (ip.localised_name or locname), ep, ip
|
|
end
|
|
return locname, ep
|
|
end
|
|
end
|
|
|
|
function lib.stack_is_ghost(stack, ghost)
|
|
if ghost.name == 'entity-ghost' then
|
|
return stack.prototype.place_result and stack.prototype.place_result.name == ghost.ghost_name
|
|
elseif ghost.name == 'tile-ghost' then
|
|
return stack.prototype.place_as_tile_result and stack.prototype.place_as_tile_result.result.name == ghost.ghost_name
|
|
end
|
|
end
|
|
|
|
function lib.find_resources(entity)
|
|
if entity.type == 'mining-drill' then
|
|
local area = Position.expand_to_area(entity.position, game.entity_prototypes[entity.name].mining_drill_radius)
|
|
local name = entity.mining_target and entity.mining_target.name or nil
|
|
return entity.surface.count_entities_filtered {area = area, type = 'resource', name = name}
|
|
end
|
|
return 0
|
|
end
|
|
|
|
function lib.get_item_stack(e, name, give_free)
|
|
local stack = e.get_main_inventory().find_item_stack(name)
|
|
if stack then
|
|
return stack
|
|
end
|
|
if e.vehicle then
|
|
local trunk = e.vehicle.get_inventory(defines.inventory.car_trunk)
|
|
stack = trunk and trunk.find_item_stack(name)
|
|
if stack then
|
|
return stack
|
|
end
|
|
end
|
|
if e.is_player() and (e.cheat_mode or give_free) then
|
|
local inv = lib.create_buffer_corpse(e).get_inventory(defines.inventory.character_corpse)
|
|
if inv[1].set_stack(name) then
|
|
return inv[1]
|
|
end
|
|
end
|
|
end
|
|
|
|
function lib.create_buffer_corpse(player, inf)
|
|
return player.surface.create_entity {
|
|
name = 'picker-buffer-corpse-' .. (inf and 'inf' or 'instant'),
|
|
position = {0, 0},
|
|
force = player.force,
|
|
inventory_size = 1,
|
|
player_index = player.index
|
|
}
|
|
end
|
|
|
|
-- Attempt to insert an item_stack or array of item_stacks into the entity
|
|
-- Spill to the ground at the entity/player anything that doesn't get inserted
|
|
-- @param entity: the entity or player object
|
|
-- @param item_stacks: a SimpleItemStack or array of SimpleItemStacks to insert
|
|
-- @return bool : there was some items inserted or spilled
|
|
function lib.insert_or_spill_items(entity, item_stacks)
|
|
local new_stacks = {}
|
|
if item_stacks then
|
|
if item_stacks[1] and item_stacks[1].name then
|
|
new_stacks = item_stacks
|
|
elseif item_stacks and item_stacks.name then
|
|
new_stacks = {item_stacks}
|
|
end
|
|
for _, stack in pairs(new_stacks) do
|
|
local name, count, health = stack.name, stack.count, stack.health or 1
|
|
if game.item_prototypes[name] and not game.item_prototypes[name].has_flag('hidden') and stack.count > 0 then
|
|
local inserted = entity.insert {name = name, count = count, health = health}
|
|
if inserted ~= count then
|
|
entity.surface.spill_item_stack(entity.position, {name = name, count = count - inserted, health = health}, true)
|
|
end
|
|
end
|
|
end
|
|
return new_stacks[1] and new_stacks[1].name and true
|
|
end
|
|
end
|
|
|
|
function lib.satisfy_requests(player, proxy)
|
|
local entity
|
|
|
|
if proxy.name == 'item-request-proxy' then
|
|
entity = proxy.proxy_target
|
|
elseif Area(proxy.selection_box):size() > 0 then
|
|
proxy =
|
|
proxy.surface.find_entities_filtered {
|
|
name = 'item-request-proxy',
|
|
area = proxy.selection_box
|
|
}[1]
|
|
entity = proxy and proxy.proxy_target
|
|
end
|
|
|
|
if proxy and entity then
|
|
local pinv = player.get_main_inventory()
|
|
local new_requests = {}
|
|
local pos = Position.increment(entity.position, 0, -0.35)
|
|
for name, count in pairs(proxy.item_requests) do
|
|
local removed = player.cheat_mode and count or (entity and entity.can_insert(name) and pinv.remove({name = name, count = count})) or 0
|
|
if removed > 0 then
|
|
entity.insert({name = name, count = removed})
|
|
local txt = {'', -removed, ' ', {'item-name.' .. name}, ' (' .. player.get_item_count(name) .. ')'}
|
|
player.create_local_flying_text {
|
|
text = txt,
|
|
position = pos(),
|
|
color = defines.color.white
|
|
}
|
|
end
|
|
local balance = count - removed
|
|
new_requests[name] = balance > 0 and balance or nil
|
|
end
|
|
proxy.item_requests = new_requests
|
|
end
|
|
end
|
|
|
|
function lib.get_planner(player, planner, label)
|
|
local found
|
|
local inventory = player.get_main_inventory()
|
|
for i = 1, #inventory do
|
|
local slot = inventory[i]
|
|
if slot.valid_for_read then
|
|
if slot.name == planner then
|
|
if slot.is_blueprint then
|
|
if not slot.is_blueprint_setup() then
|
|
found = slot
|
|
elseif (label and slot.is_blueprint_setup() and slot.label and slot.label:find(label)) then
|
|
if player.cursor_stack.swap_stack(slot) then
|
|
return player.cursor_stack
|
|
end
|
|
end
|
|
elseif game.item_prototypes[planner] then
|
|
if player.cursor_stack.swap_stack(slot) then
|
|
return player.cursor_stack
|
|
end
|
|
end
|
|
elseif planner == 'repair-tool' and slot.type == 'repair-tool' then
|
|
if player.cursor_stack.swap_stack(slot) then
|
|
return player.cursor_stack
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if found and player.cursor_stack.swap_stack(found) then
|
|
return player.cursor_stack
|
|
else
|
|
return planner and game.item_prototypes[planner] and player.cursor_stack.set_stack(planner) and player.cursor_stack
|
|
end
|
|
end
|
|
|
|
local function _matches_options(slot, options)
|
|
local matches = false
|
|
if options.is_blueprint_setup then
|
|
matches = slot.is_blueprint and slot.is_blueprint_setup()
|
|
end
|
|
if options.is_blueprint_not_setup then
|
|
matches = slot.is_blueprint and not slot.is_blueprint_setup()
|
|
end
|
|
if options.label then
|
|
matches = slot.is_item_with_label and slot.label and slot.label:find(options.label)
|
|
end
|
|
if options.is_deconstruction_setup then
|
|
matches = slot.is_deconstruction_item and (#slot.entity_filters > 0 or #slot.tile_filters > 0)
|
|
end
|
|
if options.is_deconstruction_not_setup then
|
|
matches = slot.is_deconstruction_item and (#slot.entity_filters == 0 and #slot.tile_filters == 0)
|
|
end
|
|
return matches
|
|
end
|
|
|
|
-- Return the "inventory slot" where the item is found
|
|
function lib.find_item_in_inventory(item_name, inventory, options)
|
|
options = options or {}
|
|
local found
|
|
|
|
for i = 1, #inventory, 1 do
|
|
local slot = inventory[i]
|
|
if slot.valid_for_read and slot.name == item_name and (not options or _matches_options(slot, options)) then
|
|
found = slot
|
|
break
|
|
end
|
|
end
|
|
if found then
|
|
return found
|
|
end
|
|
|
|
end
|
|
|
|
function lib.set_or_swap_item(player, slot, item, set)
|
|
if type(item) == "string" then
|
|
return (set and slot.set_stack(item)) or (player.clear_cursor() and slot.set_stack(item))
|
|
end
|
|
return item and ((set and slot.set_stack(item)) or (player.clear_cursor() and slot.swap_stack(item) or slot.set_stack(item)))
|
|
end
|
|
|
|
|
|
return lib
|