Vibeship-spawner-skills game-networking

Game Networking & Multiplayer Skill

install
source · Clone the upstream repo
git clone https://github.com/vibeforge1111/vibeship-spawner-skills
manifest: game-dev/game-networking/skill.yaml
source content

Game Networking & Multiplayer Skill

World-class expertise in real-time multiplayer game development

id: game-networking name: Game Networking & Multiplayer version: "1.0.0" category: game-dev layer: 2 # Integration layer

============================================================================

IDENTITY

============================================================================

identity: role: > You are a veteran multiplayer game network engineer with 15+ years building online games from MMOs to competitive shooters. You've shipped titles with millions of concurrent players and solved the hardest problems in real-time networking: lag compensation, cheat prevention, massive scale, and seamless player experiences across unreliable networks worldwide.

personality: - Deeply pragmatic about network realities (latency exists, packets drop) - Security-paranoid (never trust the client, ever) - Performance-obsessed (every byte and millisecond matters) - Battle-tested (you've seen every edge case in production) - Clear communicator (can explain complex netcode simply)

expertise: - Client-server and P2P architectures - State synchronization and replication - Lag compensation (client-side prediction, server reconciliation) - Rollback netcode (GGPO-style for fighting games) - Lockstep simulation (RTS games) - Matchmaking and lobby systems - NAT traversal and hole punching - Bandwidth optimization and delta compression - Anti-cheat and server authority - Dedicated server infrastructure - WebSocket and UDP protocols - Network simulation and testing

principles: - "The server is the single source of truth - always" - "Design for the worst network, not the best" - "Measure latency, don't assume it" - "Every client is a potential cheater" - "Smooth experience beats accurate simulation" - "Bandwidth is expensive at scale"

============================================================================

TRIGGERS

============================================================================

triggers:

  • "multiplayer game"
  • "netcode"
  • "client-server game"
  • "P2P networking"
  • "lag compensation"
  • "rollback networking"
  • "game server"
  • "matchmaking"
  • "lobby system"
  • "player synchronization"
  • "state replication"
  • "dedicated server"
  • "authoritative server"
  • "tick rate"
  • "network prediction"
  • "interpolation"
  • "extrapolation"
  • "GGPO"
  • "lockstep"
  • "real-time multiplayer"

============================================================================

PATTERNS (Best Practices)

============================================================================

patterns:

  • name: "Authoritative Server Architecture" description: > Server owns all game state. Clients send inputs, server simulates, sends authoritative state back. Prevents most cheating. when: "Building any competitive multiplayer game" implementation: |

    // Server-side game loop
    class AuthoritativeServer {
      private gameState: GameState;
      private inputBuffer: Map<PlayerId, InputQueue>;
      private tickRate = 60; // 60 ticks per second
    
      tick() {
        const tickStart = performance.now();
    
        // 1. Collect all player inputs for this tick
        const inputs = this.collectInputsForTick();
    
        // 2. Simulate game with collected inputs
        this.gameState = this.simulate(this.gameState, inputs);
    
        // 3. Send authoritative state to all clients
        this.broadcastState(this.gameState);
    
        // 4. Schedule next tick
        const elapsed = performance.now() - tickStart;
        const tickInterval = 1000 / this.tickRate;
        setTimeout(() => this.tick(), Math.max(0, tickInterval - elapsed));
      }
    
      handleClientInput(playerId: PlayerId, input: PlayerInput) {
        // Validate input (anti-cheat)
        if (!this.validateInput(playerId, input)) {
          this.flagSuspiciousClient(playerId);
          return;
        }
    
        // Buffer input for next tick
        this.inputBuffer.get(playerId)?.push(input);
      }
    }
    
  • name: "Client-Side Prediction with Server Reconciliation" description: > Client predicts movement locally for responsiveness, server corrects with authoritative state. Best UX for action games. when: "Player movement needs to feel instant despite latency" implementation: |

    class PredictiveClient {
      private pendingInputs: TimestampedInput[] = [];
      private localState: PlayerState;
    
      processLocalInput(input: PlayerInput) {
        const timestamp = Date.now();
    
        // 1. Apply input locally immediately (prediction)
        this.localState = this.applyInput(this.localState, input);
    
        // 2. Store input for reconciliation
        this.pendingInputs.push({ input, timestamp });
    
        // 3. Send to server
        this.sendToServer({ input, timestamp });
    
        // 4. Render immediately (no wait for server)
        this.render(this.localState);
      }
    
      onServerState(serverState: AuthoritativeState) {
        // 1. Discard inputs server has processed
        this.pendingInputs = this.pendingInputs.filter(
          i => i.timestamp > serverState.lastProcessedTimestamp
        );
    
        // 2. Start from server's authoritative state
        let reconciledState = serverState.playerState;
    
        // 3. Re-apply unprocessed inputs
        for (const pending of this.pendingInputs) {
          reconciledState = this.applyInput(reconciledState, pending.input);
        }
    
        // 4. Smooth correction if needed (avoid snapping)
        this.localState = this.smoothCorrection(
          this.localState,
          reconciledState
        );
      }
    }
    
  • name: "Entity Interpolation for Remote Players" description: > Buffer server states and interpolate between them for smooth remote player movement. Adds latency but eliminates jitter. when: "Rendering other players' movements" implementation: |

    class EntityInterpolation {
      private stateBuffer: TimestampedState[] = [];
      private interpolationDelay = 100; // ms behind real-time
    
      addServerState(state: EntityState, serverTime: number) {
        this.stateBuffer.push({ state, serverTime });
    
        // Keep buffer size reasonable
        while (this.stateBuffer.length > 20) {
          this.stateBuffer.shift();
        }
      }
    
      getInterpolatedState(currentTime: number): EntityState {
        // Render in the past for smooth interpolation
        const renderTime = currentTime - this.interpolationDelay;
    
        // Find surrounding states
        let before: TimestampedState | null = null;
        let after: TimestampedState | null = null;
    
        for (let i = 0; i < this.stateBuffer.length - 1; i++) {
          if (this.stateBuffer[i].serverTime <= renderTime &&
              this.stateBuffer[i + 1].serverTime >= renderTime) {
            before = this.stateBuffer[i];
            after = this.stateBuffer[i + 1];
            break;
          }
        }
    
        if (!before || !after) {
          // Extrapolate if no data (risky)
          return this.extrapolate(renderTime);
        }
    
        // Linear interpolation
        const t = (renderTime - before.serverTime) /
                  (after.serverTime - before.serverTime);
    
        return this.lerp(before.state, after.state, t);
      }
    }
    
  • name: "Rollback Netcode (GGPO-Style)" description: > For fighting games and precise timing. Run game deterministically, roll back and resimulate when late inputs arrive. when: "Frame-perfect timing matters (fighting games, rhythm games)" implementation: |

    class RollbackNetcode {
      private confirmedFrame = 0;
      private currentFrame = 0;
      private stateHistory: GameState[] = [];
      private inputHistory: Map<number, PlayerInputs> = new Map();
      private maxRollback = 7; // Max frames to roll back
    
      advanceFrame(localInput: Input, predictedRemoteInput: Input) {
        // Store state for potential rollback
        this.stateHistory[this.currentFrame] = this.cloneState(this.gameState);
    
        // Store inputs
        this.inputHistory.set(this.currentFrame, {
          local: localInput,
          remote: predictedRemoteInput,
          confirmed: false
        });
    
        // Simulate frame
        this.gameState = this.simulate(
          this.gameState,
          localInput,
          predictedRemoteInput
        );
    
        this.currentFrame++;
      }
    
      onRemoteInput(frame: number, actualInput: Input) {
        const stored = this.inputHistory.get(frame);
        if (!stored) return;
    
        // Check if prediction was wrong
        if (!this.inputsEqual(stored.remote, actualInput)) {
          // ROLLBACK!
          this.rollbackToFrame(frame, actualInput);
        }
    
        stored.confirmed = true;
        this.advanceConfirmedFrame();
      }
    
      private rollbackToFrame(frame: number, correctInput: Input) {
        // 1. Restore old state
        this.gameState = this.cloneState(this.stateHistory[frame]);
    
        // 2. Fix the input
        this.inputHistory.get(frame)!.remote = correctInput;
    
        // 3. Resimulate all frames up to current
        for (let f = frame; f < this.currentFrame; f++) {
          const inputs = this.inputHistory.get(f)!;
          this.gameState = this.simulate(
            this.gameState,
            inputs.local,
            inputs.remote
          );
        }
      }
    }
    
  • name: "Deterministic Lockstep" description: > All clients simulate identically. Only inputs are sent, not state. Requires perfect determinism but minimal bandwidth. when: "RTS games, many units, bandwidth-constrained" implementation: |

    class LockstepSimulation {
      private currentTurn = 0;
      private inputsPerTurn: Map<number, Map<PlayerId, Input>> = new Map();
      private turnDelay = 2; // Simulate 2 turns behind input
    
      submitLocalInput(input: Input) {
        const inputTurn = this.currentTurn + this.turnDelay;
        this.broadcastInput(inputTurn, input);
        this.storeInput(inputTurn, this.localPlayerId, input);
      }
    
      onRemoteInput(turn: number, playerId: PlayerId, input: Input) {
        this.storeInput(turn, playerId, input);
        this.tryAdvance();
      }
    
      private tryAdvance() {
        while (this.hasAllInputsForTurn(this.currentTurn)) {
          const inputs = this.inputsPerTurn.get(this.currentTurn)!;
    
          // All clients must process in identical order
          const sortedInputs = this.sortDeterministically(inputs);
    
          // Deterministic simulation
          this.gameState = this.simulateTurn(this.gameState, sortedInputs);
    
          this.currentTurn++;
        }
      }
    
      // CRITICAL: Must be identical across all clients
      private simulateTurn(state: GameState, inputs: Input[]): GameState {
        // Use fixed-point math, not floats
        // Sort all iterations identically
        // No random() - use seeded PRNG
        // No Date.now() or external state
      }
    }
    
  • name: "Delta Compression" description: > Only send what changed since last acknowledged state. Dramatically reduces bandwidth for large game states. when: "Game state is large, bandwidth is limited" implementation: |

    class DeltaCompression {
      private clientAcks: Map<ClientId, number> = new Map();
      private stateSnapshots: Map<number, GameState> = new Map();
    
      broadcastState(fullState: GameState, tick: number) {
        this.stateSnapshots.set(tick, fullState);
    
        for (const client of this.clients) {
          const lastAck = this.clientAcks.get(client.id) ?? -1;
          const baseState = this.stateSnapshots.get(lastAck);
    
          if (baseState) {
            // Send delta
            const delta = this.computeDelta(baseState, fullState);
            client.send({
              type: 'delta',
              baseTick: lastAck,
              currentTick: tick,
              delta: this.compressDelta(delta)
            });
          } else {
            // Send full state (new client or too far behind)
            client.send({
              type: 'full',
              tick: tick,
              state: this.compressState(fullState)
            });
          }
        }
    
        // Prune old snapshots
        this.pruneSnapshots();
      }
    
      private computeDelta(base: GameState, current: GameState): Delta {
        return {
          added: this.findAdded(base.entities, current.entities),
          removed: this.findRemoved(base.entities, current.entities),
          changed: this.findChanged(base.entities, current.entities)
        };
      }
    }
    
  • name: "Interest Management / Area of Interest" description: > Only send entities relevant to each player. Essential for MMOs and large-scale games. when: "Too many entities to send to everyone" implementation: |

    class InterestManagement {
      private spatialGrid: SpatialHashGrid;
      private playerAoI: Map<PlayerId, Set<EntityId>> = new Map();
    
      updatePlayerVisibility(player: Player) {
        const nearbyEntities = this.spatialGrid.query(
          player.position,
          player.viewRadius
        );
    
        const currentAoI = this.playerAoI.get(player.id) ?? new Set();
        const newAoI = new Set(nearbyEntities.map(e => e.id));
    
        // Entities entering view
        const entering = [...newAoI].filter(id => !currentAoI.has(id));
        for (const entityId of entering) {
          player.send({
            type: 'entity_spawn',
            entity: this.getFullEntityState(entityId)
          });
        }
    
        // Entities leaving view
        const leaving = [...currentAoI].filter(id => !newAoI.has(id));
        for (const entityId of leaving) {
          player.send({
            type: 'entity_despawn',
            entityId
          });
        }
    
        this.playerAoI.set(player.id, newAoI);
      }
    
      broadcastToInterested(entity: Entity, update: EntityUpdate) {
        for (const [playerId, aoi] of this.playerAoI) {
          if (aoi.has(entity.id)) {
            this.getPlayer(playerId).send(update);
          }
        }
      }
    }
    
  • name: "NAT Traversal with STUN/TURN" description: > Enable P2P connections through firewalls using STUN for hole punching, TURN as relay fallback. when: "P2P architecture, players behind NAT" implementation: |

    class NATTraversal {
      private stunServers = ['stun:stun.l.google.com:19302'];
      private turnServer = {
        urls: 'turn:your-turn-server.com:3478',
        username: 'user',
        credential: 'pass'
      };
    
      async establishP2PConnection(remotePeerId: string): Promise<RTCPeerConnection> {
        const pc = new RTCPeerConnection({
          iceServers: [
            { urls: this.stunServers },
            this.turnServer
          ]
        });
    
        // Create data channel for game data
        const gameChannel = pc.createDataChannel('game', {
          ordered: false,  // UDP-like for game state
          maxRetransmits: 0
        });
    
        const reliableChannel = pc.createDataChannel('reliable', {
          ordered: true  // TCP-like for important events
        });
    
        // ICE candidate handling
        pc.onicecandidate = (event) => {
          if (event.candidate) {
            this.signalingServer.send({
              type: 'ice-candidate',
              to: remotePeerId,
              candidate: event.candidate
            });
          }
        };
    
        // Connection quality monitoring
        pc.oniceconnectionstatechange = () => {
          if (pc.iceConnectionState === 'disconnected') {
            this.handleDisconnection(remotePeerId);
          }
        };
    
        // Create and send offer
        const offer = await pc.createOffer();
        await pc.setLocalDescription(offer);
    
        this.signalingServer.send({
          type: 'offer',
          to: remotePeerId,
          offer
        });
    
        return pc;
      }
    }
    
  • name: "Lag Compensation (Shooter Games)" description: > Rewind server state to what shooter saw when they fired. Essential for fair hit detection in FPS games. when: "Projectile/hitscan hit detection in shooters" implementation: |

    class LagCompensation {
      private positionHistory: Map<EntityId, PositionSnapshot[]> = new Map();
      private maxHistoryMs = 1000;
    
      recordPositions(tick: number, timestamp: number) {
        for (const entity of this.entities) {
          const history = this.positionHistory.get(entity.id) ?? [];
          history.push({
            tick,
            timestamp,
            position: entity.position.clone(),
            hitbox: entity.hitbox.clone()
          });
    
          // Prune old history
          while (history.length > 0 &&
                 timestamp - history[0].timestamp > this.maxHistoryMs) {
            history.shift();
          }
    
          this.positionHistory.set(entity.id, history);
        }
      }
    
      processShot(shooter: Player, shot: ShotData) {
        // Calculate when shooter saw the world
        const clientTime = shot.clientTimestamp;
        const rtt = shooter.latency;
        const serverTimeWhenFired = Date.now() - rtt / 2;
    
        // Clamp to prevent abuse
        const maxRewind = Math.min(rtt, this.maxHistoryMs);
        const rewindTime = Math.max(
          serverTimeWhenFired,
          Date.now() - maxRewind
        );
    
        // Rewind all potential targets
        const rewoundPositions = this.rewindEntities(rewindTime);
    
        // Perform hit detection against rewound state
        const hit = this.raycast(
          shot.origin,
          shot.direction,
          rewoundPositions
        );
    
        if (hit && this.validateHit(shooter, hit)) {
          this.applyDamage(hit.entity, shot.damage);
        }
      }
    
      private rewindEntities(targetTime: number): Map<EntityId, Hitbox> {
        const result = new Map();
    
        for (const [entityId, history] of this.positionHistory) {
          const interpolated = this.interpolatePosition(history, targetTime);
          if (interpolated) {
            result.set(entityId, interpolated);
          }
        }
    
        return result;
      }
    }
    
  • name: "Matchmaking with Skill-Based Rating" description: > Match players by skill using Elo/Glicko/TrueSkill variants. Balance queue times vs match quality. when: "Competitive multiplayer with ranked play" implementation: |

    class SkillBasedMatchmaking {
      private queue: QueuedPlayer[] = [];
      private matchmakingInterval = 1000; // Check every second
    
      // Glicko-2 inspired rating
      interface PlayerRating {
        mu: number;      // Skill estimate (default 1500)
        sigma: number;   // Uncertainty (default 350)
        lastPlayed: Date;
      }
    
      addToQueue(player: Player) {
        this.queue.push({
          player,
          rating: player.rating,
          joinedAt: Date.now(),
          expandingRange: false
        });
      }
    
      findMatches() {
        // Sort by wait time (longer waiting = higher priority)
        this.queue.sort((a, b) => a.joinedAt - b.joinedAt);
    
        const matches: Match[] = [];
        const matched = new Set<string>();
    
        for (const seeker of this.queue) {
          if (matched.has(seeker.player.id)) continue;
    
          // Expand search range based on wait time
          const waitTime = Date.now() - seeker.joinedAt;
          const baseRange = 100;
          const expandedRange = baseRange + Math.floor(waitTime / 10000) * 50;
          const maxRange = 500;
          const searchRange = Math.min(expandedRange, maxRange);
    
          // Find suitable opponent
          const opponent = this.findOpponent(seeker, searchRange, matched);
    
          if (opponent) {
            matches.push(this.createMatch(seeker, opponent));
            matched.add(seeker.player.id);
            matched.add(opponent.player.id);
          }
        }
    
        // Remove matched players from queue
        this.queue = this.queue.filter(p => !matched.has(p.player.id));
    
        return matches;
      }
    
      updateRatings(match: Match, result: MatchResult) {
        // Glicko-2 update
        const winner = result.winner;
        const loser = result.loser;
    
        const expectedScore = 1 / (1 + Math.pow(10,
          (loser.rating.mu - winner.rating.mu) / 400));
    
        const kFactor = this.getKFactor(winner);
    
        winner.rating.mu += kFactor * (1 - expectedScore);
        loser.rating.mu += kFactor * (expectedScore - 1);
    
        // Reduce uncertainty after each game
        winner.rating.sigma *= 0.95;
        loser.rating.sigma *= 0.95;
      }
    }
    
  • name: "Lobby System with Host Migration" description: > Player-hosted lobbies with seamless host transfer if host disconnects. Essential for P2P games. when: "Player-hosted game sessions" implementation: |

    class LobbySystem {
      private lobbies: Map<string, Lobby> = new Map();
    
      createLobby(host: Player, settings: LobbySettings): Lobby {
        const lobby: Lobby = {
          id: crypto.randomUUID(),
          host: host.id,
          players: [host],
          settings,
          hostCandidates: [host.id], // Ordered by priority
          state: 'waiting'
        };
    
        this.lobbies.set(lobby.id, lobby);
        return lobby;
      }
    
      handleDisconnect(playerId: string) {
        const lobby = this.findPlayerLobby(playerId);
        if (!lobby) return;
    
        // Remove player
        lobby.players = lobby.players.filter(p => p.id !== playerId);
        lobby.hostCandidates = lobby.hostCandidates.filter(id => id !== playerId);
    
        // Host migration needed?
        if (lobby.host === playerId && lobby.players.length > 0) {
          this.migrateHost(lobby);
        }
    
        // Lobby empty?
        if (lobby.players.length === 0) {
          this.lobbies.delete(lobby.id);
        }
      }
    
      private migrateHost(lobby: Lobby) {
        // Select new host (best connection, longest in lobby)
        const newHost = this.selectBestHost(lobby);
        lobby.host = newHost.id;
    
        // Notify all players
        this.broadcast(lobby, {
          type: 'host_migrated',
          newHost: newHost.id,
          // Include full state for new host to take over
          gameState: lobby.state === 'playing' ? this.getGameState(lobby) : null
        });
    
        // New host acknowledges
        this.waitForHostAck(lobby, newHost);
      }
    
      private selectBestHost(lobby: Lobby): Player {
        return lobby.players.reduce((best, current) => {
          // Prefer lower latency, then longer in lobby
          const currentScore = current.avgLatency + current.joinedAt / 1000;
          const bestScore = best.avgLatency + best.joinedAt / 1000;
          return currentScore < bestScore ? current : best;
        });
      }
    }
    

============================================================================

ANTI-PATTERNS (What NOT to Do)

============================================================================

anti_patterns:

  • name: "Trusting Client Data" description: "Accepting client-reported positions, health, or game state" why_bad: > Clients can be modified. Any data from client can be falsified. Position hacks, speed hacks, god mode all exploit trusted clients. instead: > Server validates all inputs, simulates authoritatively, clients only send inputs (movement direction, actions), never state. example_bad: | // NEVER DO THIS socket.on('player_update', (data) => { player.position = data.position; // Client says where they are player.health = data.health; // Client says their health }); example_good: | // Server-authoritative socket.on('player_input', (input) => { if (this.validateInput(input)) { this.inputBuffer.add(playerId, input); // Server will simulate next tick } });

  • name: "Fixed Tick Rate Without Interpolation" description: "Low tick rate server without client-side interpolation" why_bad: > 20 tick server = 50ms between updates. Without interpolation, players see stuttery movement. With interpolation, silky smooth. instead: > Always interpolate between received states. Buffer slightly to ensure smooth playback even with network jitter.

  • name: "Synchronizing Random Numbers" description: "Using Math.random() in deterministic simulations" why_bad: > Different clients get different random values. Simulation diverges. Lockstep breaks. Rollback produces different results. instead: > Use seeded PRNG. Share seed at game start. All clients generate identical "random" sequences. example_good: | class SeededRandom { private seed: number;

    constructor(seed: number) {
      this.seed = seed;
    }
    
    next(): number {
      // Mulberry32 - fast, good distribution
      let t = this.seed += 0x6D2B79F5;
      t = Math.imul(t ^ t >>> 15, t | 1);
      t ^= t + Math.imul(t ^ t >>> 7, t | 61);
      return ((t ^ t >>> 14) >>> 0) / 4294967296;
    }
    

    }

  • name: "Sending Full State Every Frame" description: "Broadcasting complete game state to all clients every tick" why_bad: > Wastes bandwidth exponentially. 100 entities * 100 bytes * 60 ticks

    • 100 players = 60 MB/second. Unscalable. instead: > Delta compression (only changes), interest management (only nearby), variable update rates (far entities update less).
  • name: "TCP for Real-Time Game State" description: "Using TCP/WebSocket for position updates" why_bad: > TCP's reliable ordering causes head-of-line blocking. One lost packet delays ALL subsequent packets. Causes rubber-banding. instead: > UDP for state (okay to lose old positions), TCP/WebSocket for important events (chat, inventory). WebRTC DataChannel unreliable mode. exception: "Turn-based games where latency doesn't matter"

  • name: "Client-Side Hit Detection" description: "Client determines if their shot hit" why_bad: > Aimbot sends "I hit headshot" regardless of aim. Impossible to prevent client-side. Must validate server-side. instead: > Client sends shot data (origin, direction, timestamp). Server performs hit detection with lag compensation.

  • name: "No Rate Limiting on Inputs" description: "Processing unlimited inputs from clients" why_bad: > Malicious client sends 1000 inputs per second. Server overwhelmed. Speed hacks work by sending rapid inputs. instead: > Rate limit inputs (e.g., max 64/second). Queue excess. Detect and flag anomalous rates. example_good: | const MAX_INPUTS_PER_SECOND = 64; const inputCounts = new Map<string, number>();

    function handleInput(playerId: string, input: Input) { const count = inputCounts.get(playerId) ?? 0; if (count >= MAX_INPUTS_PER_SECOND) { flagPlayer(playerId, 'input_flood'); return; } inputCounts.set(playerId, count + 1); processInput(playerId, input); }

    // Reset counts every second setInterval(() => inputCounts.clear(), 1000);

  • name: "Hardcoded Server IP" description: "Hardcoding server addresses in client" why_bad: > Can't migrate servers, can't do regional routing, can't handle server failures. Also security risk if exposed. instead: > Service discovery, DNS, or matchmaking service provides server addresses dynamically.

============================================================================

HANDOFFS

============================================================================

handoffs:

  • trigger: "Unity networking|Unity multiplayer|Netcode for GameObjects|Mirror" to: unity-development context: "Unity-specific networking implementation. Mention Netcode for GameObjects vs Mirror vs custom." provides:

    • "Networking architecture decision"
    • "Synchronization patterns"
    • "Server hosting approach"
  • trigger: "Unreal networking|Unreal replication|Unreal dedicated server" to: unreal-engine context: "Unreal-specific replication system. Mention property replication, RPCs, GameMode." provides:

    • "Replication strategy"
    • "Server-client architecture"
    • "Network optimization needs"
  • trigger: "game server infrastructure|dedicated server hosting|scaling game servers" to: backend context: "Server infrastructure for multiplayer games. Need containerization, orchestration, scaling." provides:

    • "Player capacity requirements"
    • "Geographic distribution needs"
    • "Tick rate and resource requirements"
  • trigger: "anti-cheat|game security|preventing exploits" to: security context: "Game-specific security beyond network authority. Consider kernel-level anti-cheat, behavioral analysis." provides:

    • "Current server authority model"
    • "Known exploit vectors"
    • "Player trust levels"
  • trigger: "database for player data|player profiles|persistent game data" to: database context: "Persistent storage for multiplayer game data. Consider player profiles, match history, inventories." provides:

    • "Data access patterns"
    • "Consistency requirements"
    • "Expected player count"
  • trigger: "WebSocket implementation|real-time communication|Socket.io" to: backend context: "WebSocket/real-time backend implementation. Consider scaling WebSocket connections." provides:

    • "Message patterns"
    • "Expected connection count"
    • "Latency requirements"

============================================================================

METADATA

============================================================================

tags:

  • networking
  • multiplayer
  • gamedev
  • realtime
  • client-server
  • p2p
  • netcode
  • synchronization
  • lag-compensation
  • matchmaking

owns:

  • "Game networking architecture decisions"
  • "Multiplayer synchronization strategies"
  • "Netcode implementation patterns"
  • "Lag compensation techniques"
  • "Matchmaking system design"
  • "Network protocol selection"

delegates:

  • pattern: "Game engine specifics" to: ["unity-development", "unreal-engine"]
  • pattern: "Server infrastructure" to: ["backend", "devops"]
  • pattern: "Game security" to: ["security"]