Compare commits

...

24 commits

Author SHA1 Message Date
Simon Brodtmann
5a0f1975ef 1.2.0 2025-12-14 18:22:36 +01:00
Simon Brodtmann
7509698888 Add class Entity 2025-12-14 18:08:19 +01:00
Simon Brodtmann
cd5bdaa59f 1.1.0 2025-12-12 23:13:08 +01:00
Simon Brodtmann
5507f65131 Settings.force also sets default_value 2025-12-12 18:52:56 +01:00
Simon Brodtmann
6de1a8f1c7 Add Recipe:addCategory 2025-12-12 18:36:25 +01:00
Simon Brodtmann
a6f495af8b Add Item:defaultImportLocation 2025-12-12 18:36:15 +01:00
Simon Brodtmann
bf7d05e3be 1.0.0 2025-11-23 19:02:37 +01:00
Simon Brodtmann
a9782564bf Add Recipe:addResult 2025-11-23 19:02:28 +01:00
Simon Brodtmann
7a18ca0c3b Add Recipe:removeResult 2025-11-12 10:22:20 +01:00
Simon Brodtmann
c2392a687c Add class Settings 2025-11-12 00:56:00 +01:00
Simon Brodtmann
6ca6034186 Add table.filterKey 2025-11-12 00:31:56 +01:00
Simon Brodtmann
e4ad298324 Add Discord link 2025-09-15 18:14:02 +02:00
Simon Brodtmann
8ded39211b 0.0.14 2025-06-10 19:47:39 +02:00
Simon Brodtmann
9878331df5 Add :merge 2025-05-31 22:55:18 +02:00
Simon Brodtmann
a9457f7c38 0.0.13 2025-05-23 21:04:51 +02:00
Simon Brodtmann
8e637400a5 Add class Item 2025-05-23 21:03:59 +02:00
Simon Brodtmann
3ce2d83c22 0.0.12 2025-04-06 16:43:54 +02:00
Simon Brodtmann
36dba7614e Add table.count 2025-04-06 16:43:21 +02:00
Simon Brodtmann
bbcc586128 0.0.11 2025-03-28 18:55:11 +01:00
Simon Brodtmann
c36fd418ab Add Technology:setIngredients 2025-03-28 18:54:28 +01:00
Simon Brodtmann
620c9f48cf 0.0.10 2025-03-16 18:42:02 +01:00
Simon Brodtmann
ea7785c761 Functions are chainable 2025-03-16 18:40:40 +01:00
Simon Brodtmann
27d9dd6c68 Recipe: addIngredient amount defaults to 1 2025-03-14 18:13:37 +01:00
Simon Brodtmann
be0781340a Rename table.concat to table.concatTables to resolve conflict 2025-02-28 23:16:17 +01:00
8 changed files with 342 additions and 27 deletions

View file

@ -1,4 +1,56 @@
--------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------
Version: 1.2.0
Date: 14.12.2025
Changes:
- Add class Entity
---------------------------------------------------------------------------------------------------
Version: 1.1.0
Date: 12.12.2025
Changes:
- Add Item:defaultImportLocation
- Add Recipe:addCategory
Bug Fixes:
- Settings.force also sets default_value
---------------------------------------------------------------------------------------------------
Version: 1.0.0
Date: 23.11.2025
Changes:
- Add table.filterKey
- Add class Settings
- Add Recipe:removeResult
- Add Recipe:addResult
---------------------------------------------------------------------------------------------------
Version: 0.0.14
Date: 10.06.2025
Changes:
- Add :merge
---------------------------------------------------------------------------------------------------
Version: 0.0.13
Date: 23.05.2025
Changes:
- Add Item class
---------------------------------------------------------------------------------------------------
Version: 0.0.12
Date: 06.04.2025
Changes:
- Add table.count
---------------------------------------------------------------------------------------------------
Version: 0.0.11
Date: 28.03.2025
Changes:
- Add Technology:setIngredients
---------------------------------------------------------------------------------------------------
Version: 0.0.10
Date: 16.03.2025
Changes:
- Recipe: addIngredient amount defaults to 1
- Functions are chainable
---------------------------------------------------------------------------------------------------
Version: 0.0.9
Date: 28.02.2025
Bug Fixes:
- Rename `table.concat` to `table.concatTables` to resolve conflict
---------------------------------------------------------------------------------------------------
Version: 0.0.8 Version: 0.0.8
Date: 28.02.2025 Date: 28.02.2025
Changes: Changes:

29
cf-lib/data/Entity.lua Normal file
View file

@ -0,0 +1,29 @@
--- Utility class for entity prototype definitions
--- @class Entity
local Entity = {}
--- Generates a selection box definition using width and height of the entity in tiles.
--- @param width number The width of the entity in tiles
--- @param height number The height of the entity in tiles
--- @return table A table containing the selection box definition
Entity.selectionBox = function(width, height)
return {
{ -width / 2, -height / 2 },
{ width / 2, height / 2 }
}
end
--- Generates a collision box definition using width and height of the entity in tiles.
--- @param width number The width of the entity in tiles
--- @param height number The height of the entity in tiles
--- @param margin number The margin to apply to the collision box compared to the selection box (default: 0.3)
--- @return table A table containing the collision box definition
Entity.collisionBox = function(width, height, margin)
margin = margin or 0.1
return {
{ -width / 2 + margin, -height / 2 + margin },
{ width / 2 - margin, height / 2 - margin }
}
end
return Entity

67
cf-lib/data/Item.lua Normal file
View file

@ -0,0 +1,67 @@
--- Utility class for a single item
--- @class Item
local Item = {}
--- Pass an item name or an item table to get a Item object
--- @param value string|table The name of the item or the item table
function Item:new(value)
local name
local item
if type(value) == "string" then
name = value
item = data.raw.item[name]
if not item then
log("Item not found: " .. name)
return nil
end
elseif type(value) == "table" then
name = value.name
item = value
end
local obj = {
prototype = item
}
setmetatable(obj, self)
self.__index = self
return obj
end
--- Applies the item to the game
function Item:apply()
data:extend({ self.prototype })
end
--- Assigns data to the item
--- Shorthand for table.assign(item.prototype, data)
--- @param data table The data to assign
function Item:assign(data)
table.assign(self.prototype, data)
return self
end
--- Deeply merges data with the item
--- Shorthand for table.merge(item.prototype, data)
--- @param data table The data to merge
function Item:merge(data)
table.merge(self.prototype, data)
return self
end
--- Sets the weight of the item calculated from given count per rocket.
--- @param count number The amount of items that fit into a rocket
function Item:itemsPerRocket(count)
self.prototype.weight = (1000 / count) * kg
return self
end
--- Sets the default import location for space platforms
--- @param planetName string The name of the planet
function Item:defaultImportLocation(planetName)
self.prototype.default_import_location = planetName
return self
end
return Item

View file

@ -1,9 +1,9 @@
---- Utility class for a single recipe --- Utility class for a single recipe
---- @class Recipe --- @class Recipe
local Recipe = {} local Recipe = {}
---- Pass a recipe name or a recipe table to get a Recipe object --- Pass a recipe name or a recipe table to get a Recipe object
---- @param value string|table The name of the recipe or the recipe table --- @param value string|table The name of the recipe or the recipe table
function Recipe:new(value) function Recipe:new(value)
local name local name
local recipe local recipe
@ -29,22 +29,32 @@ function Recipe:new(value)
return obj return obj
end end
---- Applies the recipe to the game --- Applies the recipe to the game
function Recipe:apply() function Recipe:apply()
data:extend({ self.prototype }) data:extend({ self.prototype })
end end
---- Assigns data to the recipe --- Assigns data to the recipe
---- Shorthand for table.assign(recipe.prototype, data) --- Shorthand for table.assign(recipe.prototype, data)
---- @param data table The data to assign --- @param data table The data to assign
function Recipe:assign(data) function Recipe:assign(data)
table.assign(self.prototype, data) table.assign(self.prototype, data)
return self
end
--- Deeply merges data with the recipe
--- Shorthand for table.merge(recipe.prototype, data)
--- @param data table The data to merge
function Recipe:merge(data)
table.merge(self.prototype, data)
return self
end end
--- Adds an ingredient to the recipe --- Adds an ingredient to the recipe
--- @param ingredientName string The name of the ingredient --- @param ingredientName string The name of the ingredient
--- @param amount number The amount of the ingredient --- @param amount number The amount of the ingredient (default: 1)
function Recipe:addIngredient(ingredientName, amount) function Recipe:addIngredient(ingredientName, amount)
amount = amount or 1
local ingredientType = data.raw.item[ingredientName] and "item" local ingredientType = data.raw.item[ingredientName] and "item"
or data.raw.module[ingredientName] and "item" or data.raw.module[ingredientName] and "item"
or data.raw.fluid[ingredientName] and "fluid" or data.raw.fluid[ingredientName] and "fluid"
@ -60,10 +70,11 @@ function Recipe:addIngredient(ingredientName, amount)
ingredient.amount_min = nil ingredient.amount_min = nil
ingredient.amount_max = nil ingredient.amount_max = nil
ingredient.probability = nil ingredient.probability = nil
return return self
end end
end end
table.insert(self.prototype.ingredients, { name = ingredientName, amount = amount, type = ingredientType }) table.insert(self.prototype.ingredients, { name = ingredientName, amount = amount, type = ingredientType })
return self
end end
--- Replaces an existing ingredient by name with a new ingredient or adjusts the amount --- Replaces an existing ingredient by name with a new ingredient or adjusts the amount
@ -80,33 +91,71 @@ function Recipe:replaceIngredient(old, new, amount)
if result.name == old then if result.name == old then
result.name = new result.name = new
result.amount = amount or result.amount result.amount = amount or result.amount
return return self
end end
end end
end end
return self
end end
--- Removes an existing ingredient by name --- Removes an existing ingredient by name
--- @param ingredientName string The name of the ingredient --- @param ingredientName string The name of the ingredient
function Recipe:removeIngredient(ingredientName) function Recipe:removeIngredient(ingredientName)
if self.prototype.ingredients then if self.prototype.ingredients then
for i, result in pairs(self.prototype.ingredients) do for i, ingredient in pairs(self.prototype.ingredients) do
if result.name == ingredientName then if ingredient.name == ingredientName then
self.prototype.ingredients[i] = nil table.remove(self.prototype.ingredients, i)
return return self
end end
end end
end end
return self
end
--- Adds a result to the recipe
--- @param resultName string The name of the result
--- @param amount number|table The amount of the result (default: 1) or a table with custom properties
function Recipe:addResult(resultName, amount)
local props = amount
if type(props) == "string" then
props = { amount = props }
end
if not props.amount then
props.amount = 1
end
local resultType = data.raw.item[resultName] and "item"
or data.raw.module[resultName] and "item"
or data.raw.fluid[resultName] and "fluid"
or nil
if not resultType then
log("Unknown result: " .. resultName)
return
end
self.prototype.results = self.prototype.results or {}
for _, result in pairs(self.prototype.results) do
if result.name == resultName then
result.amount = nil
result.amount_min = nil
result.amount_max = nil
result.probability = nil
for k, v in pairs(props) do
result[k] = v
end
return self
end
end
props.name = resultName
props.type = resultType
table.insert(self.prototype.results, props)
return self
end end
--- Replaces an existing result by name with a new result --- Replaces an existing result by name with a new result
--- @param old string The name of the existing result --- @param old string The name of the existing result
--- @param new? string The name of the new result --- @param new? string The name of the new result
--- @param amount? number The amount of the new result (keeps the old value if not set) --- @param amount? number The amount of the new result (keeps the old value if not set)
--- @param expensiveAmount? number The amount of the new result for the expensive recipe (uses amount if not set) function Recipe:replaceResult(old, new, amount)
function Recipe:replaceResult(old, new, amount, expensiveAmount)
if type(new) == "number" then if type(new) == "number" then
expensiveAmount = amount
amount = new amount = new
new = old new = old
end end
@ -121,6 +170,32 @@ function Recipe:replaceResult(old, new, amount, expensiveAmount)
table.main_product = new table.main_product = new
end end
end end
return self
end
--- Removes an existing result by name
--- @param resultName string The name of the result
function Recipe:removeResult(resultName)
if self.prototype.results then
for i, result in pairs(self.prototype.results) do
if result.name == resultName then
table.remove(self.prototype.results, i)
return self
end
end
end
return self
end
--- Adds an additional crafting category
--- @param categoryName string The name of the crafting category
function Recipe:addCategory(categoryName)
local categories = self.prototype.additional_categories or {}
self.prototype.additional_categories = categories
if not table.contains(categories, categoryName) then
table.insert(categories, categoryName)
end
return self
end end
--- Adds the recipe to a technology --- Adds the recipe to a technology
@ -135,14 +210,15 @@ function Recipe:unlockedByTechnology(technology)
end end
for _, effect in pairs(technology.effects) do for _, effect in pairs(technology.effects) do
if effect.type == "unlock-recipe" and effect.recipe == self.prototype.name then if effect.type == "unlock-recipe" and effect.recipe == self.prototype.name then
return return self
end end
end end
table.insert(technology.effects, { type = "unlock-recipe", recipe = self.prototype.name }) table.insert(technology.effects, { type = "unlock-recipe", recipe = self.prototype.name })
return self
end end
---- Clones the recipe --- Clones the recipe
---- @param name string The name of the new recipe --- @param name string The name of the new recipe
function Recipe:clone(name) function Recipe:clone(name)
local clone = table.deepcopy(self.prototype) local clone = table.deepcopy(self.prototype)
clone.name = name clone.name = name

View file

@ -47,12 +47,22 @@ end
--- @param data table The data to assign --- @param data table The data to assign
function Technology:assign(data) function Technology:assign(data)
table.assign(self.prototype, data) table.assign(self.prototype, data)
return self
end
--- Deeply merges data with the technology
--- Shorthand for table.merge(technology.prototype, data)
--- @param data table The data to merge
function Technology:merge(data)
table.merge(self.prototype, data)
return self
end end
--- Sets the prerequisite for the technology --- Sets the prerequisite for the technology
--- @param prerequisites table The names of the prerequisites --- @param prerequisites table The names of the prerequisites
function Technology:setPrerequisites(prerequisites) function Technology:setPrerequisites(prerequisites)
self.prototype.prerequisites = prerequisites self.prototype.prerequisites = prerequisites
return self
end end
--- Adds a prerequisite to the technology --- Adds a prerequisite to the technology
@ -63,6 +73,7 @@ function Technology:addPrerequisite(prerequisite)
if (not table.contains(self.prototype.prerequisites, _prerequisite)) then if (not table.contains(self.prototype.prerequisites, _prerequisite)) then
table.insert(self.prototype.prerequisites, _prerequisite) table.insert(self.prototype.prerequisites, _prerequisite)
end end
return self
end end
--- Adds multiple prerequisites to the technology --- Adds multiple prerequisites to the technology
@ -75,6 +86,7 @@ function Technology:addPrerequisites(prerequisites)
table.insert(self.prototype.prerequisites, _prerequisite) table.insert(self.prototype.prerequisites, _prerequisite)
end end
end end
return self
end end
--- Replaces a prerequisite in a technology --- Replaces a prerequisite in a technology
@ -88,6 +100,7 @@ function Technology:replacePrerequisite(old, new)
self.prototype.prerequisites[i] = _new self.prototype.prerequisites[i] = _new
end end
end end
return self
end end
--- Removes a prerequisite from the technology --- Removes a prerequisite from the technology
@ -97,9 +110,10 @@ function Technology:removePrerequisite(prerequisite)
for i, techPrerequisite in pairs(self.prototype.prerequisites) do for i, techPrerequisite in pairs(self.prototype.prerequisites) do
if techPrerequisite == _prerequisite then if techPrerequisite == _prerequisite then
table.remove(self.prototype.prerequisites, i) table.remove(self.prototype.prerequisites, i)
return return self
end end
end end
return self
end end
--- Adds an ingredient to the technology --- Adds an ingredient to the technology
@ -109,6 +123,7 @@ function Technology:addIngredient(ingredientName, amount)
self.prototype.unit = self.prototype.unit or { ingredients = {} } self.prototype.unit = self.prototype.unit or { ingredients = {} }
self.prototype.unit.ingredients = self.prototype.unit.ingredients or {} self.prototype.unit.ingredients = self.prototype.unit.ingredients or {}
table.insert(self.prototype.unit.ingredients, { ingredientName, amount or 1 }) table.insert(self.prototype.unit.ingredients, { ingredientName, amount or 1 })
return self
end end
--- Adds a list of ingredients to the technology with the default amount of 1 --- Adds a list of ingredients to the technology with the default amount of 1
@ -117,6 +132,7 @@ function Technology:addIngredients(ingredientNames)
for _, ingredientName in pairs(ingredientNames) do for _, ingredientName in pairs(ingredientNames) do
self:addIngredient(ingredientName) self:addIngredient(ingredientName)
end end
return self
end end
--- Removes an existing ingredient by name --- Removes an existing ingredient by name
@ -129,6 +145,16 @@ function Technology:removeIngredient(ingredientName)
end end
end end
end end
return self
end
--- Sets the ingredients for the technology
--- @param ingredientNames table The names of the ingredients
function Technology:setIngredients(ingredients)
self.prototype.unit = self.prototype.unit or {}
self.prototype.unit.ingredients = {}
self:addIngredients(ingredients)
return self
end end
--- Adds a recipe unlock to the technology --- Adds a recipe unlock to the technology
@ -136,16 +162,18 @@ end
function Technology:addRecipe(recipeName) function Technology:addRecipe(recipeName)
for _, effect in pairs(self.prototype.effects) do for _, effect in pairs(self.prototype.effects) do
if effect.type == "unlock-recipe" and effect.recipe == recipeName then if effect.type == "unlock-recipe" and effect.recipe == recipeName then
return return self
end end
end end
table.insert(self.prototype.effects, { type = "unlock-recipe", recipe = recipeName }) table.insert(self.prototype.effects, { type = "unlock-recipe", recipe = recipeName })
return self
end end
--- Adds an effect to the technology --- Adds an effect to the technology
--- @param effect table The effect to add --- @param effect table The effect to add
function Technology:addEffect(effect) function Technology:addEffect(effect)
table.insert(self.prototype.effects, effect) table.insert(self.prototype.effects, effect)
return self
end end
--- Removes a recipe unlock from the technology --- Removes a recipe unlock from the technology
@ -154,9 +182,10 @@ function Technology:removeRecipe(recipeName)
for i, effect in pairs(self.prototype.effects) do for i, effect in pairs(self.prototype.effects) do
if effect.type == "unlock-recipe" and effect.recipe == recipeName then if effect.type == "unlock-recipe" and effect.recipe == recipeName then
table.remove(self.prototype.effects, i) table.remove(self.prototype.effects, i)
return return self
end end
end end
return self
end end
--- Clones the technology --- Clones the technology

View file

@ -1,10 +1,10 @@
{ {
"name": "cf-lib", "name": "cf-lib",
"version": "0.0.8", "version": "1.2.0",
"title": "cackling fiends library", "title": "cackling fiends library",
"description": "Because I'd like to have my own library :-)", "description": "Because I'd like to have my own library :-)",
"author": "cackling fiend", "author": "cackling fiend",
"homepage": "", "homepage": "https://discord.gg/ufvFUJtVwk",
"factorio_version": "2.0", "factorio_version": "2.0",
"dependencies": [ "dependencies": [
"base" "base"

View file

@ -0,0 +1,39 @@
--- Utility class for manipulating settings
--- @class Settings
local Settings = {}
local settingTypes = { "bool-setting", "int-setting", "double-setting", "string-setting", "color-setting" }
local function getSetting(name)
for _, settingType in pairs(settingTypes) do
local setting = data.raw[settingType][name]
if setting then return setting end
end
error("getSetting: Setting with name '" .. name .. "' not found.")
end
Settings.getSetting = getSetting
function Settings.force(name, value)
local setting = getSetting(name)
setting.hidden = true
if setting.type == "bool-setting" or setting.type == "color-setting" then
setting.forced_value = value
else
setting.allowed_values = { value }
setting.default_value = value
end
end
function Settings.default(name, value)
local setting = getSetting(name)
setting.default_value = value
end
function Settings.forceDefault(name)
local setting = getSetting(name)
local value = setting.default_value
Settings.force(name, value)
end
return Settings

View file

@ -70,11 +70,23 @@ function table.filter(target, predicate)
return result return result
end end
--- Filters a table by removing given key.
--- @param target table The table to filter
--- @param key string The key to remove
function table.filterKey(target, key)
return table.filter(
target,
function(_, currentKey)
return currentKey ~= key
end
)
end
--- Concatenates two tables into a new table. --- Concatenates two tables into a new table.
--- @param table1 table The first table --- @param table1 table The first table
--- @param table2 table The second table --- @param table2 table The second table
--- @return table The concatenated table --- @return table The concatenated table
function table.concat(table1, table2) function table.concatTables(table1, table2)
local result = {} local result = {}
for _, v in pairs(table1) do for _, v in pairs(table1) do
table.insert(result, v) table.insert(result, v)
@ -92,4 +104,15 @@ function table.trim(target)
return table.filter(target, function(v) return table.filter(target, function(v)
return v ~= nil return v ~= nil
end) end)
end
--- Counts the entries of given table.
--- @param target table Table to count
--- @return number Amount of entries
function table.count(target)
local count = 0
for _ in pairs(target) do
count = count + 1
end
return count
end end