@gamerstake/game-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/.eslintrc.json +22 -0
  2. package/.testing-guide-summary.md +261 -0
  3. package/DEVELOPER_GUIDE.md +996 -0
  4. package/MANUAL_TESTING.md +369 -0
  5. package/QUICK_START.md +368 -0
  6. package/README.md +379 -0
  7. package/TESTING_OVERVIEW.md +378 -0
  8. package/dist/index.d.ts +1266 -0
  9. package/dist/index.js +1632 -0
  10. package/dist/index.js.map +1 -0
  11. package/examples/simple-game/README.md +176 -0
  12. package/examples/simple-game/client.ts +201 -0
  13. package/examples/simple-game/package.json +14 -0
  14. package/examples/simple-game/server.ts +233 -0
  15. package/jest.config.ts +39 -0
  16. package/package.json +54 -0
  17. package/src/core/GameLoop.ts +214 -0
  18. package/src/core/GameRules.ts +103 -0
  19. package/src/core/GameServer.ts +200 -0
  20. package/src/core/Room.ts +368 -0
  21. package/src/entities/Entity.ts +118 -0
  22. package/src/entities/Registry.ts +161 -0
  23. package/src/index.ts +51 -0
  24. package/src/input/Command.ts +41 -0
  25. package/src/input/InputQueue.ts +130 -0
  26. package/src/network/Network.ts +112 -0
  27. package/src/network/Snapshot.ts +59 -0
  28. package/src/physics/AABB.ts +104 -0
  29. package/src/physics/Movement.ts +124 -0
  30. package/src/spatial/Grid.ts +202 -0
  31. package/src/types/index.ts +117 -0
  32. package/src/types/protocol.ts +161 -0
  33. package/src/utils/Logger.ts +112 -0
  34. package/src/utils/RingBuffer.ts +116 -0
  35. package/tests/AABB.test.ts +38 -0
  36. package/tests/Entity.test.ts +35 -0
  37. package/tests/GameLoop.test.ts +58 -0
  38. package/tests/GameServer.test.ts +64 -0
  39. package/tests/Grid.test.ts +28 -0
  40. package/tests/InputQueue.test.ts +42 -0
  41. package/tests/Movement.test.ts +37 -0
  42. package/tests/Network.test.ts +39 -0
  43. package/tests/Registry.test.ts +36 -0
  44. package/tests/RingBuffer.test.ts +38 -0
  45. package/tests/Room.test.ts +80 -0
  46. package/tests/Snapshot.test.ts +19 -0
  47. package/tsconfig.json +28 -0
  48. package/tsup.config.ts +14 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/Logger.ts","../src/core/GameLoop.ts","../src/entities/Registry.ts","../src/spatial/Grid.ts","../src/utils/RingBuffer.ts","../src/input/InputQueue.ts","../src/network/Network.ts","../src/network/Snapshot.ts","../src/core/Room.ts","../src/core/GameServer.ts","../src/entities/Entity.ts","../src/physics/AABB.ts","../src/physics/Movement.ts","../src/types/protocol.ts"],"names":["defaultLogger","pino","level","process","env","LOG_LEVEL","transport","NODE_ENV","target","options","colorize","translateTime","ignore","undefined","base","package","logger","setLogger","customLogger","createChildLogger","bindings","child","Logger","constructor","debug","objOrMsg","msg","info","warn","error","childLogger","GameLoop","tickRate","tickMs","tickNumber","lastTickTime","running","timeout","handlers","tickTimes","metricsWindowSize","addHandler","handler","push","removeHandler","index","indexOf","splice","start","performance","now","scheduleNextTick","stop","clearTimeout","totalTicks","isRunning","getCurrentTick","getTickRate","getTickMs","getMetrics","length","avgTickTime","maxTickTime","minTickTime","ticksPerSecond","sum","reduce","a","b","avg","Math","max","min","elapsed","drift","nextDelay","setTimeout","tick","tickStart","deltaMs","onTick","tickDuration","recordTickTime","duration","budget","shift","Registry","entities","Map","dirtyEntities","Set","dirtyBuffer","allBuffer","add","entity","has","id","entityId","set","remove","get","delete","markDirty","getDirtyEntities","markClean","clear","getAll","values","size","dirtyCount","forEach","callback","filter","predicate","result","Grid","cellSize","cells","entityCells","getCellKey","worldX","worldY","cellX","floor","cellY","getCell","key","cell","x","y","addEntity","removeEntity","cellKey","moveEntity","oldX","oldY","newX","newY","oldKey","newKey","oldCell","newCell","getNearbyEntities","range","centerCellX","centerCellY","dx","dy","getEntitiesInCell","Array","from","getEntityCell","getCellCount","getEntityCount","RingBuffer","buffer","head","tail","count","capacity","item","pushOverwrite","dropped","peek","isEmpty","isFull","getCapacity","InputQueue","queues","maxQueueSize","getQueue","playerId","queue","input","pop","drain","inputs","clearAll","getTotalSize","total","Network","io","sockets","setServer","registerSocket","socket","unregisterSocket","getSocket","broadcast","event","emit","op","opcode","broadcastToRoom","roomId","to","sendTo","sendToMany","playerIds","getPlayerCount","Snapshot","create","timestamp","Date","map","e","entityToSnapshot","vx","vy","createDelta","Room","rules","registry","grid","loop","inputQueue","network","players","tickCount","startTime","config","maxInputQueueSize","maxEntities","visibilityRange","onRoomCreated","addPlayer","player","onPlayerJoin","removePlayer","onPlayerLeave","spawnEntity","destroyEntity","queueInput","command","getSnapshot","getDeltaSnapshot","onCommand","type","delta","shouldEndRoom","getPlayers","getRegistry","getGrid","getNetwork","getInputQueue","getTickCount","getUptime","getConfig","loopMetrics","uptime","playerCount","entityCount","cellCount","queuedInputs","GameServer","rooms","room","createRoom","Error","destroyRoom","getRoom","getRoomAs","hasRoom","getRooms","getRoomCount","getTotalPlayerCount","roomCount","totalPlayers","stopAll","destroyAll","Entity","dirty","lastUpdate","updatePosition","deltaSec","setVelocity","setPosition","toJSON","AABBCollision","overlaps","aHalfW","width","aHalfH","height","bHalfW","bHalfH","abs","containsPoint","aabb","halfW","halfH","fromEntity","distance","combinedHalfW","combinedHalfH","gapX","gapY","sqrt","overlap","overlapX","overlapY","sign","Movement","integrate","applyVelocity","constrainToBoundary","boundary","clamped","minX","maxX","minY","maxY","normalize","velocityFromDirection","dirX","dirY","speed","normalized","ClientOpcode","ServerOpcode"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Logger utility\n *\n * Wrapper around pino for structured logging.\n * Consumers can override this with their own logger.\n */\n\nimport pino from 'pino';\n\n/**\n * Default logger configuration.\n */\nconst defaultLogger = pino({\n level: process.env.LOG_LEVEL || 'info',\n transport:\n process.env.NODE_ENV === 'development'\n ? {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'HH:MM:ss',\n ignore: 'pid,hostname',\n },\n }\n : undefined,\n base: {\n package: '@gamerstake/game-core',\n },\n});\n\n/**\n * Logger instance.\n * Can be replaced by consumers.\n */\nexport let logger = defaultLogger;\n\n/**\n * Set a custom logger instance.\n *\n * @param customLogger - Custom pino logger\n */\nexport function setLogger(customLogger: pino.Logger): void {\n logger = customLogger;\n}\n\n/**\n * Create a child logger with additional context.\n *\n * @param bindings - Additional context fields\n */\nexport function createChildLogger(\n bindings: Record<string, unknown>,\n): pino.Logger {\n return logger.child(bindings);\n}\n\n/**\n * Logger class for dependency injection.\n */\nexport class Logger {\n private logger: pino.Logger;\n\n constructor(bindings?: Record<string, unknown>) {\n this.logger = bindings ? logger.child(bindings) : logger;\n }\n\n debug(obj: object, msg?: string): void;\n debug(msg: string): void;\n debug(objOrMsg: object | string, msg?: string): void {\n if (typeof objOrMsg === 'string') {\n this.logger.debug(objOrMsg);\n } else {\n this.logger.debug(objOrMsg, msg);\n }\n }\n\n info(obj: object, msg?: string): void;\n info(msg: string): void;\n info(objOrMsg: object | string, msg?: string): void {\n if (typeof objOrMsg === 'string') {\n this.logger.info(objOrMsg);\n } else {\n this.logger.info(objOrMsg, msg);\n }\n }\n\n warn(obj: object, msg?: string): void;\n warn(msg: string): void;\n warn(objOrMsg: object | string, msg?: string): void {\n if (typeof objOrMsg === 'string') {\n this.logger.warn(objOrMsg);\n } else {\n this.logger.warn(objOrMsg, msg);\n }\n }\n\n error(obj: object, msg?: string): void;\n error(msg: string): void;\n error(objOrMsg: object | string, msg?: string): void {\n if (typeof objOrMsg === 'string') {\n this.logger.error(objOrMsg);\n } else {\n this.logger.error(objOrMsg, msg);\n }\n }\n\n child(bindings: Record<string, unknown>): Logger {\n const childLogger = new Logger();\n childLogger.logger = this.logger.child(bindings);\n return childLogger;\n }\n}\n","/**\n * Game Loop\n *\n * Fixed tick rate server loop with drift compensation.\n * Processes inputs, updates state, broadcasts changes.\n */\n\nimport { logger } from '../utils/Logger.js';\nimport type { LoopMetrics } from '../types/index.js';\n\n/**\n * Tick handler interface.\n * Implement this to receive tick callbacks.\n */\nexport interface TickHandler {\n onTick(tickNumber: number, deltaMs: number): void;\n}\n\n/**\n * High-precision game loop using setTimeout with drift compensation.\n */\nexport class GameLoop {\n private readonly tickRate: number;\n private readonly tickMs: number;\n private tickNumber = 0;\n private lastTickTime = 0;\n private running = false;\n private timeout: NodeJS.Timeout | null = null;\n private readonly handlers: TickHandler[] = [];\n\n // Performance metrics\n private tickTimes: number[] = [];\n private readonly metricsWindowSize = 100;\n\n /**\n * Create a new game loop.\n *\n * @param tickRate - Ticks per second (default: 20)\n */\n constructor(tickRate = 20) {\n this.tickRate = tickRate;\n this.tickMs = 1000 / tickRate;\n }\n\n /**\n * Register a tick handler.\n */\n addHandler(handler: TickHandler): void {\n this.handlers.push(handler);\n }\n\n /**\n * Remove a tick handler.\n */\n removeHandler(handler: TickHandler): void {\n const index = this.handlers.indexOf(handler);\n if (index !== -1) {\n this.handlers.splice(index, 1);\n }\n }\n\n /**\n * Start the game loop.\n */\n start(): void {\n if (this.running) {\n logger.warn('Game loop already running');\n return;\n }\n\n this.running = true;\n this.lastTickTime = performance.now();\n this.tickNumber = 0;\n\n logger.info(\n { tickRate: this.tickRate, tickMs: this.tickMs },\n 'Game loop started',\n );\n\n this.scheduleNextTick();\n }\n\n /**\n * Stop the game loop.\n */\n stop(): void {\n this.running = false;\n\n if (this.timeout) {\n clearTimeout(this.timeout);\n this.timeout = null;\n }\n\n logger.info({ totalTicks: this.tickNumber }, 'Game loop stopped');\n }\n\n /**\n * Check if loop is running.\n */\n isRunning(): boolean {\n return this.running;\n }\n\n /**\n * Get current tick number.\n */\n getCurrentTick(): number {\n return this.tickNumber;\n }\n\n /**\n * Get tick rate (TPS).\n */\n getTickRate(): number {\n return this.tickRate;\n }\n\n /**\n * Get tick duration (ms).\n */\n getTickMs(): number {\n return this.tickMs;\n }\n\n /**\n * Get performance metrics.\n */\n getMetrics(): LoopMetrics {\n if (this.tickTimes.length === 0) {\n return {\n avgTickTime: 0,\n maxTickTime: 0,\n minTickTime: 0,\n ticksPerSecond: 0,\n };\n }\n\n const sum = this.tickTimes.reduce((a, b) => a + b, 0);\n const avg = sum / this.tickTimes.length;\n\n return {\n avgTickTime: avg,\n maxTickTime: Math.max(...this.tickTimes),\n minTickTime: Math.min(...this.tickTimes),\n ticksPerSecond: 1000 / avg,\n };\n }\n\n /**\n * Schedule the next tick with drift compensation.\n */\n private scheduleNextTick(): void {\n if (!this.running) return;\n\n const now = performance.now();\n const elapsed = now - this.lastTickTime;\n const drift = elapsed - this.tickMs;\n\n // Compensate for drift (but never go negative)\n const nextDelay = Math.max(0, this.tickMs - drift);\n\n this.timeout = setTimeout(() => this.tick(), nextDelay);\n }\n\n /**\n * Execute one tick.\n */\n private tick(): void {\n const tickStart = performance.now();\n const deltaMs = tickStart - this.lastTickTime;\n this.lastTickTime = tickStart;\n this.tickNumber++;\n\n try {\n // Call all handlers\n for (const handler of this.handlers) {\n handler.onTick(this.tickNumber, deltaMs);\n }\n } catch (error) {\n logger.error({ error, tick: this.tickNumber }, 'Error in tick handler');\n }\n\n // Record tick processing time\n const tickDuration = performance.now() - tickStart;\n this.recordTickTime(tickDuration);\n\n // Warn if tick took too long (>80% of budget)\n if (tickDuration > this.tickMs * 0.8) {\n logger.warn(\n {\n tickNumber: this.tickNumber,\n duration: tickDuration,\n budget: this.tickMs,\n },\n 'Tick took too long',\n );\n }\n\n // Schedule next tick\n this.scheduleNextTick();\n }\n\n /**\n * Record tick time for metrics.\n */\n private recordTickTime(duration: number): void {\n this.tickTimes.push(duration);\n\n // Keep only last N samples\n if (this.tickTimes.length > this.metricsWindowSize) {\n this.tickTimes.shift();\n }\n }\n}\n","/**\n * Entity Registry\n *\n * Manages entity lifecycle and provides efficient queries.\n */\n\nimport { Entity } from './Entity.js';\nimport { logger } from '../utils/Logger.js';\n\n/**\n * Entity registry with lifecycle management.\n *\n * Provides zero-allocation queries using pre-allocated buffers\n * to minimize GC pressure in hot paths.\n */\nexport class Registry<TEntity extends Entity = Entity> {\n private readonly entities = new Map<string, TEntity>();\n private readonly dirtyEntities = new Set<string>();\n\n // Pre-allocated buffers to avoid allocations in hot paths\n private readonly dirtyBuffer: TEntity[] = [];\n private readonly allBuffer: TEntity[] = [];\n\n /**\n * Add an entity to the registry.\n */\n add(entity: TEntity): void {\n if (this.entities.has(entity.id)) {\n logger.warn({ entityId: entity.id }, 'Entity already exists in registry');\n return;\n }\n\n this.entities.set(entity.id, entity);\n this.dirtyEntities.add(entity.id);\n\n logger.debug({ entityId: entity.id }, 'Entity added to registry');\n }\n\n /**\n * Remove an entity from the registry.\n */\n remove(entityId: string): boolean {\n const entity = this.entities.get(entityId);\n if (!entity) return false;\n\n this.entities.delete(entityId);\n this.dirtyEntities.delete(entityId);\n\n logger.debug({ entityId }, 'Entity removed from registry');\n\n return true;\n }\n\n /**\n * Get an entity by ID.\n */\n get(entityId: string): TEntity | undefined {\n return this.entities.get(entityId);\n }\n\n /**\n * Check if entity exists.\n */\n has(entityId: string): boolean {\n return this.entities.has(entityId);\n }\n\n /**\n * Mark an entity as dirty (needs broadcast).\n */\n markDirty(entityId: string): void {\n if (this.entities.has(entityId)) {\n this.dirtyEntities.add(entityId);\n }\n }\n\n /**\n * Get all dirty entities and clear dirty flags.\n * OPTIMIZED: Reuses buffer array to avoid allocations.\n *\n * @returns Array of dirty entities (reused buffer - don't store reference!)\n */\n getDirtyEntities(): TEntity[] {\n // Reset buffer without reallocation\n this.dirtyBuffer.length = 0;\n\n for (const entityId of this.dirtyEntities) {\n const entity = this.entities.get(entityId);\n if (entity) {\n this.dirtyBuffer.push(entity);\n entity.markClean();\n }\n }\n\n this.dirtyEntities.clear();\n\n return this.dirtyBuffer;\n }\n\n /**\n * Get all entities.\n * OPTIMIZED: Reuses buffer array to avoid allocations.\n *\n * @returns Array of all entities (reused buffer - don't store reference!)\n */\n getAll(): TEntity[] {\n this.allBuffer.length = 0;\n for (const entity of this.entities.values()) {\n this.allBuffer.push(entity);\n }\n return this.allBuffer;\n }\n\n /**\n * Get entity count.\n */\n size(): number {\n return this.entities.size;\n }\n\n /**\n * Get dirty entity count.\n */\n dirtyCount(): number {\n return this.dirtyEntities.size;\n }\n\n /**\n * Clear all entities.\n */\n clear(): void {\n this.entities.clear();\n this.dirtyEntities.clear();\n logger.debug('Registry cleared');\n }\n\n /**\n * Execute callback for each entity.\n */\n forEach(callback: (entity: TEntity) => void): void {\n for (const entity of this.entities.values()) {\n callback(entity);\n }\n }\n\n /**\n * Filter entities by predicate.\n *\n * @param predicate - Filter function\n * @returns New array of matching entities\n */\n filter(predicate: (entity: TEntity) => boolean): TEntity[] {\n const result: TEntity[] = [];\n for (const entity of this.entities.values()) {\n if (predicate(entity)) {\n result.push(entity);\n }\n }\n return result;\n }\n}\n","/**\n * Grid System\n *\n * Spatial partitioning using a fixed-size grid.\n * Enables O(1) lookup for nearby entities.\n */\n\nimport { logger } from '../utils/Logger.js';\n\n/**\n * A single cell in the grid.\n */\ninterface GridCell {\n readonly x: number;\n readonly y: number;\n readonly entities: Set<string>;\n}\n\n/**\n * Grid-based spatial partitioning system.\n *\n * Uses a hash map of cells for O(1) entity tracking.\n * Automatically cleans up empty cells to prevent memory leaks.\n */\nexport class Grid {\n private readonly cellSize: number;\n private readonly cells = new Map<string, GridCell>();\n private readonly entityCells = new Map<string, string>(); // entityId -> cellKey\n\n /**\n * Create a new spatial grid.\n *\n * @param cellSize - Size of each cell in world units (default: 512)\n */\n constructor(cellSize = 512) {\n this.cellSize = cellSize;\n }\n\n /**\n * Convert world coordinates to cell key.\n */\n getCellKey(worldX: number, worldY: number): string {\n const cellX = Math.floor(worldX / this.cellSize);\n const cellY = Math.floor(worldY / this.cellSize);\n return `${cellX},${cellY}`;\n }\n\n /**\n * Get or create a cell at world coordinates.\n */\n private getCell(worldX: number, worldY: number): GridCell {\n const key = this.getCellKey(worldX, worldY);\n let cell = this.cells.get(key);\n\n if (!cell) {\n const cellX = Math.floor(worldX / this.cellSize);\n const cellY = Math.floor(worldY / this.cellSize);\n cell = { x: cellX, y: cellY, entities: new Set() };\n this.cells.set(key, cell);\n }\n\n return cell;\n }\n\n /**\n * Add an entity to the grid.\n */\n addEntity(entityId: string, x: number, y: number): void {\n const cell = this.getCell(x, y);\n cell.entities.add(entityId);\n this.entityCells.set(entityId, this.getCellKey(x, y));\n\n logger.debug(\n { entityId, cellX: cell.x, cellY: cell.y },\n 'Entity added to grid',\n );\n }\n\n /**\n * Remove an entity from the grid.\n */\n removeEntity(entityId: string): void {\n const cellKey = this.entityCells.get(entityId);\n if (!cellKey) return;\n\n const cell = this.cells.get(cellKey);\n if (cell) {\n cell.entities.delete(entityId);\n\n // Clean up empty cells\n if (cell.entities.size === 0) {\n this.cells.delete(cellKey);\n }\n }\n\n this.entityCells.delete(entityId);\n\n logger.debug({ entityId }, 'Entity removed from grid');\n }\n\n /**\n * Move an entity to a new position.\n * Returns true if the entity changed cells.\n */\n moveEntity(\n entityId: string,\n oldX: number,\n oldY: number,\n newX: number,\n newY: number,\n ): boolean {\n const oldKey = this.getCellKey(oldX, oldY);\n const newKey = this.getCellKey(newX, newY);\n\n // Same cell, no update needed\n if (oldKey === newKey) {\n return false;\n }\n\n // Remove from old cell\n const oldCell = this.cells.get(oldKey);\n if (oldCell) {\n oldCell.entities.delete(entityId);\n if (oldCell.entities.size === 0) {\n this.cells.delete(oldKey);\n }\n }\n\n // Add to new cell\n const newCell = this.getCell(newX, newY);\n newCell.entities.add(entityId);\n this.entityCells.set(entityId, newKey);\n\n logger.debug({ entityId, oldKey, newKey }, 'Entity moved to new cell');\n\n return true;\n }\n\n /**\n * Get all entities in nearby cells.\n *\n * @param worldX - World X coordinate\n * @param worldY - World Y coordinate\n * @param range - Range in grid cells (default: 1 = 3x3 area)\n */\n getNearbyEntities(worldX: number, worldY: number, range = 1): string[] {\n const centerCellX = Math.floor(worldX / this.cellSize);\n const centerCellY = Math.floor(worldY / this.cellSize);\n\n const entities: string[] = [];\n\n for (let dx = -range; dx <= range; dx++) {\n for (let dy = -range; dy <= range; dy++) {\n const key = `${centerCellX + dx},${centerCellY + dy}`;\n const cell = this.cells.get(key);\n if (cell) {\n entities.push(...cell.entities);\n }\n }\n }\n\n return entities;\n }\n\n /**\n * Get entities in a specific cell.\n */\n getEntitiesInCell(worldX: number, worldY: number): string[] {\n const cell = this.cells.get(this.getCellKey(worldX, worldY));\n return cell ? Array.from(cell.entities) : [];\n }\n\n /**\n * Get the cell an entity is in.\n */\n getEntityCell(entityId: string): string | undefined {\n return this.entityCells.get(entityId);\n }\n\n /**\n * Get total number of active cells.\n */\n getCellCount(): number {\n return this.cells.size;\n }\n\n /**\n * Get total entities in grid.\n */\n getEntityCount(): number {\n return this.entityCells.size;\n }\n\n /**\n * Clear all cells and entities.\n */\n clear(): void {\n this.cells.clear();\n this.entityCells.clear();\n logger.debug('Grid cleared');\n }\n}\n","/**\n * Ring Buffer\n *\n * O(1) insert and remove, fixed capacity, no allocations in hot path.\n * Used for input queues, position history, etc.\n */\n\nexport class RingBuffer<T> {\n private readonly buffer: (T | undefined)[];\n private head = 0; // Next write position\n private tail = 0; // Next read position\n private count = 0;\n\n constructor(private readonly capacity: number) {\n this.buffer = new Array(capacity);\n }\n\n /**\n * Add item to buffer. O(1)\n * Returns false if buffer is full.\n */\n push(item: T): boolean {\n if (this.count >= this.capacity) {\n return false; // Full\n }\n\n this.buffer[this.head] = item;\n this.head = (this.head + 1) % this.capacity;\n this.count++;\n return true;\n }\n\n /**\n * Add item, overwriting oldest if full. O(1)\n */\n pushOverwrite(item: T): T | undefined {\n let dropped: T | undefined;\n\n if (this.count >= this.capacity) {\n // Drop oldest\n dropped = this.buffer[this.tail];\n this.tail = (this.tail + 1) % this.capacity;\n this.count--;\n }\n\n this.buffer[this.head] = item;\n this.head = (this.head + 1) % this.capacity;\n this.count++;\n\n return dropped;\n }\n\n /**\n * Remove and return oldest item. O(1)\n */\n shift(): T | undefined {\n if (this.count === 0) {\n return undefined;\n }\n\n const item = this.buffer[this.tail];\n this.buffer[this.tail] = undefined; // Help GC\n this.tail = (this.tail + 1) % this.capacity;\n this.count--;\n\n return item;\n }\n\n /**\n * Peek at oldest item without removing. O(1)\n */\n peek(): T | undefined {\n if (this.count === 0) {\n return undefined;\n }\n return this.buffer[this.tail];\n }\n\n /**\n * Get current size.\n */\n size(): number {\n return this.count;\n }\n\n /**\n * Check if empty.\n */\n isEmpty(): boolean {\n return this.count === 0;\n }\n\n /**\n * Check if full.\n */\n isFull(): boolean {\n return this.count >= this.capacity;\n }\n\n /**\n * Clear all items. O(1)\n */\n clear(): void {\n // Don't need to clear array, just reset pointers\n this.head = 0;\n this.tail = 0;\n this.count = 0;\n }\n\n /**\n * Get capacity.\n */\n getCapacity(): number {\n return this.capacity;\n }\n}\n","/**\n * Input Queue\n *\n * Buffers player inputs for processing in the game loop.\n * Uses RingBuffer for O(1) push/pop operations.\n */\n\nimport { logger } from '../utils/Logger.js';\nimport { RingBuffer } from '../utils/RingBuffer.js';\nimport type { Command } from './Command.js';\n\n/**\n * Input queue manager using RingBuffer for O(1) operations.\n *\n * Manages input queues for multiple players, with automatic\n * overflow handling (drops oldest inputs when full).\n */\nexport class InputQueue {\n private readonly queues = new Map<string, RingBuffer<Command>>();\n private readonly maxQueueSize: number;\n\n /**\n * Create a new input queue manager.\n *\n * @param maxQueueSize - Maximum inputs per player (default: 100)\n */\n constructor(maxQueueSize = 100) {\n this.maxQueueSize = maxQueueSize;\n }\n\n /**\n * Get or create a player's queue.\n */\n private getQueue(playerId: string): RingBuffer<Command> {\n let queue = this.queues.get(playerId);\n if (!queue) {\n queue = new RingBuffer<Command>(this.maxQueueSize);\n this.queues.set(playerId, queue);\n }\n return queue;\n }\n\n /**\n * Add an input to a player's queue. O(1)\n */\n push(playerId: string, input: Command): void {\n const queue = this.getQueue(playerId);\n\n // Push with overwrite (drops oldest if full)\n const dropped = queue.pushOverwrite(input);\n if (dropped) {\n logger.debug({ playerId }, 'Input queue overflow, dropped oldest');\n }\n }\n\n /**\n * Get and remove the next input for a player. O(1)\n */\n pop(playerId: string): Command | undefined {\n const queue = this.queues.get(playerId);\n if (!queue) return undefined;\n return queue.shift();\n }\n\n /**\n * Peek at the next input without removing. O(1)\n */\n peek(playerId: string): Command | undefined {\n const queue = this.queues.get(playerId);\n return queue?.peek();\n }\n\n /**\n * Get all inputs for a player and clear.\n */\n drain(playerId: string): Command[] {\n const queue = this.queues.get(playerId);\n if (!queue) return [];\n\n const inputs: Command[] = [];\n while (!queue.isEmpty()) {\n const input = queue.shift();\n if (input) inputs.push(input);\n }\n return inputs;\n }\n\n /**\n * Get queue size for a player.\n */\n size(playerId: string): number {\n return this.queues.get(playerId)?.size() ?? 0;\n }\n\n /**\n * Clear a player's queue.\n */\n clear(playerId: string): void {\n const queue = this.queues.get(playerId);\n if (queue) {\n queue.clear();\n }\n // Don't delete the queue itself - reuse it\n }\n\n /**\n * Remove a player's queue entirely.\n */\n remove(playerId: string): void {\n this.queues.delete(playerId);\n }\n\n /**\n * Clear all queues.\n */\n clearAll(): void {\n this.queues.clear();\n }\n\n /**\n * Get total queued inputs across all players.\n */\n getTotalSize(): number {\n let total = 0;\n for (const queue of this.queues.values()) {\n total += queue.size();\n }\n return total;\n }\n}\n","/**\n * Network Layer\n *\n * Broadcast and send utilities for game events.\n */\n\nimport type { Server, Socket } from 'socket.io';\nimport { logger } from '../utils/Logger.js';\nimport type { NetworkEvent } from '../types/index.js';\n\n/**\n * Network layer for broadcasting game events.\n *\n * Wraps Socket.io with game-specific utilities.\n */\nexport class Network {\n private io: Server | null = null;\n private readonly sockets = new Map<string, Socket>();\n\n /**\n * Set the Socket.io server instance.\n */\n setServer(io: Server): void {\n this.io = io;\n }\n\n /**\n * Register a socket connection.\n */\n registerSocket(playerId: string, socket: Socket): void {\n this.sockets.set(playerId, socket);\n logger.debug({ playerId }, 'Socket registered');\n }\n\n /**\n * Unregister a socket connection.\n */\n unregisterSocket(playerId: string): void {\n this.sockets.delete(playerId);\n logger.debug({ playerId }, 'Socket unregistered');\n }\n\n /**\n * Get a socket by player ID.\n */\n getSocket(playerId: string): Socket | undefined {\n return this.sockets.get(playerId);\n }\n\n /**\n * Broadcast event to all connected players.\n */\n broadcast(event: NetworkEvent): void {\n if (!this.io) {\n logger.warn('Cannot broadcast - no Socket.io server set');\n return;\n }\n\n this.io.emit(event.op, event);\n logger.debug({ opcode: event.op }, 'Broadcast event');\n }\n\n /**\n * Broadcast event to all players in a room.\n */\n broadcastToRoom(roomId: string, event: NetworkEvent): void {\n if (!this.io) {\n logger.warn('Cannot broadcast - no Socket.io server set');\n return;\n }\n\n this.io.to(roomId).emit(event.op, event);\n logger.debug({ roomId, opcode: event.op }, 'Broadcast to room');\n }\n\n /**\n * Send event to a specific player.\n */\n sendTo(playerId: string, event: NetworkEvent): void {\n const socket = this.sockets.get(playerId);\n if (!socket) {\n logger.warn({ playerId }, 'Cannot send - socket not found');\n return;\n }\n\n socket.emit(event.op, event);\n logger.debug({ playerId, opcode: event.op }, 'Sent to player');\n }\n\n /**\n * Send event to multiple players.\n */\n sendToMany(playerIds: string[], event: NetworkEvent): void {\n for (const playerId of playerIds) {\n this.sendTo(playerId, event);\n }\n }\n\n /**\n * Get connected player count.\n */\n getPlayerCount(): number {\n return this.sockets.size;\n }\n\n /**\n * Clear all sockets.\n */\n clear(): void {\n this.sockets.clear();\n }\n}\n","/**\n * Snapshot System\n *\n * Full state snapshots for network synchronization.\n */\n\nimport type { Entity } from '../entities/Entity.js';\nimport type { StateSnapshot, EntitySnapshot } from '../types/index.js';\n\n/**\n * Snapshot generator.\n *\n * Creates full state snapshots for sending to clients.\n * Used for initial sync and periodic full updates.\n */\nexport class Snapshot {\n /**\n * Create a full state snapshot from entities.\n *\n * @param tick - Current tick number\n * @param entities - Array of entities to snapshot\n * @returns Full state snapshot\n */\n static create(tick: number, entities: Entity[]): StateSnapshot {\n return {\n tick,\n timestamp: Date.now(),\n entities: entities.map((e) => this.entityToSnapshot(e)),\n };\n }\n\n /**\n * Convert an entity to a snapshot.\n */\n static entityToSnapshot(entity: Entity): EntitySnapshot {\n return {\n id: entity.id,\n x: entity.x,\n y: entity.y,\n vx: entity.vx,\n vy: entity.vy,\n };\n }\n\n /**\n * Create a delta snapshot (only dirty entities).\n *\n * @param tick - Current tick number\n * @param dirtyEntities - Array of dirty entities\n * @returns Delta snapshot\n */\n static createDelta(tick: number, dirtyEntities: Entity[]): StateSnapshot {\n return {\n tick,\n timestamp: Date.now(),\n entities: dirtyEntities.map((e) => this.entityToSnapshot(e)),\n };\n }\n}\n","/**\n * Room\n *\n * A single game room/match instance.\n * Manages entities, tick loop, and networking.\n */\n\nimport { GameLoop, type TickHandler } from './GameLoop.js';\nimport type { GameRules } from './GameRules.js';\nimport { Entity } from '../entities/Entity.js';\nimport { Registry } from '../entities/Registry.js';\nimport { Grid } from '../spatial/Grid.js';\nimport { InputQueue } from '../input/InputQueue.js';\nimport { Network } from '../network/Network.js';\nimport { Snapshot } from '../network/Snapshot.js';\nimport { logger } from '../utils/Logger.js';\nimport type {\n RoomConfig,\n NetworkEvent,\n StateSnapshot,\n} from '../types/index.js';\nimport type { Command } from '../input/Command.js';\n\n/**\n * A single game room/match.\n *\n * Orchestrates all game systems: tick loop, entities, spatial partitioning,\n * input processing, and network synchronization.\n *\n * @example\n * ```typescript\n * const room = new Room('room-1', new MyGameRules(), {\n * tickRate: 20,\n * cellSize: 512,\n * });\n *\n * room.start();\n *\n * // Add players\n * const player = new Entity('player-1', 100, 100);\n * room.addPlayer(player);\n * ```\n */\nexport class Room<TEntity extends Entity = Entity> implements TickHandler {\n /** Room identifier */\n readonly id: string;\n\n /** Game-specific logic */\n readonly rules: GameRules<TEntity>;\n\n // Core systems\n private readonly registry: Registry<TEntity>;\n private readonly grid: Grid;\n private readonly loop: GameLoop;\n private readonly inputQueue: InputQueue;\n private readonly network: Network;\n\n // State\n private readonly players = new Map<string, TEntity>();\n private tickCount = 0;\n private startTime = 0;\n private readonly config: Required<RoomConfig>;\n\n /**\n * Create a new room.\n *\n * @param id - Unique room identifier\n * @param rules - Game-specific logic\n * @param config - Room configuration\n */\n constructor(id: string, rules: GameRules<TEntity>, config?: RoomConfig) {\n this.id = id;\n this.rules = rules;\n\n // Apply defaults\n this.config = {\n tickRate: config?.tickRate ?? 20,\n cellSize: config?.cellSize ?? 512,\n maxInputQueueSize: config?.maxInputQueueSize ?? 100,\n maxEntities: config?.maxEntities ?? 1000,\n visibilityRange: config?.visibilityRange ?? 1,\n };\n\n // Initialize systems\n this.registry = new Registry<TEntity>();\n this.grid = new Grid(this.config.cellSize);\n this.loop = new GameLoop(this.config.tickRate);\n this.inputQueue = new InputQueue(this.config.maxInputQueueSize);\n this.network = new Network();\n\n // Register tick handler\n this.loop.addHandler(this);\n\n logger.info({ roomId: id, config: this.config }, 'Room created');\n }\n\n /**\n * Start the room (begins tick loop).\n */\n start(): void {\n this.startTime = Date.now();\n\n try {\n this.rules.onRoomCreated(this);\n } catch (error) {\n logger.error({ error, roomId: this.id }, 'Error in onRoomCreated');\n }\n\n this.loop.start();\n logger.info({ roomId: this.id }, 'Room started');\n }\n\n /**\n * Stop the room (ends tick loop).\n */\n stop(): void {\n this.loop.stop();\n logger.info(\n { roomId: this.id, totalTicks: this.tickCount },\n 'Room stopped',\n );\n }\n\n /**\n * Add a player to the room.\n */\n addPlayer(player: TEntity): void {\n if (this.players.has(player.id)) {\n logger.warn({ playerId: player.id }, 'Player already in room');\n return;\n }\n\n this.players.set(player.id, player);\n this.registry.add(player);\n this.grid.addEntity(player.id, player.x, player.y);\n\n try {\n this.rules.onPlayerJoin(this, player);\n } catch (error) {\n logger.error({ error, playerId: player.id }, 'Error in onPlayerJoin');\n }\n\n logger.info({ roomId: this.id, playerId: player.id }, 'Player joined');\n }\n\n /**\n * Remove a player from the room.\n */\n removePlayer(playerId: string): void {\n const player = this.players.get(playerId);\n if (!player) return;\n\n this.players.delete(playerId);\n this.registry.remove(playerId);\n this.grid.removeEntity(playerId);\n this.inputQueue.remove(playerId);\n\n try {\n this.rules.onPlayerLeave(this, playerId);\n } catch (error) {\n logger.error({ error, playerId }, 'Error in onPlayerLeave');\n }\n\n logger.info({ roomId: this.id, playerId }, 'Player left');\n }\n\n /**\n * Spawn a non-player entity.\n */\n spawnEntity(entity: TEntity): void {\n if (this.registry.size() >= this.config.maxEntities) {\n logger.warn({ roomId: this.id }, 'Max entities reached, cannot spawn');\n return;\n }\n\n this.registry.add(entity);\n this.grid.addEntity(entity.id, entity.x, entity.y);\n\n logger.debug({ entityId: entity.id }, 'Entity spawned');\n }\n\n /**\n * Destroy an entity.\n */\n destroyEntity(entityId: string): void {\n const entity = this.registry.get(entityId);\n if (!entity) return;\n\n this.registry.remove(entityId);\n this.grid.removeEntity(entityId);\n\n logger.debug({ entityId }, 'Entity destroyed');\n }\n\n /**\n * Queue a player input.\n */\n queueInput(playerId: string, command: Command): void {\n if (!this.players.has(playerId)) {\n logger.warn({ playerId }, 'Input from non-player');\n return;\n }\n\n this.inputQueue.push(playerId, command);\n }\n\n /**\n * Broadcast event to all players.\n */\n broadcast(event: NetworkEvent): void {\n this.network.broadcastToRoom(this.id, event);\n }\n\n /**\n * Send event to specific player.\n */\n sendTo(playerId: string, event: NetworkEvent): void {\n this.network.sendTo(playerId, event);\n }\n\n /**\n * Get full state snapshot.\n */\n getSnapshot(): StateSnapshot {\n return Snapshot.create(this.tickCount, this.registry.getAll());\n }\n\n /**\n * Get delta snapshot (only dirty entities).\n */\n getDeltaSnapshot(): StateSnapshot {\n return Snapshot.createDelta(\n this.tickCount,\n this.registry.getDirtyEntities(),\n );\n }\n\n /**\n * Main tick function (called by GameLoop).\n */\n onTick(tickNumber: number, deltaMs: number): void {\n this.tickCount = tickNumber;\n\n // Process all queued inputs\n for (const [playerId] of this.players) {\n const inputs = this.inputQueue.drain(playerId);\n for (const input of inputs) {\n try {\n this.rules.onCommand(this, playerId, input);\n } catch (error) {\n logger.error(\n { error, playerId, command: input.type },\n 'Error in onCommand',\n );\n }\n }\n }\n\n // Run game logic\n try {\n this.rules.onTick(this, deltaMs);\n } catch (error) {\n logger.error({ error, tick: tickNumber }, 'Error in onTick');\n }\n\n // Broadcast dirty entities\n const dirtyEntities = this.registry.getDirtyEntities();\n if (dirtyEntities.length > 0) {\n const delta = Snapshot.createDelta(this.tickCount, dirtyEntities);\n this.broadcast({\n op: 'S_UPDATE',\n ...delta,\n });\n }\n\n // Check if room should end\n try {\n if (this.rules.shouldEndRoom(this)) {\n logger.info({ roomId: this.id }, 'Room ending per game rules');\n this.stop();\n }\n } catch (error) {\n logger.error({ error }, 'Error in shouldEndRoom');\n }\n }\n\n // Getters\n\n /**\n * Get all players.\n */\n getPlayers(): Map<string, TEntity> {\n return this.players;\n }\n\n /**\n * Get entity registry.\n */\n getRegistry(): Registry<TEntity> {\n return this.registry;\n }\n\n /**\n * Get spatial grid.\n */\n getGrid(): Grid {\n return this.grid;\n }\n\n /**\n * Get network layer.\n */\n getNetwork(): Network {\n return this.network;\n }\n\n /**\n * Get input queue.\n */\n getInputQueue(): InputQueue {\n return this.inputQueue;\n }\n\n /**\n * Get current tick number.\n */\n getTickCount(): number {\n return this.tickCount;\n }\n\n /**\n * Get uptime in milliseconds.\n */\n getUptime(): number {\n return Date.now() - this.startTime;\n }\n\n /**\n * Check if room is running.\n */\n isRunning(): boolean {\n return this.loop.isRunning();\n }\n\n /**\n * Get room configuration.\n */\n getConfig(): Required<RoomConfig> {\n return { ...this.config };\n }\n\n /**\n * Get room metrics.\n */\n getMetrics() {\n const loopMetrics = this.loop.getMetrics();\n return {\n roomId: this.id,\n tickCount: this.tickCount,\n uptime: this.getUptime(),\n playerCount: this.players.size,\n entityCount: this.registry.size(),\n cellCount: this.grid.getCellCount(),\n queuedInputs: this.inputQueue.getTotalSize(),\n ...loopMetrics,\n };\n }\n}\n","/**\n * Game Server\n *\n * Multi-room game server.\n * Manages room lifecycle and routing.\n */\n\nimport type { Server } from 'socket.io';\nimport { Room } from './Room.js';\nimport type { GameRules } from './GameRules.js';\nimport type { Entity } from '../entities/Entity.js';\nimport { logger } from '../utils/Logger.js';\nimport type { RoomConfig, ServerMetrics } from '../types/index.js';\n\n/**\n * Multi-room game server.\n *\n * Orchestrates multiple game rooms and provides routing\n * for Socket.io connections.\n *\n * @example\n * ```typescript\n * const server = new GameServer();\n * server.setServer(io);\n *\n * const room = server.createRoom('room-1', new MyGameRules());\n *\n * // Later...\n * server.destroyRoom('room-1');\n * ```\n */\nexport class GameServer {\n private readonly rooms = new Map<string, Room>();\n private io: Server | null = null;\n\n /**\n * Set the Socket.io server instance.\n *\n * This should be called before creating rooms to enable\n * network functionality.\n */\n setServer(io: Server): void {\n this.io = io;\n\n // Set server on all existing rooms\n for (const room of this.rooms.values()) {\n room.getNetwork().setServer(io);\n }\n\n logger.info('Socket.io server set');\n }\n\n /**\n * Create a new room.\n *\n * @param id - Unique room identifier\n * @param rules - Game-specific logic\n * @param config - Room configuration\n * @returns The created room\n * @throws If room with same ID already exists\n */\n createRoom<TEntity extends Entity = Entity>(\n id: string,\n rules: GameRules<TEntity>,\n config?: RoomConfig,\n ): Room<TEntity> {\n if (this.rooms.has(id)) {\n throw new Error(`Room ${id} already exists`);\n }\n\n const room = new Room(id, rules, config);\n\n // Set network server if available\n if (this.io) {\n room.getNetwork().setServer(this.io);\n }\n\n this.rooms.set(id, room as Room);\n room.start();\n\n logger.info({ roomId: id }, 'Room created and started');\n\n return room;\n }\n\n /**\n * Destroy a room.\n *\n * Stops the room's tick loop and removes it from the server.\n *\n * @param id - Room identifier\n * @returns True if room was destroyed, false if not found\n */\n destroyRoom(id: string): boolean {\n const room = this.rooms.get(id);\n if (!room) {\n logger.warn({ roomId: id }, 'Cannot destroy - room not found');\n return false;\n }\n\n room.stop();\n this.rooms.delete(id);\n\n logger.info({ roomId: id }, 'Room destroyed');\n\n return true;\n }\n\n /**\n * Get a room by ID.\n */\n getRoom(id: string): Room | undefined {\n return this.rooms.get(id);\n }\n\n /**\n * Get a room with specific entity type.\n *\n * @param id - Room identifier\n * @returns Room cast to specific entity type, or undefined\n */\n getRoomAs<TEntity extends Entity>(id: string): Room<TEntity> | undefined {\n return this.rooms.get(id) as Room<TEntity> | undefined;\n }\n\n /**\n * Check if room exists.\n */\n hasRoom(id: string): boolean {\n return this.rooms.has(id);\n }\n\n /**\n * Get all rooms.\n */\n getRooms(): Map<string, Room> {\n return this.rooms;\n }\n\n /**\n * Get room count.\n */\n getRoomCount(): number {\n return this.rooms.size;\n }\n\n /**\n * Get total player count across all rooms.\n */\n getTotalPlayerCount(): number {\n let total = 0;\n for (const room of this.rooms.values()) {\n total += room.getPlayers().size;\n }\n return total;\n }\n\n /**\n * Get server health metrics.\n */\n getMetrics(): ServerMetrics {\n return {\n roomCount: this.rooms.size,\n totalPlayers: this.getTotalPlayerCount(),\n rooms: Array.from(this.rooms.values()).map((room) => ({\n id: room.id,\n playerCount: room.getPlayers().size,\n entityCount: room.getRegistry().size(),\n tickCount: room.getTickCount(),\n isRunning: room.isRunning(),\n avgTickTime: room.getMetrics().avgTickTime,\n ticksPerSecond: room.getMetrics().ticksPerSecond,\n })),\n };\n }\n\n /**\n * Stop all rooms.\n */\n stopAll(): void {\n logger.info({ roomCount: this.rooms.size }, 'Stopping all rooms');\n\n for (const room of this.rooms.values()) {\n room.stop();\n }\n }\n\n /**\n * Destroy all rooms.\n */\n destroyAll(): void {\n logger.info({ roomCount: this.rooms.size }, 'Destroying all rooms');\n\n for (const room of this.rooms.values()) {\n room.stop();\n }\n\n this.rooms.clear();\n }\n}\n","/**\n * Entity System\n *\n * Base entity class for all game objects.\n */\n\n/**\n * Base entity class.\n * All game objects (players, NPCs, items) extend this.\n *\n * Includes position, velocity, and dirty flag for\n * efficient network synchronization.\n */\nexport class Entity {\n /** Unique entity identifier */\n readonly id: string;\n\n /** World X position */\n x: number;\n\n /** World Y position */\n y: number;\n\n /** Velocity X (units/second) */\n vx: number;\n\n /** Velocity Y (units/second) */\n vy: number;\n\n /** Dirty flag - entity needs to be broadcast */\n dirty: boolean;\n\n /** Last update timestamp */\n lastUpdate: number;\n\n /**\n * Create a new entity.\n *\n * @param id - Unique identifier\n * @param x - Initial X position\n * @param y - Initial Y position\n */\n constructor(id: string, x: number, y: number) {\n this.id = id;\n this.x = x;\n this.y = y;\n this.vx = 0;\n this.vy = 0;\n this.dirty = true; // New entities need to be broadcast\n this.lastUpdate = Date.now();\n }\n\n /**\n * Update position based on velocity and delta time.\n *\n * @param deltaMs - Time since last update (milliseconds)\n */\n updatePosition(deltaMs: number): void {\n if (this.vx !== 0 || this.vy !== 0) {\n const deltaSec = deltaMs / 1000;\n this.x += this.vx * deltaSec;\n this.y += this.vy * deltaSec;\n this.dirty = true;\n this.lastUpdate = Date.now();\n }\n }\n\n /**\n * Set velocity.\n */\n setVelocity(vx: number, vy: number): void {\n if (this.vx !== vx || this.vy !== vy) {\n this.vx = vx;\n this.vy = vy;\n this.dirty = true;\n this.lastUpdate = Date.now();\n }\n }\n\n /**\n * Teleport to position (no velocity integration).\n */\n setPosition(x: number, y: number): void {\n if (this.x !== x || this.y !== y) {\n this.x = x;\n this.y = y;\n this.dirty = true;\n this.lastUpdate = Date.now();\n }\n }\n\n /**\n * Mark entity as clean (after broadcast).\n */\n markClean(): void {\n this.dirty = false;\n }\n\n /**\n * Mark entity as dirty (needs broadcast).\n */\n markDirty(): void {\n this.dirty = true;\n }\n\n /**\n * Get entity as plain object for serialization.\n */\n toJSON(): Record<string, unknown> {\n return {\n id: this.id,\n x: this.x,\n y: this.y,\n vx: this.vx,\n vy: this.vy,\n };\n }\n}\n","/**\n * AABB Collision Detection\n *\n * Axis-Aligned Bounding Box collision detection.\n */\n\nimport type { Entity } from '../entities/Entity.js';\n\n/**\n * Axis-Aligned Bounding Box.\n */\nexport interface AABB {\n x: number; // Center X\n y: number; // Center Y\n width: number; // Total width\n height: number; // Total height\n}\n\n/**\n * AABB collision detection utilities.\n */\nexport class AABBCollision {\n /**\n * Check if two AABBs overlap.\n */\n static overlaps(a: AABB, b: AABB): boolean {\n const aHalfW = a.width / 2;\n const aHalfH = a.height / 2;\n const bHalfW = b.width / 2;\n const bHalfH = b.height / 2;\n\n return (\n Math.abs(a.x - b.x) < aHalfW + bHalfW &&\n Math.abs(a.y - b.y) < aHalfH + bHalfH\n );\n }\n\n /**\n * Check if a point is inside an AABB.\n */\n static containsPoint(aabb: AABB, x: number, y: number): boolean {\n const halfW = aabb.width / 2;\n const halfH = aabb.height / 2;\n\n return (\n x >= aabb.x - halfW &&\n x <= aabb.x + halfW &&\n y >= aabb.y - halfH &&\n y <= aabb.y + halfH\n );\n }\n\n /**\n * Create AABB from entity.\n */\n static fromEntity(entity: Entity, width: number, height: number): AABB {\n return {\n x: entity.x,\n y: entity.y,\n width,\n height,\n };\n }\n\n /**\n * Get the distance between two AABBs.\n * Returns 0 if overlapping.\n */\n static distance(a: AABB, b: AABB): number {\n const dx = Math.abs(a.x - b.x);\n const dy = Math.abs(a.y - b.y);\n const combinedHalfW = (a.width + b.width) / 2;\n const combinedHalfH = (a.height + b.height) / 2;\n\n const gapX = Math.max(0, dx - combinedHalfW);\n const gapY = Math.max(0, dy - combinedHalfH);\n\n return Math.sqrt(gapX * gapX + gapY * gapY);\n }\n\n /**\n * Compute the overlap amount between two AABBs.\n * Returns { x: 0, y: 0 } if not overlapping.\n */\n static overlap(a: AABB, b: AABB): { x: number; y: number } {\n const dx = a.x - b.x;\n const dy = a.y - b.y;\n\n const combinedHalfW = (a.width + b.width) / 2;\n const combinedHalfH = (a.height + b.height) / 2;\n\n const overlapX = combinedHalfW - Math.abs(dx);\n const overlapY = combinedHalfH - Math.abs(dy);\n\n if (overlapX > 0 && overlapY > 0) {\n return {\n x: overlapX * Math.sign(dx),\n y: overlapY * Math.sign(dy),\n };\n }\n\n return { x: 0, y: 0 };\n }\n}\n","/**\n * Movement Physics\n *\n * Velocity integration and boundary constraints.\n */\n\nimport type { Entity } from '../entities/Entity.js';\n\n/**\n * Boundary constraints for movement.\n */\nexport interface Boundary {\n minX: number;\n maxX: number;\n minY: number;\n maxY: number;\n}\n\n/**\n * Movement physics utilities.\n */\nexport class Movement {\n /**\n * Update entity position based on velocity.\n *\n * @param entity - Entity to update\n * @param deltaMs - Time delta in milliseconds\n */\n static integrate(entity: Entity, deltaMs: number): void {\n if (entity.vx === 0 && entity.vy === 0) return;\n\n const deltaSec = deltaMs / 1000;\n entity.x += entity.vx * deltaSec;\n entity.y += entity.vy * deltaSec;\n entity.markDirty();\n }\n\n /**\n * Apply velocity to entity.\n */\n static applyVelocity(entity: Entity, vx: number, vy: number): void {\n entity.setVelocity(vx, vy);\n }\n\n /**\n * Stop entity movement.\n */\n static stop(entity: Entity): void {\n entity.setVelocity(0, 0);\n }\n\n /**\n * Constrain entity to boundary.\n *\n * @param entity - Entity to constrain\n * @param boundary - Boundary constraints\n * @returns True if entity was clamped\n */\n static constrainToBoundary(entity: Entity, boundary: Boundary): boolean {\n let clamped = false;\n\n if (entity.x < boundary.minX) {\n entity.x = boundary.minX;\n entity.vx = 0;\n clamped = true;\n } else if (entity.x > boundary.maxX) {\n entity.x = boundary.maxX;\n entity.vx = 0;\n clamped = true;\n }\n\n if (entity.y < boundary.minY) {\n entity.y = boundary.minY;\n entity.vy = 0;\n clamped = true;\n } else if (entity.y > boundary.maxY) {\n entity.y = boundary.maxY;\n entity.vy = 0;\n clamped = true;\n }\n\n if (clamped) {\n entity.markDirty();\n }\n\n return clamped;\n }\n\n /**\n * Calculate distance between two entities.\n */\n static distance(a: Entity, b: Entity): number {\n const dx = a.x - b.x;\n const dy = a.y - b.y;\n return Math.sqrt(dx * dx + dy * dy);\n }\n\n /**\n * Normalize a direction vector.\n */\n static normalize(x: number, y: number): { x: number; y: number } {\n const length = Math.sqrt(x * x + y * y);\n if (length === 0) return { x: 0, y: 0 };\n return {\n x: x / length,\n y: y / length,\n };\n }\n\n /**\n * Calculate velocity from direction and speed.\n */\n static velocityFromDirection(\n dirX: number,\n dirY: number,\n speed: number,\n ): { vx: number; vy: number } {\n const normalized = this.normalize(dirX, dirY);\n return {\n vx: normalized.x * speed,\n vy: normalized.y * speed,\n };\n }\n}\n","/**\n * Network protocol definitions.\n *\n * Opcodes and message formats for client-server communication.\n */\n\n/**\n * Client → Server opcodes.\n */\nexport enum ClientOpcode {\n /** Player movement input */\n C_MOVE = 'C_MOVE',\n\n /** Player stop input */\n C_STOP = 'C_STOP',\n\n /** Generic action */\n C_ACTION = 'C_ACTION',\n}\n\n/**\n * Server → Client opcodes.\n */\nexport enum ServerOpcode {\n /** Initial state on join */\n S_INIT = 'S_INIT',\n\n /** Delta state update */\n S_UPDATE = 'S_UPDATE',\n\n /** Entity spawned */\n S_SPAWN = 'S_SPAWN',\n\n /** Entity destroyed */\n S_DESPAWN = 'S_DESPAWN',\n\n /** Custom game event */\n S_EVENT = 'S_EVENT',\n\n /** Error message */\n S_ERROR = 'S_ERROR',\n}\n\n/**\n * Client movement input.\n */\nexport interface C_Move {\n op: ClientOpcode.C_MOVE;\n seq: number;\n dir: { x: number; y: number };\n timestamp: number;\n}\n\n/**\n * Client stop input.\n */\nexport interface C_Stop {\n op: ClientOpcode.C_STOP;\n seq: number;\n timestamp: number;\n}\n\n/**\n * Client action input.\n */\nexport interface C_Action {\n op: ClientOpcode.C_ACTION;\n seq: number;\n action: string;\n data?: Record<string, unknown>;\n timestamp: number;\n}\n\n/**\n * Server initial state.\n */\nexport interface S_Init {\n op: ServerOpcode.S_INIT;\n playerId: string;\n tick: number;\n entities: Array<{\n id: string;\n x: number;\n y: number;\n vx: number;\n vy: number;\n }>;\n}\n\n/**\n * Server delta update.\n */\nexport interface S_Update {\n op: ServerOpcode.S_UPDATE;\n tick: number;\n entities: Array<{\n id: string;\n x: number;\n y: number;\n vx: number;\n vy: number;\n seq?: number; // Echo client seq for reconciliation\n }>;\n}\n\n/**\n * Server entity spawn.\n */\nexport interface S_Spawn {\n op: ServerOpcode.S_SPAWN;\n entity: {\n id: string;\n x: number;\n y: number;\n vx: number;\n vy: number;\n };\n}\n\n/**\n * Server entity despawn.\n */\nexport interface S_Despawn {\n op: ServerOpcode.S_DESPAWN;\n entityId: string;\n reason?: string;\n}\n\n/**\n * Server custom event.\n */\nexport interface S_Event {\n op: ServerOpcode.S_EVENT;\n event: string;\n data?: Record<string, unknown>;\n}\n\n/**\n * Server error message.\n */\nexport interface S_Error {\n op: ServerOpcode.S_ERROR;\n code: string;\n message: string;\n}\n\n/**\n * Union of all client messages.\n */\nexport type ClientMessage = C_Move | C_Stop | C_Action;\n\n/**\n * Union of all server messages.\n */\nexport type ServerMessage =\n | S_Init\n | S_Update\n | S_Spawn\n | S_Despawn\n | S_Event\n | S_Error;\n"]}
@@ -0,0 +1,176 @@
1
+ # Simple Game - Manual Testing Example
2
+
3
+ This is a minimal multiplayer game for **manually testing** the `@gamerstake/game-core` package.
4
+
5
+ ## What It Does
6
+
7
+ - Creates a persistent game world (1000x1000 units)
8
+ - Allows multiple players to connect
9
+ - Players can move around with velocity-based movement
10
+ - Spawns static obstacle entities
11
+ - Broadcasts game state updates at 20 TPS
12
+ - Logs metrics and player activity
13
+
14
+ ## Running the Test
15
+
16
+ ### 1. Build the package first
17
+
18
+ ```bash
19
+ cd /Users/nbjekovic/GAMESTAKES/gamerstake/packages/game-core
20
+ pnpm build
21
+ ```
22
+
23
+ ### 2. Start the server
24
+
25
+ ```bash
26
+ node examples/simple-game/server.js
27
+ ```
28
+
29
+ You should see:
30
+ ```
31
+ Game server started on port 3000
32
+ Room: test-room
33
+ Tick rate: 20 TPS
34
+ ```
35
+
36
+ ### 3. In another terminal, start a client
37
+
38
+ ```bash
39
+ node examples/simple-game/client.js
40
+ ```
41
+
42
+ The client will:
43
+ - Connect to the server
44
+ - Receive initial game state
45
+ - Automatically move around in different patterns
46
+ - Log position updates
47
+
48
+ ### 4. (Optional) Start more clients
49
+
50
+ Open additional terminals and run more clients:
51
+
52
+ ```bash
53
+ node examples/simple-game/client.js
54
+ ```
55
+
56
+ Each client is a separate player. You'll see them join in the server logs!
57
+
58
+ ## What to Watch For
59
+
60
+ ### On the Server
61
+
62
+ - Players connecting/disconnecting
63
+ - Movement commands being processed
64
+ - Game state updates being broadcast
65
+ - Tick performance metrics (should be <40ms)
66
+
67
+ ### On the Client
68
+
69
+ - Initial state received
70
+ - Position updates as player moves
71
+ - Other players joining/leaving
72
+
73
+ ## Testing Different Scenarios
74
+
75
+ ### Test 1: Movement
76
+
77
+ The client automatically cycles through movement patterns:
78
+ - Right, Down, Left, Up
79
+ - Diagonal movement
80
+ - Stop command
81
+ - Custom actions
82
+
83
+ ### Test 2: Multiple Players
84
+
85
+ Run 3-5 clients simultaneously to test:
86
+ - Multiple players in the same room
87
+ - State synchronization
88
+ - Network broadcasting
89
+ - Server performance
90
+
91
+ ### Test 3: Performance
92
+
93
+ Monitor the server metrics logs:
94
+ ```
95
+ Room: X players, Y entities, Avg tick: Zms
96
+ ```
97
+
98
+ Tick time should stay well below 50ms (the tick budget for 20 TPS).
99
+
100
+ ### Test 4: Connection Stability
101
+
102
+ Try:
103
+ - Stopping clients (Ctrl+C) and reconnecting
104
+ - Stopping the server and restarting
105
+ - Network interruptions
106
+
107
+ ## Customizing the Test
108
+
109
+ ### Change Server Port
110
+
111
+ ```bash
112
+ PORT=4000 node examples/simple-game/server.js
113
+ ```
114
+
115
+ ```bash
116
+ SERVER_URL=http://localhost:4000 node examples/simple-game/client.js
117
+ ```
118
+
119
+ ### Modify Game Rules
120
+
121
+ Edit `server.ts` and change the `SimpleGameRules` class:
122
+ - Spawn different entities
123
+ - Change movement speed
124
+ - Add collision detection
125
+ - Implement game logic
126
+
127
+ ### Add More Commands
128
+
129
+ In `server.ts`, add new socket event handlers:
130
+ ```typescript
131
+ socket.on('C_CUSTOM', (data) => {
132
+ room.queueInput(playerId, {
133
+ seq: data.seq,
134
+ type: 'custom',
135
+ // ...custom data
136
+ timestamp: Date.now(),
137
+ });
138
+ });
139
+ ```
140
+
141
+ Then handle it in `onCommand()`.
142
+
143
+ ## Troubleshooting
144
+
145
+ ### "Cannot find module './dist/index.js'"
146
+
147
+ You need to build the package first:
148
+ ```bash
149
+ pnpm build
150
+ ```
151
+
152
+ ### "Port 3000 already in use"
153
+
154
+ Change the port:
155
+ ```bash
156
+ PORT=4000 node examples/simple-game/server.js
157
+ ```
158
+
159
+ ### Client can't connect
160
+
161
+ Make sure:
162
+ 1. Server is running
163
+ 2. Port matches (default 3000)
164
+ 3. No firewall blocking
165
+
166
+ ## Next Steps
167
+
168
+ After manual testing works, you can:
169
+
170
+ 1. **Build a real game** - Use this as a template
171
+ 2. **Add collision detection** - Use `AABBCollision` from game-core
172
+ 3. **Implement game mechanics** - Shooting, collecting, scoring, etc.
173
+ 4. **Build a client UI** - Web-based game client with Phaser/Three.js
174
+ 5. **Deploy** - Add Docker, environment configs, monitoring
175
+
176
+ See the **Developer Guide** for more advanced usage!
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Manual Testing Client
3
+ *
4
+ * A simple client for testing the game server.
5
+ * Connects to the server and simulates player movement.
6
+ */
7
+
8
+ import { io, Socket } from 'socket.io-client';
9
+
10
+ const SERVER_URL = process.env.SERVER_URL || 'http://localhost:3000';
11
+
12
+ let socket: Socket;
13
+ let seq = 0;
14
+ let playerId: string | null = null;
15
+ let entities: Map<string, any> = new Map();
16
+
17
+ // ============================================================================
18
+ // Connection
19
+ // ============================================================================
20
+
21
+ console.log('Connecting to server:', SERVER_URL);
22
+
23
+ socket = io(SERVER_URL, {
24
+ transports: ['websocket'],
25
+ });
26
+
27
+ socket.on('connect', () => {
28
+ console.log('Connected! Socket ID:', socket.id);
29
+ console.log('');
30
+ });
31
+
32
+ socket.on('disconnect', () => {
33
+ console.log('Disconnected from server');
34
+ });
35
+
36
+ socket.on('connect_error', (error) => {
37
+ console.error('Connection error:', error.message);
38
+ process.exit(1);
39
+ });
40
+
41
+ // ============================================================================
42
+ // Server Events
43
+ // ============================================================================
44
+
45
+ socket.on('S_INIT', (data) => {
46
+ playerId = data.playerId;
47
+ console.log('Initialized! Player ID:', playerId);
48
+ console.log('Initial entities:', data.entities.length);
49
+
50
+ // Store initial entities
51
+ data.entities.forEach((entity: any) => {
52
+ entities.set(entity.id, entity);
53
+ if (entity.id === playerId) {
54
+ console.log(` You are at (${entity.x.toFixed(0)}, ${entity.y.toFixed(0)})`);
55
+ }
56
+ });
57
+
58
+ console.log('');
59
+ console.log('Starting movement test...');
60
+ console.log('');
61
+
62
+ // Start automated movement test
63
+ setTimeout(() => startMovementTest(), 1000);
64
+ });
65
+
66
+ socket.on('S_UPDATE', (data) => {
67
+ // Update entities
68
+ data.entities?.forEach((entity: any) => {
69
+ entities.set(entity.id, entity);
70
+ });
71
+
72
+ // Remove deleted entities
73
+ data.deleted?.forEach((id: string) => {
74
+ entities.delete(id);
75
+ });
76
+
77
+ // Log player position every few updates
78
+ if (seq % 20 === 0 && playerId) {
79
+ const player = entities.get(playerId);
80
+ if (player) {
81
+ console.log(`Position: (${player.x.toFixed(0)}, ${player.y.toFixed(0)}) | ` +
82
+ `Velocity: (${player.vx.toFixed(0)}, ${player.vy.toFixed(0)}) | ` +
83
+ `Total entities: ${entities.size}`);
84
+ }
85
+ }
86
+ });
87
+
88
+ socket.on('PLAYER_JOINED', (data) => {
89
+ console.log(`Player ${data.playerId} joined at (${data.x.toFixed(0)}, ${data.y.toFixed(0)})`);
90
+ });
91
+
92
+ socket.on('PLAYER_LEFT', (data) => {
93
+ console.log(`Player ${data.playerId} left`);
94
+ entities.delete(data.playerId);
95
+ });
96
+
97
+ socket.on('PLAYER_ACTION', (data) => {
98
+ console.log(`Player ${data.playerId} performed action: ${data.action}`);
99
+ });
100
+
101
+ // ============================================================================
102
+ // Input Commands
103
+ // ============================================================================
104
+
105
+ function move(dirX: number, dirY: number) {
106
+ socket.emit('C_MOVE', {
107
+ seq: ++seq,
108
+ dir: { x: dirX, y: dirY },
109
+ timestamp: Date.now(),
110
+ });
111
+ }
112
+
113
+ function stop() {
114
+ socket.emit('C_STOP', {
115
+ seq: ++seq,
116
+ timestamp: Date.now(),
117
+ });
118
+ }
119
+
120
+ function action(actionName: string, data?: any) {
121
+ socket.emit('C_ACTION', {
122
+ seq: ++seq,
123
+ action: actionName,
124
+ data,
125
+ timestamp: Date.now(),
126
+ });
127
+ }
128
+
129
+ // ============================================================================
130
+ // Automated Movement Test
131
+ // ============================================================================
132
+
133
+ let testPhase = 0;
134
+
135
+ function startMovementTest() {
136
+ setInterval(() => {
137
+ testPhase++;
138
+
139
+ switch (testPhase % 8) {
140
+ case 0:
141
+ console.log('Moving right');
142
+ move(1, 0);
143
+ break;
144
+ case 1:
145
+ console.log('Moving down');
146
+ move(0, 1);
147
+ break;
148
+ case 2:
149
+ console.log('Moving left');
150
+ move(-1, 0);
151
+ break;
152
+ case 3:
153
+ console.log('Moving up');
154
+ move(0, -1);
155
+ break;
156
+ case 4:
157
+ console.log('Moving diagonal');
158
+ move(1, -1);
159
+ break;
160
+ case 5:
161
+ console.log('Stopping');
162
+ stop();
163
+ break;
164
+ case 6:
165
+ console.log('Performing action');
166
+ action('jump', { height: 100 });
167
+ break;
168
+ case 7:
169
+ console.log('Circling...');
170
+ move(0.707, 0.707);
171
+ break;
172
+ }
173
+ }, 3000); // Change direction every 3 seconds
174
+ }
175
+
176
+ // ============================================================================
177
+ // CLI Info
178
+ // ============================================================================
179
+
180
+ console.log('');
181
+ console.log('═══════════════════════════════════════════════════════════');
182
+ console.log(' Game Core - Manual Test Client');
183
+ console.log('═══════════════════════════════════════════════════════════');
184
+ console.log('');
185
+ console.log(' This client will:');
186
+ console.log(' 1. Connect to the game server');
187
+ console.log(' 2. Receive initial game state');
188
+ console.log(' 3. Automatically move around to test the engine');
189
+ console.log('');
190
+ console.log(' Watch the server logs to see the tick processing!');
191
+ console.log('');
192
+ console.log('═══════════════════════════════════════════════════════════');
193
+ console.log('');
194
+
195
+ // Graceful shutdown
196
+ process.on('SIGINT', () => {
197
+ console.log('');
198
+ console.log('Disconnecting...');
199
+ socket.disconnect();
200
+ process.exit(0);
201
+ });
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "game-core-manual-test",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "description": "Manual testing example for @gamerstake/game-core",
7
+ "scripts": {
8
+ "server": "node server.js",
9
+ "client": "node client.js",
10
+ "test": "npm run server & sleep 2 && npm run client"
11
+ },
12
+ "keywords": ["game-core", "testing", "example"],
13
+ "author": "GamerStake"
14
+ }