The code moves into src/: index, server and the test harness keep the root
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c122745390
commit
1f636530b9
16 files changed
+16
-13
No files matched your search
+4
-2
@@ -3,7 +3,8 @@
|
|||||||
# stage COPYs the marker so BuildKit cannot skip this stage as unused.
|
# stage COPYs the marker so BuildKit cannot skip this stage as unused.
|
||||||
FROM node:22-alpine AS test
|
FROM node:22-alpine AS test
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY *.js /app/
|
COPY test.js /app/
|
||||||
|
COPY src /app/src
|
||||||
RUN node test.js && touch /tests-passed
|
RUN node test.js && touch /tests-passed
|
||||||
|
|
||||||
FROM python:3.12-alpine
|
FROM python:3.12-alpine
|
||||||
@@ -14,7 +15,8 @@ FROM python:3.12-alpine
|
|||||||
# ponytail: switch to hashed filenames if traffic ever matters.
|
# ponytail: switch to hashed filenames if traffic ever matters.
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=test /tests-passed /tmp/tests-passed
|
COPY --from=test /tests-passed /tmp/tests-passed
|
||||||
COPY index.html manifest.webmanifest *.js server.py /app/
|
COPY index.html manifest.webmanifest server.py /app/
|
||||||
|
COPY src /app/src
|
||||||
COPY assets /app/assets
|
COPY assets /app/assets
|
||||||
# THE SCORES LIVE HERE AND THIS MUST BE A PERSISTENT VOLUME. Without one the json sits in the
|
# THE SCORES LIVE HERE AND THIS MUST BE A PERSISTENT VOLUME. Without one the json sits in the
|
||||||
# container's writable layer and every deploy silently resets the leaderboard to empty — which
|
# container's writable layer and every deploy silently resets the leaderboard to empty — which
|
||||||
|
|||||||
+5
-4
@@ -29,7 +29,8 @@ the primary target.
|
|||||||
the Dockerfile. Oliver tests on his phone at splatter-tennis.wuwi.one ~30s after
|
the Dockerfile. Oliver tests on his phone at splatter-tennis.wuwi.one ~30s after
|
||||||
a push. **Bump `main.js?v=N` in index.html every time** or phones keep the old build.
|
a push. **Bump `main.js?v=N` in index.html every time** or phones keep the old build.
|
||||||
The Dockerfile must also COPY any new top-level file (it currently ships `index.html`,
|
The Dockerfile must also COPY any new top-level file (it currently ships `index.html`,
|
||||||
`manifest.webmanifest`, `*.js`, `server.py`, `assets/`).
|
`manifest.webmanifest`, `server.py`, `src/`, `assets/` — `test.js` only feeds the test stage and
|
||||||
|
is deliberately not in the served image).
|
||||||
- **The image is `python:3.12-alpine` running `server.py`, no longer `nginx:alpine`.** The world
|
- **The image is `python:3.12-alpine` running `server.py`, no longer `nginx:alpine`.** The world
|
||||||
board needs one process that can WRITE, and nginx is not one; everything the nginx conf did here
|
board needs one process that can WRITE, and nginx is not one; everything the nginx conf did here
|
||||||
(no-cache so a deploy lands on a plain reload, and `application/manifest+json`, without which
|
(no-cache so a deploy lands on a plain reload, and `application/manifest+json`, without which
|
||||||
@@ -51,7 +52,7 @@ the primary target.
|
|||||||
- **Oliver edits files himself** (tuning values, sometimes sprites). ALWAYS Read current file state
|
- **Oliver edits files himself** (tuning values, sometimes sprites). ALWAYS Read current file state
|
||||||
before editing; never assume your last version is what is on disk.
|
before editing; never assume your last version is what is on disk.
|
||||||
|
|
||||||
## Module map (all in repo root)
|
## Module map (game code in `src/`; `index.html`, `server.py` and `test.js` at the root)
|
||||||
`config.js` TUNE (live T panel) + structural constants + `UI` palette · `state.js` the `G` object +
|
`config.js` TUNE (live T panel) + structural constants + `UI` palette · `state.js` the `G` object +
|
||||||
P/O/ball/score + `setupPoint`/`sendBoy` · `gameplay.js` ballistics/swings/serve/rules/AI/`update()` +
|
P/O/ball/score + `setupPoint`/`sendBoy` · `gameplay.js` ballistics/swings/serve/rules/AI/`update()` +
|
||||||
transition + `splatPoint` + ball-boy routines · `beats.js` **the beat machinery: every mode
|
transition + `splatPoint` + ball-boy routines · `beats.js` **the beat machinery: every mode
|
||||||
@@ -827,8 +828,8 @@ Clear the intro first: `document.getElementById('intro')?.remove()`.
|
|||||||
own geometry could possibly reach. To check WHERE something lands, recompute the projection
|
own geometry could possibly reach. To check WHERE something lands, recompute the projection
|
||||||
directly (`T.proj(...)`) and compare numbers; keep pixel-diffing for "did anything at all change".
|
directly (`T.proj(...)`) and compare numbers; keep pixel-diffing for "did anything at all change".
|
||||||
- **The module-refresh list MUST include the VERSIONED entry point.** `index.html` loads
|
- **The module-refresh list MUST include the VERSIONED entry point.** `index.html` loads
|
||||||
`main.js?v=N`, and `fetch('main.js', {cache:'reload'})` does not bust that URL — so main.js alone
|
`src/main.js?v=N`, and `fetch('src/main.js', {cache:'reload'})` does not bust that URL — so main.js
|
||||||
stays stale through a reload while every other module is fresh. Read the src off the page:
|
alone stays stale through a reload while every other module is fresh. Read the src off the page:
|
||||||
`document.querySelector('script[type=module]').getAttribute('src')` and fetch that too. Symptom: a
|
`document.querySelector('script[type=module]').getAttribute('src')` and fetch that too. Symptom: a
|
||||||
change in main.js appears to do nothing at all, repeatably.
|
change in main.js appears to do nothing at all, repeatably.
|
||||||
- **You MUST set `T.TUNE.autoAssist = 1.15` first** — the Browser pane reports `pointer: fine`, so
|
- **You MUST set `T.TUNE.autoAssist = 1.15` first** — the Browser pane reports `pointer: fine`, so
|
||||||
|
|||||||
+1
-1
@@ -398,6 +398,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="module" src="main.js?v=148"></script>
|
<script type="module" src="src/main.js?v=149"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -278,7 +278,7 @@ intro.addEventListener('pointerdown', () => menuMusic());
|
|||||||
// which build am I looking at? Push = deploy and the browser cannot see git, so the served file's
|
// which build am I looking at? Push = deploy and the browser cannot see git, so the served file's
|
||||||
// own timestamp IS the version marker — it changes on every deploy, with nothing to remember to bump.
|
// own timestamp IS the version marker — it changes on every deploy, with nothing to remember to bump.
|
||||||
// Match it against `git log -1 --format=%cd` when a phone looks suspiciously out of date.
|
// Match it against `git log -1 --format=%cd` when a phone looks suspiciously out of date.
|
||||||
fetch('main.js', { method: 'HEAD' })
|
fetch('src/main.js', { method: 'HEAD' }) // page-relative: index.html sits at the root, the code in src/
|
||||||
.then(r => { const t = r.headers.get('last-modified'); if (!t) return;
|
.then(r => { const t = r.headers.get('last-modified'); if (!t) return;
|
||||||
document.getElementById('build').textContent = 'BUILD ' + new Date(t).toLocaleString('en-GB').replace(',', ''); })
|
document.getElementById('build').textContent = 'BUILD ' + new Date(t).toLocaleString('en-GB').replace(',', ''); })
|
||||||
.catch(() => {}); // no header, no line — never a broken start screen
|
.catch(() => {}); // no header, no line — never a broken start screen
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -60,11 +60,11 @@ globalThis.ResizeObserver = class { observe() {} disconnect() {} };
|
|||||||
globalThis.getComputedStyle = () => ({ paddingTop: '0' });
|
globalThis.getComputedStyle = () => ({ paddingTop: '0' });
|
||||||
|
|
||||||
// ---- game modules (real code) ----------------------------------------------
|
// ---- game modules (real code) ----------------------------------------------
|
||||||
const { G, P, score, ball, setupPoint } = await import('./state.js');
|
const { G, P, score, ball, setupPoint } = await import('./src/state.js');
|
||||||
const { update, forceZombies, splatPoint, restartRun } = await import('./gameplay.js');
|
const { update, forceZombies, splatPoint, restartRun } = await import('./src/gameplay.js');
|
||||||
const { startDuel, resolveInterlude, startBossFight, endBossFight } = await import('./beats.js');
|
const { startDuel, resolveInterlude, startBossFight, endBossFight } = await import('./src/beats.js');
|
||||||
const { zombies, spawnZombie } = await import('./zombies.js');
|
const { zombies, spawnZombie } = await import('./src/zombies.js');
|
||||||
const { TUNE } = await import('./config.js');
|
const { TUNE } = await import('./src/config.js');
|
||||||
|
|
||||||
const DT = 1 / 60;
|
const DT = 1 / 60;
|
||||||
function freshSplatter() {
|
function freshSplatter() {
|
||||||
|
|||||||
Reference in new issue
Block a user