You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
4.6 KiB
179 lines
4.6 KiB
-- ___ _ _ _ |
|
-- / __| |_ __ _| |_ ___ _ _(_)___ |
|
-- \__ \ _/ _` | _/ _ \ '_| / _ \ |
|
-- |___/\__\__,_|\__\___/_| |_\___/ |
|
-- |
|
-- Fetch metrics via attributes and |
|
-- functions from the game's API. |
|
|
|
|
|
local this = {} |
|
|
|
this.overlays = {} |
|
|
|
this.overlays.get_entity_count = function(parent, entity) |
|
|
|
res, data = pcall(function() |
|
return parent.get_entity_count(entity) |
|
end) |
|
|
|
if res then return data end |
|
|
|
return nil |
|
|
|
end |
|
|
|
this.overlays.get_flow_count = function(parent, prototypeName, isInput, precisionIndex) |
|
if type(isInput) ~= "boolean" then return nil end |
|
if defines.flow_precision_index[precisionIndex] == nil then return nil end |
|
|
|
res, data = pcall(function() |
|
return parent.get_flow_count({ |
|
name=prototypeName, |
|
input=isInput, |
|
precision_index=defines.flow_precision_index[precisionIndex], |
|
count=true |
|
}) |
|
end) |
|
|
|
return data |
|
end |
|
|
|
|
|
this.callOverlayFunction = function(functionName, callback, name, parent, args) |
|
|
|
-- entity counts |
|
if functionName == "get_entity_count" then |
|
|
|
--data = parent.get_entity_count(args[1]) |
|
data = this.overlays.get_entity_count(parent, args[1]) |
|
|
|
if data == nil then |
|
return false |
|
else |
|
this.doCallback(callback, name, data) |
|
return true |
|
end |
|
|
|
-- flow statistics |
|
-- worst hack to validate that parent inherits from FlowStatistics |
|
elseif functionName == "get_flow_count" and string.sub(parent.object_name, -14) == "FlowStatistics" then |
|
|
|
if args[2] == 'input' then isInput = true else isInput = false end |
|
|
|
if args[1] == "*" then |
|
|
|
if (isInput) then definedRef = parent.input_counts else definedRef = parent.output_counts end |
|
|
|
for index, val in pairs(definedRef) do |
|
|
|
data = this.overlays.get_flow_count(parent, index, isInput, args[3]) |
|
|
|
-- replace the wildcard in the name for subsequent metrics |
|
iterationName = string.gsub(name, '%*', index, 1) |
|
this.doCallback(callback, iterationName, data) |
|
end |
|
|
|
return true |
|
|
|
else |
|
|
|
data = this.overlays.get_flow_count(parent, args[1], isInput, args[3]) |
|
this.doCallback(callback, name, data) |
|
return true |
|
|
|
end |
|
|
|
elseif functionName == "get_flow_count" then |
|
|
|
game.players[1].print("Cannot get_flow_count for unexpected instance of:") |
|
game.players[1].print(parent.object_name) |
|
|
|
end |
|
|
|
end |
|
|
|
-- call the user-supplied function after a metric has been fetched |
|
this.doCallback = function(callback, name, val) |
|
pcall(callback, name, val) |
|
end |
|
|
|
|
|
-- recursive function to walk the game API for the requested name |
|
-- (given in dot notation) |
|
-- if successful calls callback(name, value) and returns true |
|
-- otherwise returns false |
|
-- returns true if wildcard with no matches |
|
this.traverseApiForValues = function(name, callback, remainingPath, parent) |
|
|
|
-- name is a required parameter |
|
if not name then return false end |
|
|
|
-- optional parameter used in recursion |
|
remainingPath = remainingPath or name |
|
|
|
|
|
-- pop next key from start of dot notation string |
|
key = string.match(remainingPath, "[^.]+") |
|
if not key then return false end |
|
|
|
-- remove key from remaining path |
|
remainingPath = string.sub(remainingPath, string.len(key)+2) |
|
|
|
-- typecast numeric keys for table index references |
|
if isNumeric(key) then key = tonumber(key) end |
|
|
|
-- first function iteration uses game object |
|
if not parent then |
|
return this.traverseApiForValues(name, callback, remainingPath, game) |
|
end |
|
|
|
-- ignore requests for things that don't exist |
|
if key ~= "*" and not checkTableKeyExists(parent, key) then |
|
return false |
|
end |
|
|
|
-- callable functions |
|
if type(parent[key]) == "function" then |
|
|
|
-- parse the remaining path for function args |
|
args = split(remainingPath, ".") |
|
|
|
-- call the function |
|
data = this.callOverlayFunction(key, callback, name, parent, args) |
|
if data then return true end |
|
|
|
return false |
|
end |
|
|
|
-- wildcards |
|
if key == "*" and type(parent) == "table" then |
|
wildcardRemainingPath = remainingPath |
|
|
|
if not table_size(parent) then |
|
return false |
|
end |
|
|
|
for idx, item in pairs(parent) do |
|
-- choose a key for this wildcard match |
|
iterationKey = idx |
|
if checkTableKeyExists(item, name) then iterationKey = item.name end |
|
|
|
-- replace the wildcard in the name for subsequent metrics |
|
iterationName = string.gsub(name, '%*', iterationKey, 1) |
|
this.traverseApiForValues(iterationName, callback, wildcardRemainingPath, item) |
|
end |
|
|
|
return true |
|
end |
|
|
|
-- return if nothing else to traverse |
|
if string.len(remainingPath)<1 then |
|
this.doCallback(callback, name, parent[key]) |
|
return true |
|
end |
|
|
|
return this.traverseApiForValues(name, callback, remainingPath, parent[key]) |
|
end |
|
|
|
return this |