Добавлены все обновления от сообщества, вплоть до #148
This commit is contained in:
645
ghost-counter/scripts/core.lua
Normal file
645
ghost-counter/scripts/core.lua
Normal file
@@ -0,0 +1,645 @@
|
||||
---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
|
||||
Reference in New Issue
Block a user