No dumb comments
This commit is contained in:
parent
ec52e57dee
commit
779985c322
9 changed files with 2 additions and 32 deletions
|
|
@ -1,4 +1,3 @@
|
||||||
# The server image only needs `shared/` and `backend/`.
|
|
||||||
**/node_modules
|
**/node_modules
|
||||||
**/dist
|
**/dist
|
||||||
**/lib
|
**/lib
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ concurrency:
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# ---- Static website -> /pages mount on the runner host --------------------
|
|
||||||
website:
|
website:
|
||||||
name: Build & deploy website
|
name: Build & deploy website
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
|
|
@ -45,11 +44,9 @@ jobs:
|
||||||
source: frontend/dist
|
source: frontend/dist
|
||||||
target: declared
|
target: declared
|
||||||
|
|
||||||
# ---- Server Docker image -> Forgejo container registry --------------------
|
|
||||||
server-image:
|
server-image:
|
||||||
name: Build & publish server image
|
name: Build & publish server image
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
# No registry push on PRs; build validation still happens in the website job.
|
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|
|
||||||
3
.vscode/launch.json
vendored
3
.vscode/launch.json
vendored
|
|
@ -1,7 +1,4 @@
|
||||||
{
|
{
|
||||||
// Use IntelliSense to learn about possible attributes.
|
|
||||||
// Hover to view descriptions of existing attributes.
|
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
12
Dockerfile
12
Dockerfile
|
|
@ -1,12 +1,6 @@
|
||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
# doppler game server (the `doppler-server` package).
|
# The full image carries the build tools for socket.io's optional native dependencies.
|
||||||
# The frontend is a static site and is NOT built here — see .forgejo/workflows.
|
|
||||||
|
|
||||||
# ---- Stage 1: build the shared lib, then bundle the server -------------------
|
|
||||||
# Node 22 (current LTS) matches the project toolchain (webpack 5 / TypeScript 6,
|
|
||||||
# see .devcontainer). The full (non-slim) image carries the build tools that
|
|
||||||
# socket.io's optional native deps (bufferutil/utf-8-validate) compile against.
|
|
||||||
FROM node:22-bookworm AS build
|
FROM node:22-bookworm AS build
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|
@ -17,7 +11,6 @@ RUN cd shared && npm install
|
||||||
COPY shared/ shared/
|
COPY shared/ shared/
|
||||||
RUN cd shared && npm run build
|
RUN cd shared && npm run build
|
||||||
|
|
||||||
# Install the backend deps. `file:../shared` now resolves to the built /app/shared.
|
|
||||||
COPY backend/package.json backend/
|
COPY backend/package.json backend/
|
||||||
RUN cd backend && npm install
|
RUN cd backend && npm install
|
||||||
COPY backend/ backend/
|
COPY backend/ backend/
|
||||||
|
|
@ -27,12 +20,10 @@ RUN cd backend && npm run build
|
||||||
# left external (express, socket.io, cors, gl-matrix, minimist, msgpack parser).
|
# left external (express, socket.io, cors, gl-matrix, minimist, msgpack parser).
|
||||||
RUN cd backend && npm prune --production
|
RUN cd backend && npm prune --production
|
||||||
|
|
||||||
# ---- Stage 2: minimal runtime ----------------------------------------------
|
|
||||||
FROM node:22-bookworm-slim
|
FROM node:22-bookworm-slim
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
# Run as an unprivileged user.
|
|
||||||
RUN groupadd -r app && useradd -r -g app -d /app app
|
RUN groupadd -r app && useradd -r -g app -d /app app
|
||||||
|
|
||||||
COPY --from=build /app/backend/dist ./dist
|
COPY --from=build /app/backend/dist ./dist
|
||||||
|
|
@ -41,7 +32,6 @@ COPY --from=build /app/backend/node_modules ./node_modules
|
||||||
USER app
|
USER app
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
# Hits the same /state endpoint the website polls (see serverInformationEndpoint).
|
|
||||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
||||||
CMD node -e "require('http').get('http://localhost:3000/state',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))"
|
CMD node -e "require('http').get('http://localhost:3000/state',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -230,8 +230,6 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Top-down radar of the whole arena (see Minimap). The circular border is
|
|
||||||
// the world boundary; dots are painted onto the canvas.
|
|
||||||
.minimap {
|
.minimap {
|
||||||
top: $small-padding;
|
top: $small-padding;
|
||||||
left: $small-padding;
|
left: $small-padding;
|
||||||
|
|
@ -252,7 +250,6 @@ body {
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Off-screen pointer to the keystone "Heart", tinted by its current owner.
|
|
||||||
.keystone-arrow {
|
.keystone-arrow {
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
|
|
||||||
|
|
@ -330,8 +327,6 @@ body {
|
||||||
content: '\25C9';
|
content: '\25C9';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Twin-stick aim indicator: drawn from the button centre toward the
|
|
||||||
// current drag direction while aiming a shot (see TouchListener).
|
|
||||||
.aim-line {
|
.aim-line {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
|
|
@ -735,8 +730,6 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Centred "Eliminated" overlay shown while the local player is dead; the
|
|
||||||
// respawn countdown is the server-driven "Reviving in N…" announcement.
|
|
||||||
.elimination {
|
.elimination {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 42%;
|
top: 42%;
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,6 @@ module.exports = (env, argv) => {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// svg-url-loader emits a CJS module that css-loader 7 writes out verbatim.
|
|
||||||
test: /\.svg$/,
|
test: /\.svg$/,
|
||||||
type: 'asset/inline',
|
type: 'asset/inline',
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ export const resolveCircleMovement = (
|
||||||
let remainingSeconds = deltaTimeInSeconds;
|
let remainingSeconds = deltaTimeInSeconds;
|
||||||
let firstHit: Sdf | undefined;
|
let firstHit: Sdf | undefined;
|
||||||
|
|
||||||
// Resolve at most two contacts per step, spending only the time left after each hit.
|
|
||||||
for (let pass = 0; pass < 2 && remainingSeconds > 0; pass++) {
|
for (let pass = 0; pass < 2 && remainingSeconds > 0; pass++) {
|
||||||
const speed = vec2.length(body.velocity);
|
const speed = vec2.length(body.velocity);
|
||||||
if (speed === 0) {
|
if (speed === 0) {
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ interface Result {
|
||||||
maximumSpeed: number;
|
maximumSpeed: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exercise shared movement with independent server, network, and render clocks.
|
|
||||||
// Measure world travel: the camera tracks the local character exactly, so measuring
|
// Measure world travel: the camera tracks the local character exactly, so measuring
|
||||||
// their relative position would always report zero even when the world visibly stutters.
|
// their relative position would always report zero even when the world visibly stutters.
|
||||||
const measure = ({
|
const measure = ({
|
||||||
|
|
@ -96,7 +95,6 @@ const measure = ({
|
||||||
const predictor = new LocalCharacterPredictor();
|
const predictor = new LocalCharacterPredictor();
|
||||||
predictor.setStrength(settings.playerMaxStrength);
|
predictor.setStrength(settings.playerMaxStrength);
|
||||||
|
|
||||||
// Deterministic frame-time noise: a real display never delivers a perfectly even cadence.
|
|
||||||
let seed = 12345;
|
let seed = 12345;
|
||||||
const random = () => (seed = (seed * 1103515245 + 12345) & 0x7fffffff) / 0x7fffffff;
|
const random = () => (seed = (seed * 1103515245 + 12345) & 0x7fffffff) / 0x7fffffff;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,6 @@ function character(id = 1) {
|
||||||
step: vi.fn(),
|
step: vi.fn(),
|
||||||
render: vi.fn(),
|
render: vi.fn(),
|
||||||
beforeDestroy: vi.fn(),
|
beforeDestroy: vi.fn(),
|
||||||
// A health setter also represents damage sound/flash feedback in CharacterView.
|
|
||||||
setHealth: vi.fn((health: number) => (object.health = health)),
|
setHealth: vi.fn((health: number) => (object.health = health)),
|
||||||
onShoot: vi.fn(),
|
onShoot: vi.fn(),
|
||||||
onDie: vi.fn(),
|
onDie: vi.fn(),
|
||||||
|
|
@ -126,7 +125,6 @@ describe('suspended rendering', () => {
|
||||||
expect(survivor.onShoot).not.toHaveBeenCalled();
|
expect(survivor.onShoot).not.toHaveBeenCalled();
|
||||||
expect(retained(container).remoteCalls.length).toBeLessThanOrEqual(3);
|
expect(retained(container).remoteCalls.length).toBeLessThanOrEqual(3);
|
||||||
|
|
||||||
// With no additional effects, subsequent snapshots retire the entire old tail.
|
|
||||||
snapshot(container, 46);
|
snapshot(container, 46);
|
||||||
expect(container.planets).toHaveLength(0);
|
expect(container.planets).toHaveLength(0);
|
||||||
expect(retained(container).objects.size).toBe(1);
|
expect(retained(container).objects.size).toBe(1);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue