This site is a collection of experiments to explore the range of code we can make using AI tools.
Built with Hono, Deno, JSX/React components and modern web standards.
Focus is on wide range of experiements with a large code base (monorepo) but keep dev sane, fast and fun while keeping performance high.
These are small experiments to explore the range of code we can make using AI tools.
Offset = ServerTime - (T1 + T2)/2
A robust, copy-pasteable TypeScript class for your game.
export class TimeSync {
offset = 0;
rtt = 0;
async sync() {
const t1 = Date.now();
const serverTime = await fetchTime();
const t2 = Date.now();
this.rtt = t2 - t1;
this.offset = serverTime - (t1 + this.rtt/2);
}
async syncBatch(count = 10) {
const offsets = [];
for(let i=0; i<count; i++) {
await this.sync();
offsets.push(this.offset);
}
offsets.sort((a,b) => a-b);
const mid = Math.floor(offsets.length/2);
this.offset = offsets.length % 2 !== 0
? offsets[mid]
: (offsets[mid-1] + offsets[mid]) / 2;
}
now() {
return Date.now() + this.offset;
}
}Don't render at exactly ServerTime. Render at ServerTime - 100ms (or 2-3 tick duration) to smooth out jitter and prevent snapping when packets arrive late.
Metrics (this tool) measure the network.Game Clock should be a smooth, monotonically increasing value that chases the measured offset over time, avoiding sudden jumps.
Hardware clocks vary (drift). You must re-sync periodically (e.g. every 30s) or continuously adjust your game speed (e.g. run at 1.01x speed) to stay aligned without snapping.
Travel time for a packet to reach the server and back. Measured in ms.
How often the server processes inputs and updates the world. Measured in Hz.
What "20Hz" looks like in code:
const TICK_MS = 50; // 1000ms / 20Hz
while (serverRunning) {
const start = Date.now();
updateGamePhysics();
broadcastState();
// Wait for remainder of the 50ms
await sleep(TICK_MS - (Date.now() - start));
}Why you lag even with 0ms Ping:
// 1. Find the two snapshots we are between
const T_render = Date.now() - BUFFER_MS;
const A = buffer.find(snap => snap.t <= T_render);
const B = buffer.find(snap => snap.t > T_render);
// 2. Calculate progress (Alpha) 0.0 to 1.0
const progress = (T_render - A.t) / (B.t - A.t);
// 3. Lerp!
const x = lerp(A.x, B.x, progress);
// Helper
function lerp(start, end, alpha) {
return start + (end - start) * alpha;
}