compact atc_chains

This commit is contained in:
Max
2026-06-01 14:45:09 +02:00
parent 816a28986c
commit 862aa03549
3 changed files with 169 additions and 27806 deletions
+1 -27789
View File
File diff suppressed because one or more lines are too long
+90
View File
@@ -0,0 +1,90 @@
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import json
from pathlib import Path
def crop_icon(icon: str | None) -> list[int | str] | None:
if not icon:
return None
lines = icon.split("\n")
xs: list[int] = []
ys: list[int] = []
for y, line in enumerate(lines):
for x, char in enumerate(line):
if char != " ":
xs.append(x)
ys.append(y)
if not xs:
return [0, 0, ""]
min_x = min(xs)
max_x = max(xs)
min_y = min(ys)
max_y = max(ys)
cropped_lines = [line[min_x : max_x + 1].rstrip() for line in lines[min_y : max_y + 1]]
return [min_x, min_y, "\n".join(cropped_lines)]
def compact_chains(data: object) -> list[list[object]]:
if isinstance(data, dict):
chains = data.get("chains")
else:
chains = data
if not isinstance(chains, list):
raise ValueError("Input JSON does not contain a valid chains array")
compact: list[list[object]] = []
for chain in chains:
if not isinstance(chain, dict):
raise ValueError("Expected verbose chain objects as input")
items = chain.get("items")
if not isinstance(items, list) or not items:
continue
base_id = chain["base_id"]
base_icon = crop_icon(items[0].get("icon_nfp_16x16"))
compact_items = []
for item in items[1:]:
compact_items.append([
item["item_id"],
crop_icon(item.get("icon_nfp_16x16")),
])
compact.append([base_id, base_icon, compact_items])
return compact
def main() -> int:
parser = argparse.ArgumentParser(
description="Rewrite atc_chains.json into a compact format used by compcount.lua."
)
parser.add_argument("path", nargs="?", default="atc_chains.json")
args = parser.parse_args()
path = Path(args.path)
original_text = path.read_text(encoding="utf-8")
data = json.loads(original_text)
compact = compact_chains(data)
compact_text = json.dumps(compact, separators=(",", ":"))
path.write_text(compact_text, encoding="utf-8")
print(f"Rewrote {path}")
print(f"Old size: {len(original_text.encode('utf-8'))} bytes")
print(f"New size: {len(compact_text.encode('utf-8'))} bytes")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+68 -7
View File
@@ -79,23 +79,32 @@ local function ensureChainsLoaded()
local data = textutils.unserializeJSON(file.readAll()) local data = textutils.unserializeJSON(file.readAll())
file.close() file.close()
assert(type(data) == "table" and type(data.chains) == "table", "Invalid JSON data") local chains = data
if type(data) == "table" and type(data.chains) == "table" then
chains = data.chains
end
assert(type(chains) == "table", "Invalid JSON data")
chainItemsByBaseId = {} chainItemsByBaseId = {}
baseItemIds = {} baseItemIds = {}
itemById = {} itemById = {}
for _, chain in ipairs(data.chains) do for _, chain in ipairs(chains) do
if not whitelistLookup or whitelistLookup[chain.base_id] then local baseId = chain.base_id or chain[1]
if not whitelistLookup or whitelistLookup[baseId] then
if not defaultBaseId then if not defaultBaseId then
defaultBaseId = chain.base_id defaultBaseId = baseId
end end
baseItemIds[#baseItemIds + 1] = chain.base_id baseItemIds[#baseItemIds + 1] = baseId
local items = {} local items = {}
local itemCount = 0 local itemCount = 0
if chain.base_id then
for _, item in ipairs(chain.items or {}) do for _, item in ipairs(chain.items or {}) do
if item.stage == "item" then if item.stage == "item" then
itemById[item.item_id] = { itemById[item.item_id] = {
@@ -111,8 +120,24 @@ local function ensureChainsLoaded()
itemById[item.item_id] = items[itemCount] itemById[item.item_id] = items[itemCount]
end end
end end
else
itemById[baseId] = {
id = baseId,
icon_nfp = chain[2],
}
chainItemsByBaseId[chain.base_id] = items for i = 1, #(chain[3] or {}) do
local compactItem = chain[3][i]
itemCount = itemCount + 1
items[itemCount] = {
id = compactItem[1],
icon_nfp = compactItem[2],
}
itemById[compactItem[1]] = items[itemCount]
end
end
chainItemsByBaseId[baseId] = items
end end
end end
end end
@@ -164,13 +189,49 @@ local function parseNfpImage(nfp)
return image return image
end end
local function parseIconData(iconData)
if type(iconData) == "string" then
return parseNfpImage(iconData)
end
if type(iconData) ~= "table" then
return nil
end
local offsetX = tonumber(iconData[1]) or 0
local offsetY = tonumber(iconData[2]) or 0
local croppedImage = parseNfpImage(iconData[3])
if not croppedImage then
return nil
end
if offsetX == 0 and offsetY == 0 then
return croppedImage
end
local image = {}
for y, row in pairs(croppedImage) do
local shiftedRow = {}
for x, value in pairs(row) do
shiftedRow[x + offsetX] = value
end
image[y + offsetY] = shiftedRow
end
return image
end
local function getItemIcon(item) local function getItemIcon(item)
if not item then if not item then
return nil return nil
end end
if item.icon == nil then if item.icon == nil then
item.icon = parseNfpImage(item.icon_nfp) or false item.icon = parseIconData(item.icon_nfp) or false
item.icon_nfp = nil item.icon_nfp = nil
end end