Nooncraft/converters.py

125 lines
3.2 KiB
Python

import fxconv
import yaml
def convert(input, output, params, target):
recognized = True
if params["custom-type"] == "blockinfo":
o = convert_blockinfo(input, params)
elif params["custom-type"] == "iteminfo":
o = convert_iteminfo(input, params)
else:
recognized = False
if recognized:
fxconv.elf(o, output, "_" + params["name"], **target)
return 0
return 1
def mkBreakability(br):
return fxconv.u8({
None: 0,
"Fluid": 0,
"ByAnything": 1,
"ByTool": 2,
"Unbreakable": 3,
}[br])
def mkToolKind(tk):
return fxconv.u8({
None: 0xff,
"Pickaxe": 0,
"Axe": 1,
"Shovel": 2,
"Hoe": 3,
}[tk])
def mkBool(b):
if isinstance(b, str):
b = b.lower()
return fxconv.u8(b in [True, "yes", "true"])
def mkGlyph(s):
assert len(s) == 1
special = {
0x2058: 1,
0x00B7: 2,
0x2225: 3,
0x00A4: 4,
0x2197: 5,
0x00BB: 6,
0x2193: 7,
0x00EE: 8,
0x222B: 9,
0x25AA: 10,
0x2605: 11,
0x25CF: 12,
0x21A5: 13,
0x039B: 14,
# 15 is combined with a diacritic (from CASIO's custom charset)
0x2295: 16,
0x25A1: 0x7f,
}
if ord(s) >= 0x20 and ord(s) <= 0x7f:
return fxconv.u8(ord(s))
elif ord(s) in special:
return fxconv.u8(special[ord(s)])
else:
raise ValueError(f"unknown glyph {s}")
def mkGlyphCluster(str):
assert len(str) == 4
return b"".join(mkGlyph(s) for s in str)
def convert_blockinfo(input, params):
with open(input, "r") as fp:
data = yaml.safe_load(fp.read())
o = fxconv.ObjectData()
for b in data:
# Make sure there are no typos in the fields
assert (f in ["name", "breakability", "toolKind",
"baseBreakDurationTicks", "walkable", "replaceable"] for f in b)
# If a tool is specified, default to Breakability::ByTool
tk = b.get("toolKind", None)
br = b.get("breakability", "ByTool" if tk is not None else "ByAnything")
o += fxconv.string(b["name"])
o += mkGlyphCluster(b["cluster"])
o += mkBreakability(br)
o += mkToolKind(tk)
o += fxconv.u16(int(b.get("breakingTime", 20)))
o += mkBool(b.get("walkable", False))
o += mkBool(b.get("replaceable", False))
o += bytes(2)
o += fxconv.sym("Nooncraft_blockInfoCount")
o += fxconv.u32(len(data))
return o
def convert_iteminfo(input, params):
with open(input, "r") as fp:
data = yaml.safe_load(fp.read())
o = fxconv.ObjectData()
for i in data:
# Make sure there are no typos in the fields
assert (f in ["name", "cluster", "toolKind", "toolLevel", "stackSize"]
for f in i)
tk = i.get("toolKind", None)
o += fxconv.string(i["name"])
o += mkGlyphCluster(i["cluster"])
o += fxconv.u8(tk is not None)
o += mkToolKind(tk)
o += fxconv.u8(0 if tk is None else i["toolLevel"])
o += fxconv.u8(int(i.get("stackSize", 1 if tk is not None else 64)))
o += fxconv.sym("Nooncraft_itemInfoCount")
o += fxconv.u32(len(data))
return o