From a028618ae4e4647a7db1c973d66c34e6b5548138 Mon Sep 17 00:00:00 2001 From: Wali Lambert <98448225+YatoVoid@users.noreply.github.com> Date: Tue, 25 Aug 2026 10:00:48 -0500 Subject: [PATCH] Add SecurityCraft, required on both sides; bump client pack to 1.2.0 Fix mod-name normalization in the sync tool and its compat test: neither fully URL-decoded a filename before comparing, which only mattered once a mod's canonical name needed bracket characters. --- CHANGELOG.md | 2 ++ data/EduCraftClient.mrpack | Bin 16243 -> 16236 bytes docker-compose.yml | 2 +- tests/test_client_server_mods.py | 5 +++-- tools/sync_client_pack.py | 4 ++-- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index adf0514..7788d6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ being corrected, and those are the ones most likely to save someone time later. ## [Unreleased] ### Added +- **SecurityCraft**, required on both client and server (no dependencies to + pull in). Pack bumped to versionId 1.2.0. **REQUIRES PACK RE-IMPORT.** - Droplet-side security alerting to Discord. A systemd timer runs every 15 minutes and reports SSH logins, failed-auth bursts, sensitive sudo, fail2ban bans, container faults, `ops.json` changes, sensitive file edits, new user diff --git a/data/EduCraftClient.mrpack b/data/EduCraftClient.mrpack index ddbfcd008deed282c82fad458337158048e23d4d..fdd32384d521633d53ef5e65ccc1335db5bc00a4 100644 GIT binary patch delta 11783 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 ZXd4(9`oCKF3N8+m7N+_@&;HlL{{_D)xaI%= delta 11750 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 comparable mod key. Strips version and loader token.""" - name = name.replace("%20", " ").replace("%2B", "+") + name = urllib.parse.unquote(name) stem = re.split(r"[-_]\d", name.lower())[0] stem = re.sub(r"[-_ ]?(forge|fabric|neoforge|quilt|mc)$", "", stem) - return stem.replace("-", "").replace("_", "").replace(" ", "") + return re.sub(r"[-_ \[\]]", "", stem) def get_json(url):