646 lines
26 KiB
Lua
646 lines
26 KiB
Lua
---Gets or makes playerdata table.
|
|
---@param player_index uint LuaPlayer index
|
|
---@return Playerdata playerdata
|
|
function get_make_playerdata(player_index)
|
|
local playerdata = global.playerdata[player_index]
|
|
|
|
if not playerdata then
|
|
playerdata = {
|
|
luaplayer=game.players[player_index],
|
|
index=player_index,
|
|
is_active=false,
|
|
job={},
|
|
logistic_requests={},
|
|
gui={},
|
|
options={}
|
|
}
|
|
global.playerdata[player_index] = playerdata
|
|
end
|
|
|
|
return playerdata
|
|
end
|
|
|
|
---Returns an empty request table for the given item.
|
|
---@param name string Item name
|
|
---@return Request request
|
|
function make_empty_request(name)
|
|
return {name=name, count=0, inventory=0, logistic_request={}}
|
|
end
|
|
|
|
---Sorts a table of `Request` objects by count, in descending order.
|
|
---@param requests table<string, Request> Table of requests to be sorted
|
|
---@return Request[] requests_sorted
|
|
function sort_requests(requests)
|
|
local requests_sorted = {}
|
|
for _, request in pairs(requests) do table.insert(requests_sorted, request) end
|
|
|
|
table.sort(requests_sorted, function(a, b)
|
|
if a.count > b.count then
|
|
return true
|
|
elseif a.count < b.count then
|
|
return false
|
|
elseif a.name < b.name then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end)
|
|
|
|
return requests_sorted
|
|
end
|
|
|
|
---Iterates over passed entities and counts items needed to build all ghost entities and tiles.
|
|
---@param entities LuaEntity[] table of entities
|
|
---@param ignore_tiles boolean Determines whether ghost tiles are counted
|
|
---@return table<uint, LuaEntity> ghosts table of actual ghost entities/tiles
|
|
---@return table requests table of requests, indexed by request name
|
|
function get_selection_counts(entities, ignore_tiles)
|
|
local ghosts, requests = {}, {}
|
|
local cache = {}
|
|
|
|
-- Iterate over entities and filter out anything that's not a ghost
|
|
local insert = table.insert
|
|
for _, entity in pairs(entities) do
|
|
local entity_type = entity.type
|
|
if entity_type == "entity-ghost" or (entity_type == "tile-ghost" and not ignore_tiles) then
|
|
local ghost_name = entity.ghost_name
|
|
local unit_number = entity.unit_number --[[@as uint]]
|
|
|
|
-- Get item to place entity, from prototype if necessary
|
|
if not cache[ghost_name] then
|
|
local prototype = entity_type == "entity-ghost" and
|
|
game.entity_prototypes[ghost_name] or
|
|
game.tile_prototypes[ghost_name]
|
|
cache[ghost_name] = {
|
|
item=prototype.items_to_place_this and prototype.items_to_place_this[1] or nil
|
|
}
|
|
end
|
|
|
|
ghosts[unit_number] = {}
|
|
|
|
-- If entity is associated with item, increment request for that item by `item.count`
|
|
local item = cache[ghost_name].item
|
|
if item then
|
|
requests[item.name] = requests[item.name] or make_empty_request(item.name)
|
|
requests[item.name].count = requests[item.name].count + item.count
|
|
insert(ghosts[unit_number], item)
|
|
end
|
|
|
|
-- If entity has module requests, increment request for each module type
|
|
local item_requests = entity_type == "entity-ghost" and entity.item_requests or nil
|
|
if item_requests and table_size(item_requests) > 0 then
|
|
for name, val in pairs(item_requests) do
|
|
requests[name] = requests[name] or make_empty_request(name)
|
|
requests[name].count = requests[name].count + val
|
|
insert(ghosts[unit_number], {name=name, count=val})
|
|
end
|
|
end
|
|
|
|
script.register_on_entity_destroyed(entity)
|
|
elseif entity_type == "item-request-proxy" then
|
|
local unit_number = entity.unit_number --[[@as uint]]
|
|
ghosts[unit_number] = {}
|
|
for name, val in pairs(entity.item_requests) do
|
|
requests[name] = requests[name] or make_empty_request(name)
|
|
requests[name].count = requests[name].count + val
|
|
insert(ghosts[unit_number], {name=name, count=val})
|
|
end
|
|
script.register_on_entity_destroyed(entity)
|
|
elseif entity.to_be_upgraded() then
|
|
local unit_number = entity.unit_number --[[@as uint]]
|
|
local prototype = entity.get_upgrade_target() --[[@as LuaEntityPrototype]]
|
|
local ghost_name = prototype.name
|
|
|
|
-- Get item to place entity, from prototype if necessary
|
|
if not cache[ghost_name] then
|
|
cache[ghost_name] = {
|
|
item=prototype.items_to_place_this and prototype.items_to_place_this[1] or nil
|
|
}
|
|
end
|
|
|
|
ghosts[unit_number] = {}
|
|
|
|
-- If entity is associated with item, increment request for that item by `item.count`
|
|
local item = cache[ghost_name].item
|
|
if item then
|
|
requests[item.name] = requests[item.name] or make_empty_request(item.name)
|
|
requests[item.name].count = requests[item.name].count + item.count
|
|
insert(ghosts[unit_number], item)
|
|
end
|
|
|
|
script.register_on_entity_destroyed(entity)
|
|
end
|
|
end
|
|
|
|
return ghosts, requests
|
|
end
|
|
|
|
---Returns the blueprint tiles contained within a given item stack.
|
|
---@param item_stack LuaItemStack Must be a blueprint or a blueprint-book
|
|
---@return Tile[] tiles
|
|
function get_blueprint_tiles(item_stack)
|
|
if item_stack.is_blueprint_book then
|
|
local inventory = item_stack.get_inventory(defines.inventory.item_main) --[[@as LuaInventory]]
|
|
return get_blueprint_tiles(inventory[item_stack.active_index])
|
|
else
|
|
return (item_stack.get_blueprint_tiles() or {})
|
|
end
|
|
end
|
|
|
|
---Processes blueprint entities and tiles to generate item request counts.
|
|
---@param entities table array of blueprint entities
|
|
---@param tiles table array of blueprint tiles
|
|
---@return table requests
|
|
function get_blueprint_counts(entities, tiles)
|
|
local requests = {}
|
|
local cache = {}
|
|
|
|
-- Iterate over blueprint entities
|
|
for _, entity in pairs(entities) do
|
|
if not cache[entity.name] then
|
|
local prototype = game.entity_prototypes[entity.name]
|
|
cache[entity.name] = {
|
|
item=prototype.items_to_place_this and prototype.items_to_place_this[1] or nil
|
|
}
|
|
end
|
|
|
|
-- If entity is associated with item, increment request for that item by `item.count`
|
|
local item = cache[entity.name].item
|
|
if item then
|
|
requests[item.name] = requests[item.name] or make_empty_request(item.name)
|
|
requests[item.name].count = requests[item.name].count + item.count
|
|
end
|
|
|
|
-- If entity has module requests, increment request for each module type
|
|
local item_requests = entity.items
|
|
if item_requests and table_size(item_requests) > 0 then
|
|
for name, val in pairs(item_requests) do
|
|
requests[name] = requests[name] or make_empty_request(name)
|
|
requests[name].count = requests[name].count + val
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Iterate over blueprint tiles
|
|
for _, tile in pairs(tiles) do
|
|
if not cache[tile.name] then
|
|
local prototype = game.tile_prototypes[tile.name]
|
|
cache[tile.name] = {
|
|
item=prototype.items_to_place_this and prototype.items_to_place_this[1] or nil
|
|
}
|
|
end
|
|
|
|
-- If tile is associated with item, increment request for that item by `item.count`
|
|
local item = cache[tile.name].item
|
|
if item then
|
|
requests[item.name] = requests[item.name] or make_empty_request(item.name)
|
|
requests[item.name].count = requests[item.name].count + item.count
|
|
end
|
|
end
|
|
|
|
return requests
|
|
end
|
|
|
|
---Converts a given player's `Request` table to signals out of a series of constant combinators.
|
|
---@param player_index uint Player index
|
|
function make_combinators_blueprint(player_index)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
|
|
-- Make sure constant combinator prototype exists
|
|
local prototype = game.entity_prototypes["constant-combinator"]
|
|
if not prototype then
|
|
playerdata.luaplayer.print({"ghost-counter-message.missing-constant-combinator-prototype"})
|
|
return
|
|
end
|
|
|
|
local n_slots = prototype.item_slot_count
|
|
local requests = playerdata.job.requests_sorted
|
|
local request_index = 1
|
|
local combinators = {}
|
|
|
|
-- Iterate over the number of constant combinators we will need
|
|
for i = 1, math.ceil(#requests / n_slots) do
|
|
combinators[i] = {
|
|
entity_number=i,
|
|
name="constant-combinator",
|
|
position={i - 0.5, 0},
|
|
direction=4,
|
|
control_behavior={filters={}},
|
|
connections={{}}
|
|
}
|
|
|
|
local filters = combinators[i].control_behavior.filters
|
|
|
|
-- Set the combinator slots to the ghost request counts
|
|
for j = 1, n_slots do
|
|
local request = requests[request_index]
|
|
filters[j] = {signal={type="item", name=request.name}, count=request.count, index=j}
|
|
|
|
-- Increment request index; break if no more requests are left
|
|
request_index = request_index + 1
|
|
if request_index > #requests then break end
|
|
end
|
|
end
|
|
|
|
-- Wire up the combinators to one another
|
|
if #combinators > 1 then
|
|
for i = 1, (#combinators - 1) do
|
|
local connections = combinators[i].connections[1]
|
|
|
|
connections["green"] = {{entity_id=i + 1}}
|
|
connections["red"] = {{entity_id=i + 1}}
|
|
end
|
|
end
|
|
|
|
-- Try to clear the cursor
|
|
local is_successful = playerdata.luaplayer.clear_cursor()
|
|
|
|
if is_successful then
|
|
playerdata.luaplayer.cursor_stack.set_stack("blueprint")
|
|
playerdata.luaplayer.cursor_stack.set_blueprint_entities(combinators)
|
|
else
|
|
playerdata.luaplayer.print({"ghost-counter-message.failed-to-clear-cursor"})
|
|
end
|
|
end
|
|
|
|
---Deletes requests with zero ghosts from the `job.requests` table.
|
|
---@param player_index uint Player index
|
|
function remove_empty_requests(player_index)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
for name, request in pairs(playerdata.job.requests) do
|
|
if request.count <= 0 then playerdata.job.requests[name] = nil end
|
|
end
|
|
end
|
|
|
|
---Updates table of `Request`s with inventory and cursor stack contents.
|
|
---@param player_index uint Player index
|
|
function update_inventory_info(player_index)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
local cursor_stack = playerdata.luaplayer.cursor_stack
|
|
local inventory = playerdata.luaplayer.get_main_inventory()
|
|
local contents = inventory and inventory.get_contents() or {}
|
|
local requests = playerdata.job.requests
|
|
|
|
-- Iterate over each request and get the count in inventory
|
|
for name, request in pairs(requests) do request.inventory = contents[name] or 0 end
|
|
|
|
-- Add cursor contents to request count
|
|
if cursor_stack and cursor_stack.valid_for_read and requests[cursor_stack.name] then
|
|
local request = requests[cursor_stack.name]
|
|
request.inventory = request.inventory + cursor_stack.count
|
|
end
|
|
end
|
|
|
|
---Updates table of `Request`s with the player's current logistic requests.
|
|
---@param player_index uint Player index
|
|
function update_logistics_info(player_index)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
local requests = playerdata.job.requests
|
|
|
|
-- Get player character
|
|
local character = playerdata.luaplayer.character
|
|
if not character then return end
|
|
|
|
-- Iterate over each logistic slot and update request table with logistic request details
|
|
local logistic_requests = {}
|
|
for i = 1, character.request_slot_count do
|
|
local slot = playerdata.luaplayer.get_personal_logistic_slot(i --[[@as uint]])
|
|
if requests[slot.name] then
|
|
requests[slot.name].logistic_request = {slot_index=i, min=slot.min, max=slot.max}
|
|
logistic_requests[slot.name] = true
|
|
end
|
|
end
|
|
|
|
-- Clear the `logistic_request` table of the request if one was not found
|
|
for _, request in pairs(playerdata.job.requests) do
|
|
if not logistic_requests[request.name] then request.logistic_request = {} end
|
|
end
|
|
end
|
|
|
|
---Iterates over one-time requests table and restores old requests if they have been fulfilled.
|
|
---@param player_index uint Player index
|
|
function update_one_time_logistic_requests(player_index)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
if not playerdata.luaplayer.character then return end
|
|
|
|
local inventory = playerdata.luaplayer.get_main_inventory() --[[@as LuaInventory]]
|
|
|
|
-- Iterate over one-time requests table and restore old requests if they have been fulfilled
|
|
for name, logi_req in pairs(playerdata.logistic_requests) do
|
|
local request = playerdata.job.requests[name]
|
|
local slot = playerdata.luaplayer.get_personal_logistic_slot(logi_req.slot_index)
|
|
|
|
if request then
|
|
-- Update logistic request to reflect new ghost count
|
|
if slot.min ~= request.count then
|
|
local new_slot = {name=name, min=request.count}
|
|
logi_req.new_min = request.count
|
|
logi_req.is_new = true
|
|
playerdata.luaplayer.set_personal_logistic_slot(logi_req.slot_index, new_slot)
|
|
end
|
|
|
|
-- Restore prior request (if any) if one-time request has been fulfilled
|
|
if (inventory.get_item_count(name) >= logi_req.new_min) or
|
|
(logi_req.new_min <= (logi_req.old_min or 0)) then
|
|
restore_prior_logistic_request(player_index, name)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
---Iterates over player's logistic slots and returns the first empty slot. Player _must_ have a
|
|
---character entity.
|
|
---@param player_index uint Player index
|
|
---@return uint? slot_index First empty slot
|
|
function get_first_empty_slot(player_index)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
local character = playerdata.luaplayer.character --[[@as LuaEntity]]
|
|
|
|
for slot_index = 1, character.request_slot_count + 1 do
|
|
---@cast slot_index uint
|
|
local slot = playerdata.luaplayer.get_personal_logistic_slot(slot_index)
|
|
if slot.name == nil then return slot_index end
|
|
end
|
|
end
|
|
|
|
---Gets a table with details of any existing logistic request for a given item.
|
|
---@param player_index uint Player index
|
|
---@param name string Item name
|
|
---@return table|nil logistic_request
|
|
function get_existing_logistic_request(player_index, name)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
local character = playerdata.luaplayer.character
|
|
if not character then return nil end
|
|
|
|
for i = 1, character.request_slot_count do
|
|
---@cast i uint
|
|
local slot = playerdata.luaplayer.get_personal_logistic_slot(i)
|
|
if slot and slot.name == name then
|
|
return {slot_index=i, name=slot.name, min=slot.min, max=slot.max}
|
|
end
|
|
end
|
|
end
|
|
|
|
---Generates a logistic request or modifies an existing request to satisfy need. Registers the
|
|
---change in a `playerdata.logistic_requests` table so that it can be reverted later on.
|
|
---@param player_index uint Player index
|
|
---@param name string `request` name
|
|
function make_one_time_logistic_request(player_index, name)
|
|
-- Abort if no player character
|
|
local playerdata = get_make_playerdata(player_index)
|
|
if not playerdata.luaplayer.character then return end
|
|
|
|
-- Abort if player already has more of item in inventory than needed
|
|
local request = playerdata.job.requests[name]
|
|
if not request or request.inventory >= request.count then return end
|
|
|
|
-- Get any existing request and abort if it would already meet need
|
|
local existing_request = get_existing_logistic_request(player_index, request.name) or {}
|
|
if (existing_request.min or 0) >= request.count then return end
|
|
|
|
-- Prepare new logistic slot and get existing or first empty `slot_index`
|
|
local new_slot = {name=request.name, min=request.count}
|
|
local slot_index = existing_request.slot_index or get_first_empty_slot(player_index)
|
|
if not slot_index then return end
|
|
|
|
-- Save details of change in playerdata so that it can be reverted later
|
|
-- This is set here in order for the event handler to be able to identify this change
|
|
-- as originating from the mod and to ignore it.
|
|
playerdata.logistic_requests[request.name] = {
|
|
slot_index=slot_index,
|
|
old_min=existing_request.min,
|
|
old_max=existing_request.max,
|
|
new_min=request.count,
|
|
is_new=true
|
|
}
|
|
|
|
-- Actually modify personal logistic slot
|
|
local is_successful = playerdata.luaplayer.set_personal_logistic_slot(slot_index, new_slot)
|
|
|
|
if is_successful then
|
|
-- Update request's `logistic_request` table
|
|
request.logistic_request.slot_index = slot_index
|
|
request.logistic_request.min = request.count
|
|
request.logistic_request.max = nil
|
|
|
|
playerdata.has_updates = true
|
|
register_update(player_index, game.tick)
|
|
else
|
|
-- Delete record of temporary request as it didn't go through
|
|
playerdata.logistic_requests[request.name] = nil
|
|
end
|
|
end
|
|
|
|
---Restores the prior logistic request (if any) that was in place before the one-time request was
|
|
---made.
|
|
---@param player_index uint Player index
|
|
---@param name string Item name
|
|
function restore_prior_logistic_request(player_index, name)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
if not playerdata.luaplayer.character then return end
|
|
|
|
local request = playerdata.logistic_requests[name]
|
|
local slot
|
|
|
|
-- Either clear or reset slot using old request values
|
|
if request.old_min or request.old_max then
|
|
slot = {name=name, min=request.old_min, max=request.old_max}
|
|
playerdata.luaplayer.set_personal_logistic_slot(request.slot_index, slot)
|
|
else
|
|
playerdata.luaplayer.clear_personal_logistic_slot(request.slot_index)
|
|
end
|
|
|
|
if playerdata.job.requests[name] then
|
|
if slot then
|
|
playerdata.job.requests[name].logistic_request = {
|
|
slot_index=request.slot_index,
|
|
min=slot.min,
|
|
max=slot.max
|
|
}
|
|
else
|
|
playerdata.job.requests[name].logistic_request = {}
|
|
end
|
|
end
|
|
end
|
|
|
|
---Iterates over `playerdata.logistic_requests` to get rid of them.
|
|
---@param player_index uint Player index
|
|
function cancel_all_one_time_requests(player_index)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
for name, _ in pairs(playerdata.logistic_requests) do
|
|
restore_prior_logistic_request(player_index, name)
|
|
end
|
|
end
|
|
|
|
---Returns the yield of a given item from a single craft of a given recipe.
|
|
---@param item_name string Item name
|
|
---@param recipe LuaRecipePrototype Recipe prototype
|
|
---@return number
|
|
function get_yield_per_craft(item_name, recipe)
|
|
local yield = 0
|
|
|
|
for _, product in pairs(recipe.products) do
|
|
if product.name == item_name then
|
|
local probability = product.probability or 1
|
|
yield = (product.amount) and (product.amount * probability) or
|
|
((product.amount_min + product.amount_max) * 0.5 * probability)
|
|
break
|
|
end
|
|
end
|
|
|
|
return yield
|
|
end
|
|
|
|
---Returns the number of times an item is set to be produced by a given character, taking into
|
|
---account their crafting queue contents.
|
|
---@param character LuaEntity Character entity
|
|
---@param item_name string Name of item to craft
|
|
---@return uint item_count
|
|
function get_item_count_from_character_crafting_queue(character, item_name)
|
|
if character.crafting_queue_size == 0 then return 0 end
|
|
|
|
local relevant_recipes = game.get_filtered_recipe_prototypes{
|
|
{filter="has-product-item", elem_filters={{filter="name", name=item_name}}},
|
|
{filter="hidden-from-player-crafting", invert=true, mode="and"}
|
|
}
|
|
local unique_recipes = {} --[[@as table<string, uint>]]
|
|
local item_count = 0
|
|
|
|
-- Create a list of unique and relevant recipes in the crafting queue
|
|
for _, queue_item in pairs(character.crafting_queue) do
|
|
local recipe_name = queue_item.recipe
|
|
if not queue_item.prerequisite and (unique_recipes[recipe_name] or relevant_recipes[recipe_name]) then
|
|
unique_recipes[recipe_name] = (unique_recipes[recipe_name] or 0) + queue_item.count
|
|
end
|
|
end
|
|
|
|
-- Count number of `name` items that will ultimately be produced by recipes in crafting queue
|
|
for recipe_name, n_crafts in pairs(unique_recipes) do
|
|
local yield_per_craft = get_yield_per_craft(item_name, relevant_recipes[recipe_name])
|
|
item_count = item_count + math.floor(yield_per_craft * n_crafts)
|
|
end
|
|
|
|
return item_count --[[@as uint]]
|
|
end
|
|
|
|
---Crafts a given item; amount to craft based on the corresponding request for that item.
|
|
---@param player_index uint Player index
|
|
---@param request Request Request data
|
|
---@return "no-character"|"no-crafts-needed"|"attempted" result
|
|
---@return uint? items_crafted Number of items crafted
|
|
function craft_request(player_index, request)
|
|
-- Abort if no player character
|
|
local playerdata = get_make_playerdata(player_index)
|
|
local character = playerdata.luaplayer.character
|
|
if not character then return "no-character" end
|
|
|
|
-- Abort if player already has more of item in inventory than needed
|
|
if request.inventory >= request.count then return "no-crafts-needed" end
|
|
|
|
-- Calculate item need; abort if 0 (or less)
|
|
local crafting_yield = get_item_count_from_character_crafting_queue(character, request.name)
|
|
local item_need = request.count - request.inventory - crafting_yield
|
|
local original_need = item_need
|
|
if item_need <= 0 then return "no-crafts-needed" end
|
|
|
|
local crafting_recipes = game.get_filtered_recipe_prototypes{
|
|
{filter="has-product-item", elem_filters={{filter="name", name=request.name}}},
|
|
{filter="hidden-from-player-crafting", invert=true, mode="and"}
|
|
}
|
|
|
|
for recipe_name, recipe in pairs(crafting_recipes) do
|
|
local yield_per_craft = get_yield_per_craft(request.name, recipe)
|
|
local needed_crafts = math.ceil(item_need / yield_per_craft) --[[@as uint]]
|
|
local actual_crafts = character.begin_crafting{recipe=recipe_name, count=needed_crafts, silent=true}
|
|
|
|
item_need = item_need - math.floor(actual_crafts * yield_per_craft)
|
|
if item_need <= 0 then break end
|
|
end
|
|
|
|
return "attempted", original_need - item_need
|
|
end
|
|
|
|
---Registers that a change in data tables has occured and marks the responsible player as having
|
|
---data updates to process.
|
|
---@param player_index uint Player index
|
|
---@param tick number Tick during which the data update occurred
|
|
function register_update(player_index, tick)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
|
|
-- Mark player as having a data update, in order for it to get reprocessed
|
|
playerdata.has_updates = true
|
|
|
|
-- Record the tick in which the update was registered
|
|
global.last_event = tick
|
|
|
|
-- Register nth_tick handler if needed
|
|
register_nth_tick_handler(true)
|
|
end
|
|
|
|
---Registers/unregisters on_nth_tick event handler.
|
|
---@param state any
|
|
function register_nth_tick_handler(state)
|
|
if state and not global.events.nth_tick then
|
|
global.events.nth_tick = true
|
|
script.on_nth_tick(global.settings.min_update_interval, on_nth_tick)
|
|
elseif state == false and global.events.nth_tick then
|
|
global.events.nth_tick = false
|
|
---@diagnostic disable-next-line
|
|
script.on_nth_tick(nil)
|
|
end
|
|
end
|
|
|
|
---Registers/unregisters event handlers for inventory or player cursor stack changes.
|
|
---@param state boolean Determines whether to register or unregister event handlers
|
|
function register_inventory_monitoring(state)
|
|
if state and not global.events.inventory then
|
|
global.events.inventory = true
|
|
|
|
script.on_event(defines.events.on_player_main_inventory_changed,
|
|
on_player_main_inventory_changed)
|
|
script.on_event(defines.events.on_player_cursor_stack_changed,
|
|
on_player_main_inventory_changed)
|
|
script.on_event(defines.events.on_entity_destroyed, on_ghost_destroyed)
|
|
elseif state == false and global.events.inventory then
|
|
global.events.inventory = false
|
|
|
|
script.on_event(defines.events.on_player_main_inventory_changed, nil)
|
|
script.on_event(defines.events.on_player_cursor_stack_changed, nil)
|
|
script.on_event(defines.events.on_entity_destroyed, nil)
|
|
end
|
|
end
|
|
|
|
---Registers/unregisters event handlers for player logistic slot changes.
|
|
---@param state boolean Determines whether to register or unregister event handlers
|
|
function register_logistics_monitoring(state)
|
|
if state and not global.events.logistics then
|
|
global.events.logistics = true
|
|
script.on_event(defines.events.on_entity_logistic_slot_changed,
|
|
on_entity_logistic_slot_changed)
|
|
elseif state == false and global.events.logistics then
|
|
global.events.logistics = false
|
|
script.on_event(defines.events.on_entity_logistic_slot_changed, nil)
|
|
end
|
|
end
|
|
|
|
---Iterates over global playerdata table and determines whether any connected players have their
|
|
---mod GUI open.
|
|
---@return boolean
|
|
function is_inventory_monitoring_needed()
|
|
for _, playerdata in pairs(global.playerdata) do
|
|
if playerdata.is_active and playerdata.luaplayer.connected then return true end
|
|
end
|
|
return false
|
|
end
|
|
|
|
---Iterates over the global playerdata table and checks to see if any one-time logistic requests
|
|
---are still unfulfilled.
|
|
---@return boolean
|
|
function is_logistics_monitoring_needed()
|
|
for _, playerdata in pairs(global.playerdata) do
|
|
if (playerdata.is_active or table_size(playerdata.logistic_requests) > 0) and
|
|
playerdata.luaplayer.connected then return true end
|
|
end
|
|
return false
|
|
end
|