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,61 @@
/*
* This file is part of the LoVisual Client distribution.
* Copyright (c) 2026 loki5512344.
*
* Licensed under the GNU General Public License v3.0.
*/
package dev.loki.lovisual.util.protection;
/**
* Minimal pure throttle for repeated warnings.
*
* <p>The caller supplies the current time, so the class has no clock
* dependency and stays unit-testable.</p>
*/
public final class NotifyThrottle {
private final long intervalMs;
private boolean fired;
private long lastMs;
public NotifyThrottle(long intervalMs) {
this.intervalMs = Math.max(0L, intervalMs);
}
/**
* Returns true when the caller may emit a notification now, recording
* the given time as the last emission. Returns false while the previous
* emission is still inside the interval.
*/
public boolean tryAcquire(long nowMs) {
if (remainingMs(nowMs) > 0L) {
return false;
}
fired = true;
lastMs = nowMs;
return true;
}
/**
* Milliseconds left until the next notification is allowed.
* Zero when the throttle has never fired or the window elapsed.
*/
public long remainingMs(long nowMs) {
if (!fired) {
return 0L;
}
long elapsed = nowMs - lastMs;
if (elapsed < 0L) {
// Clock moved backwards: do not lock out the caller.
return 0L;
}
long left = intervalMs - elapsed;
return Math.max(0L, left);
}
public void reset() {
fired = false;
lastMs = 0L;
}
}

View file

@ -0,0 +1,73 @@
/*
* This file is part of the LoVisual Client distribution.
* Copyright (c) 2026 loki5512344.
*
* Licensed under the GNU General Public License v3.0.
*/
package dev.loki.lovisual.util.protection;
import java.util.LinkedHashMap;
import java.util.Map;
import dev.loki.lovisual.features.gui.clickgui.settings.core.Setting;
import dev.loki.lovisual.features.module.modules.player.inventory.LockSlot;
/**
* Pure decision logic for the LockSlot module: whether dropping an item
* from a given hotbar slot must be blocked.
*/
public final class SlotLockPolicy {
public static final int HOTBAR_SIZE = 9;
private SlotLockPolicy() {
}
/**
* Default setting state: all hotbar slots unlocked.
* Keys are ordered "slot1".."slot9".
*/
public static Map<String, Boolean> defaultSlotStates() {
Map<String, Boolean> out = new LinkedHashMap<>();
for (int i = 0; i < HOTBAR_SIZE; i++) {
out.put(slotKey(i), false);
}
return out;
}
/**
* Setting key for a zero-based hotbar slot: 0 -> "slot1", 8 -> "slot9".
*/
public static String slotKey(int hotbarSlot) {
return "slot" + (hotbarSlot + 1);
}
/**
* True when the slot is explicitly locked by the given states map.
* Missing or out-of-range slots are treated as unlocked.
*/
public static boolean isSlotLocked(Map<String, Boolean> slotStates, int hotbarSlot) {
if (slotStates == null || slotStates.isEmpty()) return false;
if (hotbarSlot < 0 || hotbarSlot >= HOTBAR_SIZE) return false;
Boolean locked = slotStates.get(slotKey(hotbarSlot));
return locked != null && locked;
}
/**
* Full drop decision for a hotbar slot.
*
* @param slotStates locked-slot setting states keyed by {@link #slotKey(int)}
* @param selectedSlot zero-based hotbar slot the drop comes from
* @param playersNearby whether other players are within the guard radius
* @param onlyNearby the "only_players_nearby" setting value
*/
public static boolean isDropBlocked(
Map<String, Boolean> slotStates,
int selectedSlot,
boolean playersNearby,
boolean onlyNearby
) {
if (!isSlotLocked(slotStates, selectedSlot)) return false;
return !onlyNearby || playersNearby;
}
}