d1961e79fc
Integrate 182 upstream commits throughb2473e60while retaining MoonWell packaging, branding and the community ruRU pack. Upstream replaces the C Lua/mlua host with benilla-lua/benilla-mlua and the native glue screens with stock GlueXML. The update also includes the new locale/DBC/name rules, cache and interaction handling, rendering, quest log and chat behavior, including the latest quest completion and timed-quest failure fixes. Fork adaptations use the new APIs: stock Wow.ini locales remain intact, while the ruRU overlay reads column zero and retains its ruRU authentication tag and Lua identity. Russian names keep their twelve-letter policy and Unicode roster matching; fonts, spell costs, race/class labels and translated options retain real-pack regression coverage. Windows regression fixes keep the locale-default test valid under instrumented window overrides and the shader assertion independent of checkout line endings. The original C Lua 5.1 host, rebuilt fromc0630f3din an isolated directory, reproduces the complete Windows cos-sweep answer byte for byte; cos now uses platform-specific goldens. Validation on Windows: scripts/gates.sh passed all automatic gates, including real-data and no-install workspace tests, reference tables, documentation, message catalog, render-pass lint, player clippy/tests and engine boots with and without data. MoonWell player clippy also passed with -D warnings. The committed tree exactly matches the full green stamp; five vendored Kira files retain the tested checkout's line endings, with normalized contents unchanged. All three actual ruRU pack regressions passed in both builds. Fifteen test archives were restored read-only from the published client and SHA-256 checked. Each real-data/player rung skipped 31 tests because the optional addon corpus is absent (24 general, 7 Quiver). Live smoke was not run: no declared probe account; no player-account login or character creation was performed. Linux/macOS changes were not locally built.
104 lines
3.8 KiB
Python
Executable File
104 lines
3.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
r"""Generate `crates/benilla-ui/src/messages/catalog.rs` from `reference/messages.tsv`.
|
|
|
|
The table is the reference's message registry at `0xb4b498`, which `CGGameUI::DisplayError`
|
|
`0x496720` indexes by message id; this re-shapes it into a Rust static that ships with benilla.
|
|
|
|
python3 scripts/gen-message-catalog.py # the vendored table -> the .rs, in place
|
|
python3 scripts/gen-message-catalog.py --check # fail when the .rs is not what it generates
|
|
python3 scripts/gen-message-catalog.py <tsv> # another table
|
|
|
|
It refuses rather than emits on a non-dense id range, a duplicate key or an unknown kind.
|
|
"""
|
|
import os
|
|
import sys
|
|
|
|
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
TABLE = os.path.join(REPO, "reference", "messages.tsv")
|
|
OUT = os.path.join(REPO, "crates", "benilla-ui", "src", "messages", "catalog.rs")
|
|
|
|
KINDS = {0: "Chat", 1: "Info", 2: "Error"}
|
|
|
|
HEADER = """\
|
|
//! The 1.12 client's message catalog, row for row.
|
|
//!
|
|
//! @generated by `scripts/gen-message-catalog.py` from `reference/messages.tsv`.
|
|
//! Do not edit by hand; regenerate.
|
|
|
|
use super::{MessageRecord, MsgKind};
|
|
|
|
/// Every row of `0xb4b498`, indexed by message id: the ids are dense `0..465`, so `CATALOG[id]`
|
|
/// is the reference's `0xb4b498 + 20*id`.
|
|
///
|
|
/// `rustfmt` is off: the generator emits one row per line, and a rewrap would drift from it.
|
|
#[rustfmt::skip]
|
|
pub static CATALOG: [MessageRecord; {count}] = [
|
|
"""
|
|
|
|
|
|
def main(path: str, check: bool = False) -> int:
|
|
if not os.path.exists(path):
|
|
raise SystemExit(f"no table at {path}")
|
|
rows = []
|
|
for line in open(path):
|
|
if line.startswith("id\t"):
|
|
continue
|
|
f = line.rstrip("\n").split("\t")
|
|
if len(f) != 7:
|
|
raise SystemExit(f"malformed row (expected 7 fields, got {len(f)}): {line!r}")
|
|
rows.append(
|
|
{
|
|
"id": int(f[0]),
|
|
"key": f[2],
|
|
"kind": int(f[3]),
|
|
"sound": f[4],
|
|
"type_tag": int(f[5], 16),
|
|
"chat_type": int(f[6]),
|
|
}
|
|
)
|
|
|
|
for want, r in enumerate(rows):
|
|
if r["id"] != want:
|
|
raise SystemExit(f"ids are not dense: expected {want}, got {r['id']}")
|
|
keys = [r["key"] for r in rows]
|
|
if len(set(keys)) != len(keys):
|
|
raise SystemExit("duplicate key in the catalog — by_key would be ambiguous")
|
|
for r in rows:
|
|
if r["kind"] not in KINDS:
|
|
raise SystemExit(
|
|
f"row {r['id']} ({r['key']}) has kind {r['kind']}, which MsgKind does not model"
|
|
)
|
|
|
|
out = [HEADER.replace("{count}", str(len(rows)))]
|
|
for r in rows:
|
|
sound = "None" if r["sound"] == "NONE" else f'Some("{r["sound"]}")'
|
|
out.append(
|
|
f' MessageRecord {{ id: {r["id"]}, key: "{r["key"]}", '
|
|
f'kind: MsgKind::{KINDS[r["kind"]]}, sound: {sound}, '
|
|
f'type_tag: {r["type_tag"]:#04x}, chat_type: {r["chat_type"]} }},\n'
|
|
)
|
|
out.append("];\n")
|
|
text = "".join(out)
|
|
if check:
|
|
have = open(OUT).read() if os.path.exists(OUT) else None
|
|
if have != text:
|
|
raise SystemExit(
|
|
f"{os.path.relpath(OUT, REPO)} is not what {os.path.relpath(path, REPO)} "
|
|
"generates; run scripts/gen-message-catalog.py"
|
|
)
|
|
print(f"{os.path.relpath(OUT, REPO)} matches its table ({len(rows)} rows)")
|
|
return 0
|
|
with open(OUT, "w") as f:
|
|
f.write(text)
|
|
print(f"wrote {os.path.relpath(OUT, REPO)} ({len(rows)} rows)")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
args = sys.argv[1:]
|
|
check = "--check" in args
|
|
args = [a for a in args if a != "--check"]
|
|
if len(args) > 1 or (check and args):
|
|
raise SystemExit(__doc__)
|
|
sys.exit(main(args[0] if args else TABLE, check))
|