199 lines
6.1 KiB
Lua
199 lines
6.1 KiB
Lua
--[[
|
|
Takes a config string and turns it into a config object.
|
|
|
|
The configuration object looks like this:
|
|
{
|
|
['category-name'] = {
|
|
{
|
|
technology_count = 5, -- 0 means infinite
|
|
bonus_per_technology = 0.05, -- 5%
|
|
|
|
prerequisites = {
|
|
'qol-category-name-1-3',
|
|
'logistic-science-pack',
|
|
... next prerequisite
|
|
},
|
|
|
|
cycle_count_formula = '100*L',
|
|
cycle_time = 30, -- seconds
|
|
cycle_ingredients = {
|
|
{ 'logistic-science-pack', 2 },
|
|
... next ingredient
|
|
},
|
|
},
|
|
... next tier
|
|
},
|
|
... next category
|
|
}
|
|
]]
|
|
|
|
local setting_name_formats = require('defines.setting_name_formats')
|
|
local technology_formats = require('defines.technology_name_formats')
|
|
local category_map = require('categories').map
|
|
local default_import_settings = {
|
|
multiplier = 1,
|
|
min = -1000000,
|
|
max = 1000000,
|
|
}
|
|
local is_infinite_research_enabled = settings.startup[setting_name_formats.infinite_research_enabled].value
|
|
|
|
-- returns index: number, strings: string[]
|
|
local function decode_string_table(str, index)
|
|
local strings = {}
|
|
local comma = str:find(',', index, true)
|
|
assert(comma)
|
|
local string_count = tonumber(str:sub(index, comma - 1))
|
|
assert(string_count > 0)
|
|
index = comma + 1
|
|
|
|
local temp = {}
|
|
for _ = 1, string_count do
|
|
comma = str:find(',', index, true)
|
|
assert(comma)
|
|
-- Check for escape
|
|
while str:byte(comma + 1) == 44 --[[ , ]] do
|
|
temp[#temp + 1] = str:sub(index, comma)
|
|
index = comma + 2
|
|
comma = str:find(',', index, true)
|
|
end
|
|
temp[#temp + 1] = str:sub(index, comma - 1)
|
|
index = comma + 1
|
|
|
|
strings[#strings + 1] = table.concat(temp)
|
|
for i = #temp, 1, -1 do
|
|
temp[i] = nil
|
|
end
|
|
end
|
|
|
|
return index, strings
|
|
end
|
|
|
|
local function decode_numbers(str, index)
|
|
local nrs = {}
|
|
while true do
|
|
local comma = str:find(',', index, true)
|
|
if comma then
|
|
nrs[#nrs + 1] = tonumber(str:sub(index, comma - 1))
|
|
index = comma + 1
|
|
else
|
|
nrs[#nrs + 1] = tonumber(str:sub(index))
|
|
return nrs
|
|
end
|
|
end
|
|
end
|
|
|
|
return function (str)
|
|
assert(#str >= 3);
|
|
local version, comma = str:byte(1, 2)
|
|
if version ~= 49 --[[ 1 ]] or comma ~= 44 --[[ , ]] then
|
|
error('incorrect config version')
|
|
end
|
|
|
|
local index, strings = decode_string_table(str, 3)
|
|
local numbers = decode_numbers(str, index)
|
|
|
|
local nr_index = 0
|
|
local function decode_nr()
|
|
nr_index = nr_index + 1
|
|
assert(nr_index <= #numbers)
|
|
return numbers[nr_index]
|
|
end
|
|
local function decode_str()
|
|
local nr = decode_nr()
|
|
if nr == 0 then
|
|
return ''
|
|
else
|
|
return strings[nr]
|
|
end
|
|
end
|
|
|
|
local decoded_categories = {}
|
|
local category_count = decode_nr()
|
|
for _ = 1, category_count do
|
|
local name = decode_str()
|
|
local import_settings =
|
|
category_map[name] and category_map[name].import_settings or default_import_settings
|
|
local tier_count = decode_nr()
|
|
local tiers = {}
|
|
for tier_index = 1, tier_count do
|
|
local technology_count = decode_nr()
|
|
local bonus_per_technology = decode_nr() * import_settings.multiplier
|
|
bonus_per_technology = math.max(import_settings.min, math.min(import_settings.max, bonus_per_technology))
|
|
local prerequisites = {}
|
|
do
|
|
local previous_tier = decode_nr()
|
|
if previous_tier ~= 0 then
|
|
assert(tier_index > 1)
|
|
prerequisites[#prerequisites + 1] =
|
|
technology_formats.player:format(name, tier_index - 1, previous_tier)
|
|
end
|
|
local prerequisite_count = decode_nr()
|
|
for _ = 1, prerequisite_count do
|
|
prerequisites[#prerequisites + 1] = decode_str()
|
|
end
|
|
end
|
|
local cycle_count_formula = decode_str()
|
|
local cycle_time = decode_nr()
|
|
local cycle_ingredients = {}
|
|
do
|
|
local ingredient_count = decode_nr()
|
|
for _ = 1, ingredient_count do
|
|
local count = decode_nr()
|
|
cycle_ingredients[#cycle_ingredients + 1] =
|
|
{ decode_str(), count }
|
|
end
|
|
end
|
|
|
|
if is_infinite_research_enabled or technology_count ~= 0 then
|
|
tiers[#tiers + 1] = {
|
|
technology_count = technology_count,
|
|
bonus_per_technology = bonus_per_technology,
|
|
prerequisites = prerequisites,
|
|
cycle_count_formula = cycle_count_formula,
|
|
cycle_time = cycle_time,
|
|
cycle_ingredients = cycle_ingredients,
|
|
}
|
|
end
|
|
end
|
|
|
|
if category_map[name] then
|
|
decoded_categories[name] = tiers
|
|
else
|
|
log(('[qol] category with name %q in configuration is ignored'):format(name))
|
|
end
|
|
end
|
|
return decoded_categories
|
|
end
|
|
|
|
--[[
|
|
|
|
Structure represented as comma separated values:
|
|
config = {
|
|
version = 1
|
|
strings = count * escaped_string
|
|
categories = count * {
|
|
category_name = stringref
|
|
tiers = count * {
|
|
technology_count = int (0 means infinite)
|
|
bonus_per_technology = float
|
|
previous_tier_requirement = int (0 means no dependency)
|
|
other_requirements = count * stringref
|
|
cycle_count_formula = stringref
|
|
cycle_time = int
|
|
cycle_ingredients = count * {
|
|
count = int
|
|
name = stringref
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
count is an int
|
|
escaped_string is the string data with ',' replaced with ',,'
|
|
stringref is a 1-based index into strings, or 0 meaning empty string
|
|
|
|
int is unsigned 32-bit integer
|
|
float is IEEE-754 64-bit binary floating point
|
|
|
|
]]
|