Files
Erik W. a62da8926d release: v2.3.0 refactor and UI/audio fixes
- bump project/runtime version markers to v2.3.0 (pyproject + TetriNode UI version)

- complete behavior-preserving refactor from monoliths into modular Python and JS architecture (tetrinode/ + js/live/)

- add parity + standard regression harnesses under qa/

- fix queue panel layout so Queue bottom stays aligned to matrix bottom regardless of Controls visibility

- fix music playback fallback when selected track is none, including modal Play behavior and runtime playback path
2026-02-08 17:14:25 -05:00

74 lines
1.8 KiB
JavaScript

export function createLockRepeatHelpers(deps) {
const {
collides,
move,
dasMs,
arrMs,
} = deps;
function getLockMode(node, getConfig) {
const defaultMode = "extended";
const raw = `${getConfig(node).lock_down_mode || ""}`.trim().toLowerCase();
if (["extended", "infinite", "classic"].includes(raw)) return raw;
return defaultMode;
}
function applyLockModeAfterAction(state, mode) {
const onSurface = collides(state.board, { ...state.piece, y: state.piece.y + 1 });
if (!onSurface) {
state.locking = false;
state.lockElapsed = 0;
return;
}
state.locking = true;
if (mode === "classic") {
return;
}
if (mode === "infinite") {
state.lockElapsed = 0;
return;
}
if (state.lockMoves < 15) {
state.lockMoves += 1;
state.lockElapsed = 0;
} else {
state.lockElapsed = state.lockDelayMs;
}
}
function setMoveDirection(state, dir) {
if (state.moveDir === dir) return;
state.moveDir = dir;
state.moveDasElapsed = 0;
state.moveArrElapsed = 0;
}
function clearMoveDirection(state) {
state.moveDir = null;
state.moveDasElapsed = 0;
state.moveArrElapsed = 0;
}
function updateAutoRepeat(state, node, getConfig, deltaMs) {
if (!state.moveDir) return;
state.moveDasElapsed += deltaMs;
if (state.moveDasElapsed < dasMs) return;
state.moveArrElapsed += deltaMs;
while (state.moveArrElapsed >= arrMs) {
state.moveArrElapsed -= arrMs;
const dx = state.moveDir === "left" ? -1 : 1;
if (move(state, dx, 0)) {
applyLockModeAfterAction(state, getLockMode(node, getConfig));
}
}
}
return {
getLockMode,
applyLockModeAfterAction,
setMoveDirection,
clearMoveDirection,
updateAutoRepeat,
};
}