Module:Item: Difference between revisions

From Space Station 14 Wiki
(added support for name skip markers in lookups)
(adjusted the code for removing duplicate IDs from the "names" JSON)
Line 36: Line 36:
if name_query == nil then  
if name_query == nil then  
error("Name query is nil")  
error("Name query is nil")  
end
-- check if name is an item ID in disguise
local match_by_id = item_names_by_item_id[name_query]
if match_by_id ~= nil then
-- if so - return the name = item ID
return name_query
end
end
-- otherwise look through the names for each item there is
local name_query_lower = string.lower(name_query)
local name_query_lower = string.lower(name_query)
for item_id, names in pairs(item_names_by_item_id) do
for item_id, names in pairs(item_names_by_item_id) do
for _, name in ipairs(names) do
for _, name in ipairs(names) do
Line 90: Line 97:
local names_length = numeric_table_length(names)  
local names_length = numeric_table_length(names)  
if names_length < 2 then
if names_length == 0 then
error("Expected item with ID'" .. id_query .. "' to have atleast 2 names: got " .. names_length)
error("Expected item with ID'" .. id_query .. "' to have atleast one name")
end
end
local main_name = names[2]
local main_name = names[1]
if string.find(main_name, skip_lookup_marker) ~= nil then
if string.find(main_name, skip_lookup_marker) ~= nil then
return string.sub(main_name, 1, string.len(main_name) - skip_lookup_marker_length_with_space - 1)
return string.sub(main_name, 1, string.len(main_name) - skip_lookup_marker_length_with_space - 1)

Revision as of 20:13, 17 August 2024

Module documentation
View or edit this documentation (about module documentation)

Implements {{Item}}.

Known items are synced regularly from the upstream, but things like icons and links must be defined manually. See #JSON files to see what data files there are, and see #FAQ on specific instructions.

JSON files

JSON files that are updated automatically, syncing with the upstream:

Warning
Do not make changes to the above JSON files - any changes made will be erased on next update.

JSON files that are filled manually:

FAQ

How to add new item?

New items are added automatically. This doesn't include icons - for that, see #How to add icon to item?.

Where to get item ID?

From Module:Item/item_names_by_item_ids.json.

How to add icon to item?

If you want to add multiple textures per single item, see #Adding multiple icons to item

1. Upload new icon to the wiki.

2. Go to Module:Item/item_image_files_by_item_id.json.

3. Add a new line. Follow the format: "<item ID>": "<file name>"

Example
"WeaponLaserCarbine": "laser rifle-East-35325.png"

4. Save the file. The icon should now appear when using {{item}}.

Adding multiple icons to item

Currently, the only supported use case if for items that have a different icon based on the amount of item.

1. Upload new icons to the wiki.

2. Go to Module:Item/item_image_files_by_item_id.json.

3. Add a new line. Follow the format:

Format
"<item ID>": {
	"default": "<default file name>",
	"byCondition": [
		{
			"type": "amount",
			"conditions": [
				{
					"file": "<file name 1>",
					"min": <minimum amount 1>
				},
				{
					"file": "<file name 2>",
					"min": <minimum amount 2>
				},
				{
					"file": "<file name 3>",
				}
			]
		}
	]
}
  • item ID - item ID to add icons for.
  • default file name - icon to use when amount is not specified.
  • file name 1/2/N - icons to use with specified amounts.
  • "min": <amount 1/2/N> - icon to use when there's at least this much of item.

Last condition entry (objects that have "file" and "min" fields) shouldn't have any condition in it (i.e. no "min" specified), because it will be used in cases where other conditions do not satisfy.

Conditions are evaluated top to bottom, meaning the file from the first one that satisfies will be used.

4. Save the file. The icons should now appear when using {{item}} and differ based on the amount.

How to add custom names to item?

When using {{item}}, you probably don't want to use item IDs because that's internal game info which is a pain in the ass to write. Gladly, there's an existing set of item names defined in Module:Item/item_ids_by_item_lowercase_names.json, which are human-readable. But not all existing items will have their names in there, because some names do repeat (for instance, various bottles named bottle).

To add new cool names and have them not be erased on new update (which happens to the JSON file linked in previous paragraph), add them to Module:Item/item_ids_by_item_lowercase_names_overrides.json. These will have higher priority and will be used instead. You can define as much "aliases" for an item ID as you wish.

Step-by-step: 1. Go to Module:Item/item_ids_by_item_lowercase_names_overrides.json.

2. Add a new line. Follow format: "<item lowercase name>": "<item ID>". Please note, that all items names defined here must be lowercase.

Example
"emag": "EmagUnlimited"

3. Save the file.

How to add a link to item?

To make {{item}} behave like a link all the time, a page link needs to be established in Module:Item/item page links by item ids.json. Please note, if you need a one-time link, use the link parameter in the {{item}} template.

1. Go to Module:Item/item_ids_by_item_lowercase_names_overrides.json.

2. Add a new line. Follow format: "<item ID>": "<page name>".

Example
"Protolathe": "Research_and_Development#Protolathe"

3. Save the file.

TODO

  • Ores are currently hardcoded into names overrides. Figure out a way to pull them from game resources. This is for Module:Item recipe.



-- Contains utilities for working with in-game items.

local p = {} --p stands for package
local getArgs = require('Module:Arguments').getArgs

-- A marker that can be used in item names for items with duplicates names across multiple items,
-- to skip a particular item on a lookup.
-- This should be added to the end of a name, separated with a space.
local skip_lookup_marker = "@@skip@@"
-- Length of the lookup marker with a space before it included.
local skip_lookup_marker_length_with_space = string.len(skip_lookup_marker) + 1

-- A table of items IDs mapped to their names.
local item_names_by_item_id = mw.loadJsonData("Module:Item/item names by item id.json")

-- A table of items IDs mapped to their image file names.
local item_image_by_item_id = mw.loadJsonData("Module:Item/item image files by item id.json")

function numeric_table_length(t)
  local count = 0
  for _ in ipairs(t) do count = count + 1 end
  return count
end

function table_length(t)
  local count = 0
  for _ in pairs(t) do count = count + 1 end
  return count
end

-- Lookups the item's ID by its name or an alias. 
-- Any casing is allowed.
function p.lookup_item_id_by_name(frame)
	local args = getArgs(frame)
	local name_query = args[1]
	if name_query == nil then 
		error("Name query is nil") 
	end

	-- check if name is an item ID in disguise 
	local match_by_id = item_names_by_item_id[name_query]
	if match_by_id ~= nil then
		-- if so - return the name = item ID
		return name_query
	end
	
	-- otherwise look through the names for each item there is
	local name_query_lower = string.lower(name_query)
	for item_id, names in pairs(item_names_by_item_id) do
		for _, name in ipairs(names) do
			if string.lower(name) == name_query_lower then
				return item_id
			end
		end
	end
	
	error("No item ID found for item with name: " .. name_query)
end

-- Lookups the item's image by its ID. 
-- The case must match.
function p.lookup_item_image_by_id(frame)
	local args = getArgs(frame)
	local id_query = args[1]
	if id_query == nil then 
		error("ID query is nil") 
	end
	
	local match = item_image_by_item_id[id_query]
	if match == nil then 
		error("No item image found by ID: " .. id_query .. ". Note that new images must be added manually to the module")
	end
	
	return match
end

-- Lookups the item's image by its name or an alias. 
-- Any casing is allowed.
-- A shorthand method.
function p.lookup_item_image_by_name(frame)
	return p.lookup_item_image_by_id(p.lookup_item_id_by_name(frame))
end

-- Lookups the item's name by its ID.
-- The case must match.
function p.lookup_item_name_by_id(frame)
	local args = getArgs(frame)
	local id_query = args[1]
	if id_query == nil then 
		error("ID query is nil") 
	end
	
	local names = item_names_by_item_id[id_query]
	if names == nil then 
		error("No item names found by ID: " .. id_query)
	end
	
	local names_length = numeric_table_length(names) 
	if names_length == 0 then
		error("Expected item with ID'" .. id_query .. "' to have atleast one name")
	end
	
	local main_name = names[1]
	if string.find(main_name, skip_lookup_marker) ~= nil then
		return string.sub(main_name, 1, string.len(main_name) - skip_lookup_marker_length_with_space - 1)
	end
	
	return main_name
end

function p.generate_item_icons_for_all_items_with_icons(frame)
	local args = getArgs(frame)
	local columns_count = args[1]
	if columns_count == nil then 
		error("columns count is nil") 
	end

	local container = mw.html.create("div")
		:css("column-count", columns_count)
	
	-- an array of item ids that have images
	local item_ids_with_images = {}
	for item_id, _ in pairs(item_image_by_item_id) do
		table.insert(item_ids_with_images, item_id)
	end
	
	-- sort alphabetically
	table.sort(item_ids_with_images, function (first, second)
	    return p.lookup_item_name_by_id({ [1] = first }) < p.lookup_item_name_by_id({ [1] = second })
	end)
	
	-- generate child elements from the template
	for _, item_id in ipairs(item_ids_with_images) do
		container:node(frame:preprocess("<div>{{item|" .. item_id .. "}}</div>"))
	end
		
	return container
		:allDone()
end

return p