chore(history): squash 59 commit(s) from 2026-09-23

- refactor(hud/weather/render): Scoreboard 931→240 + Rain 903→159 + UiMeshGeometry 956→99 (8.5.2)
- refactor(chams): Chams 985 → 129 + 4×≤195 (8.5.2)
- refactor(module): Module 1031 → 139 + 4×≤134 (8.5.2)
- refactor(tooltips): BetterTooltips 960 → 181 + 4×≤199 (8.5.2)
- refactor(clickgui): ClickGuiPickerState 970→166 + ModulesMenuScreen 966→145 (8.5.2)
- refactor(clickgui): CombatProtocolHeuristicsEditorState 932→79 + 4×≤192 (8.5.2)
- refactor(hud): CompactHudStatModel 894 → 125 + 4×≤175 (8.5.2)
- refactor(iris): ShaderPatchCompiler 843→66 + 4×≤174 (8.5.2)
- refactor(tab): CustomTabList 834→136 + 4×≤166 (8.5.2)
- refactor(relations): OnlineRelationPlayerPickerComponent 837→74 + 4×≤192 (8.5.2)
- refactor(hits): HitEffect 770→120 + 4×≤176 (8.5.2)
- refactor(predict): Predictions 815→150 + 4×≤195 (8.5.2)
- refactor(config): ConfigProfilesComponent 799→125 + 4×≤195 (8.5.2)
- refactor(sim): PlayerMovementSimulation 757→157 + 4×≤194 (8.5.2)
- refactor(predict): ProjectilePuncher 747→104 + 3×≤134 (8.5.2)
- refactor(crosshair): Crosshair 743→143 + 4×≤167 (8.5.2)
- refactor(mediaplayer): MediaPlayer 743→174 + 4×≤196 (8.5.2)
- refactor(hud): Itemizer 699→193 + Cooldowns 707→151 (8.5.2)
- refactor(hud): Potions 617→176 + 4×≤166 (8.5.2)
- refactor(hud): Admins 702→118 + 4×≤138 (8.5.2)
- refactor(hud): Keybinds 611→157 + 4×≤160 (8.5.2)
- refactor(hud): ModuleList 499→181 + 3×≤150 (8.5.2)
- refactor(hud): Radar 392→161 + 2×≤124 (8.5.2)
- refactor(hud): Fps 309→168 + 3×≤107 (8.5.2)
- refactor(hud): Memory 304→151 + 3×≤144 (8.5.2)
- refactor(hud): Tps 339→154 + 3×≤143 (8.5.2)
- refactor(hud): Ping 309→145 + 3×≤125 (8.5.2)
- refactor(hud): SpeedBps 334→156 + 3×≤142 (8.5.2)
- refactor(hud): GameTime 314→150 + 3×≤127 (8.5.2)
- refactor(hud): SystemTime 300→136 + 3×≤130 (8.5.2)
- refactor(hud): Coordinates 337→174 + 2×≤172 (8.5.2)
- refactor(hud): Armor 324→162 + 2×≤148 (8.5.2)
- refactor(hud): Inventory 476→153 + 3×≤181 (8.5.2)
- docs(todo): обновлён 8.5.2 — отмечены готовые гиганты (BetterButtons/InventorySwap/Svg/Темы/WorldParticles/Module/Chams и хвост)
- docs(api): папка combatant-client-26.2/docs + addons.md (API можно ломать при рефакторе)
- refactor(visuals): BlockHighlight 692→271 + 4×≤200 (8.5.2)
- refactor(mixins): GameRendererMixin 830→344 (хуки) + 4 хелпера (8.5.2)
- refactor(visuals): WorldParticles 821→260 + 6×≤200, режимы добиты (8.5.2)
- docs(todo): 8.5.2 — WorldParticles/GameRendererMixin/BlockHighlight отмечены ГОТОВО
- refactor(render): MeshBuilder 738→447 (фасад write-API) + 3 хелпера, FrameStats снесён (8.5.2)
- docs(todo): Фаза 10 — дизайн платформы (аккаунты/конфиги/аватарки), backlog RPC-чата
- docs(todo): Подсистема 3 — Аддоны 2.0 (скрипты/версии) + витрина аддонов + админка
- docs(todo): Подсистема 2 — RPC-чат/друзья/виджеты-телеметрия + рейт-лимиты, доп. правки Подсистемы 3
- chore: переименование combatant-client-26.2 -> mod, добавлены backend/ и frontend/
- docs(backend): implementation plan for accounts-service (Подсистема 1, часть 1)
- chore: пересоздать backend/frontend через cargo new и bun create vite + tailwind; убрать таблицу компонентов из TODO.md
- docs(backend): edition 2024 в плане вместо 2021
- chore: обновить версии до реально актуальных (проверено компиляцией)
- docs: правила платформы (лимит 250 строк, антипаттерны backend/frontend по итогам ресёрча) + frontend/ARCHITECTURE.md
- docs: добавить правило ≤4 файла на папку в правила платформы (backend/frontend)
- docs: commit messages in English from now on
- chore: gitignore .superpowers/ scratch directory
- docs: commit messages in English from now on (mod)
- feat(backend): scaffold accounts-service with health check
- chore(backend): remove target/ build artifacts from git, add gitignore
- chore: track docs/ in git (was accidentally gitignored, never committed)
- chore(backend): convert to Cargo workspace, plan full microservice layout
- feat(backend): accounts/avatars/device_links schema + migration
- feat(backend): argon2id password hashing
This commit is contained in:
loki5512344 2026-09-23 22:38:08 +02:00
parent ec10395511
commit 9d08fa910a
2239 changed files with 35265 additions and 28110 deletions

View file

@ -0,0 +1,184 @@
#!/usr/bin/env python3
"""Structure split helper (Phase 8.5.1): move classes into leaf subpackages by spec JSON,
fix package lines, rewrite FQNs repo-wide, expand star imports of emptied bases,
insert single-type imports for moved classes, promote the PRIMARY top-level type
(class name == file name) to public when it was package-private.
Does NOT run the compile loop — call promote.py afterwards.
Usage: python3 split_struct.py spec.json (run from project root, e.g. combatant-client-26.2)"""
import os, re, subprocess, json, sys
ROOT = "src/main/java/dev/loki/lovisual"
def git_mv(src, dstdir, name):
os.makedirs(dstdir, exist_ok=True)
dst = os.path.join(dstdir, name + ".java")
if os.path.abspath(src) == os.path.abspath(dst):
return
subprocess.run(["git", "mv", "-f", src, dst], check=True)
def main(specpath):
spec = json.load(open(specpath))
BASE = spec["base"]
files = {}
for dp, dns, fns in os.walk(BASE):
for fn in fns:
if fn.endswith(".java"):
files[fn[:-5]] = os.path.join(dp, fn)
reldots = {}
for sub, names in spec["move"].items():
dst = os.path.join(BASE, sub)
os.makedirs(dst, exist_ok=True)
for n in names:
src = files.get(n)
if src is None:
print("MISSING:", n)
continue
cur = os.path.relpath(os.path.dirname(src), ROOT).replace("/", ".")
newp = os.path.relpath(dst, ROOT).replace("/", ".")
if cur == newp:
continue
reldots[f"{cur}.{n}"] = f"{newp}.{n}"
git_mv(src, dst, n)
if not reldots:
print("nothing moved")
# package lines for whole base tree
for dp, dns, fns in os.walk(BASE):
pkg = "dev.loki.lovisual." + os.path.relpath(dp, ROOT).replace("/", ".")
for fn in fns:
if not fn.endswith(".java"):
continue
p = os.path.join(dp, fn)
t = open(p).read()
n = re.sub(r"^package [^;]*;", f"package {pkg};", t, count=1, flags=re.M)
if n != t:
open(p, "w").write(n)
moved_pkg = {}
for dp, dns, fns in os.walk(BASE):
pkg = os.path.relpath(dp, ROOT).replace("/", ".")
for fn in fns:
if fn.endswith(".java"):
moved_pkg[fn[:-5]] = pkg
# global dupes (WorldCommandBuffer, GlyphAtlas* etc.) should not be auto-imported
global_cls = {}
for dp, dns, fns in os.walk(ROOT):
for fn in fns:
if fn.endswith(".java"):
global_cls.setdefault(fn[:-5], set()).add(
os.path.relpath(dp, ROOT).replace("/", ".")
)
dupes = {k for k, v in global_cls.items() if len(v) > 1}
base_pkg = "dev.loki.lovisual." + os.path.relpath(BASE, ROOT).replace("/", ".")
WILD_STAR = f"import {base_pkg}.*;"
WILD_LEGACY = f"import {base_pkg}.;"
SHADOW = {
"Font",
"GlyphAtlasManager",
"Scoreboard",
"Inventory",
"MediaPlayer",
"Player",
"Entity",
"Level",
"World",
}
for tree in ("src/main/java", "src/test/java"):
for dp, dns, fns in os.walk(tree):
my = None
rel = os.path.relpath(dp, tree)
if rel.startswith("dev/loki/lovisual"):
my = rel.replace("/", ".")
for fn in fns:
if not fn.endswith(".java"):
continue
p = os.path.join(dp, fn)
t = open(p).read()
o = t
# replace longest FQNs first to avoid prefix collision (InventorySwap vs InventorySwapVisibility)
for old, new in sorted(reldots.items(), key=lambda kv: -len(kv[0])):
# exact FQN replace: old must be followed by non-word or end, use regex
t = re.sub(
r"dev\.loki\.lovisual\." + re.escape(old) + r"(?=[\W])",
f"dev.loki.lovisual.{new}",
t,
)
# expand star imports (both .* and legacy .%;) only if base became empty
wild_hit = (WILD_STAR in t) or (WILD_LEGACY in t)
if wild_hit:
base_still_has_top = any(
cp == os.path.relpath(BASE, ROOT).replace("/", ".")
for cp in moved_pkg.values()
)
if not base_still_has_top:
body = "\n".join(t.splitlines()[8:])
need = [
f"import dev.loki.lovisual.{cp}.{cls};"
for cls, cp in moved_pkg.items()
if cls not in SHADOW
and cls not in dupes
and re.search(r"(?<![\w.])%s\b" % re.escape(cls), body)
]
repl = "".join(n + "\n" for n in sorted(need))
if WILD_STAR in t:
t = t.replace(WILD_STAR + "\n", repl)
if WILD_LEGACY in t:
t = t.replace(WILD_LEGACY + "\n", repl)
# insert missing single-type imports for moved classes used by simple name
body = "\n".join(t.splitlines()[8:])
need = []
for cls, cp in moved_pkg.items():
if cls in dupes or cls in SHADOW:
continue
if my is not None and cp == my:
continue
if cls == fn[:-5]:
continue
if not re.search(r"(?<![\w.])%s\b" % re.escape(cls), body):
continue
if f"import dev.loki.lovisual.{cp}.{cls};" in t:
continue
need.append(f"import dev.loki.lovisual.{cp}.{cls};")
if need:
lines = t.splitlines(keepends=True)
imps = [i for i, l in enumerate(lines) if l.startswith("import ")]
idx = (
max(imps)
if imps
else next(
(i for i, l in enumerate(lines) if l.startswith("package")),
0,
)
)
lines.insert(idx + 1, "\n".join(sorted(need)) + "\n")
t = "".join(lines)
# promote PRIMARY type only (name == file stem) if package-private
def prom_primary(m):
if m.group(3) != fn[:-5]:
return m.group(0)
return "public " + m.group(0) if not m.group(1) else m.group(0)
t = re.sub(
r"^(public\s+)?((?:(?:final|abstract|sealed|strictfp)\s+)*)(class|interface|enum|record)\s+(\w+)",
lambda m: (
m.group(0)
if (m.group(4) != fn[:-5] or m.group(1))
else "public " + m.group(2) + m.group(3) + " " + m.group(4)
),
t,
count=1,
flags=re.M,
)
if t != o:
open(p, "w").write(t)
print("structure done for", BASE)
if __name__ == "__main__":
main(sys.argv[1])