compact atc_chains
This commit is contained in:
+1
-27789
File diff suppressed because one or more lines are too long
@@ -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())
|
||||||
+78
-17
@@ -79,40 +79,65 @@ 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
|
||||||
|
|
||||||
for _, item in ipairs(chain.items or {}) do
|
if chain.base_id then
|
||||||
if item.stage == "item" then
|
for _, item in ipairs(chain.items or {}) do
|
||||||
itemById[item.item_id] = {
|
if item.stage == "item" then
|
||||||
id = item.item_id,
|
itemById[item.item_id] = {
|
||||||
icon_nfp = item.icon_nfp_16x16,
|
id = item.item_id,
|
||||||
}
|
icon_nfp = item.icon_nfp_16x16,
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
itemCount = itemCount + 1
|
||||||
|
items[itemCount] = {
|
||||||
|
id = item.item_id,
|
||||||
|
icon_nfp = item.icon_nfp_16x16,
|
||||||
|
}
|
||||||
|
itemById[item.item_id] = items[itemCount]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
itemById[baseId] = {
|
||||||
|
id = baseId,
|
||||||
|
icon_nfp = chain[2],
|
||||||
|
}
|
||||||
|
|
||||||
|
for i = 1, #(chain[3] or {}) do
|
||||||
|
local compactItem = chain[3][i]
|
||||||
itemCount = itemCount + 1
|
itemCount = itemCount + 1
|
||||||
items[itemCount] = {
|
items[itemCount] = {
|
||||||
id = item.item_id,
|
id = compactItem[1],
|
||||||
icon_nfp = item.icon_nfp_16x16,
|
icon_nfp = compactItem[2],
|
||||||
}
|
}
|
||||||
itemById[item.item_id] = items[itemCount]
|
itemById[compactItem[1]] = items[itemCount]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
chainItemsByBaseId[chain.base_id] = items
|
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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user