The matchmaking and collaboration engine for PeerPigeon
npm install pigeonmatchThe matchmaking and collaboration engine for PeerPigeon - a versatile solution for building distributed peer-to-peer applications with intelligent matchmaking and state synchronization.
- 🎮 Flexible Matchmaking: Configure minimum and maximum peer counts (2 or more peers)
- 🌐 Network Namespace Support: Uses PeerPigeon's native namespace isolation for separate peer networks
- 🕸️ Mesh Peer Discovery: Automatically tracks both direct and indirect peers throughout the mesh via gossip protocol
- ⏱️ Vector Clock Arbitration: Resolve conflicts and handle latency issues in distributed systems
- 🔄 State Synchronization: Automatic state synchronization across peers
- ⚡ Vue/Vite Compatible: Built with Vue 3 and Vite support by default
- 🔌 Built on PeerPigeon: Leverages the powerful PeerPigeon WebRTC mesh networking library
``bash`
npm install pigeonmatch
`typescript
import { PeerPigeonMesh } from 'peerpigeon';
import { MatchmakingEngine, MatchmakingEvent } from 'pigeonmatch';
// Create PeerPigeon mesh instance
const mesh = new PeerPigeonMesh({
networkName: 'game-lobby',
enableWebDHT: true
});
await mesh.init();
await mesh.connect('ws://localhost:3000');
// Create a matchmaking engine with mesh integration
// Automatically tracks ALL peers (direct + indirect) in the mesh via gossip protocol
const matchmaker = new MatchmakingEngine({
minPeers: 2, // Minimum peers required for a match
maxPeers: 4, // Maximum peers in a match
namespace: 'game-lobby',
matchTimeout: 30000,
mesh: mesh // Enables automatic peer discovery
});
// Listen for match events
matchmaker.on(MatchmakingEvent.MATCH_FOUND, (match) => {
console.log('Match found!', match);
});
matchmaker.on(MatchmakingEvent.PEER_JOINED, (peer) => {
console.log('Peer joined:', peer);
});
// Peers are automatically discovered from the mesh!
// You can also manually add peers with custom metadata
matchmaker.addPeer({
id: 'peer-1',
metadata: { skill: 'advanced' }
});
`
`typescript
import { PeerPigeonMesh } from 'peerpigeon';
import { CollaborationEngine, CollaborationEvent, ConflictResolutionStrategy } from 'pigeonmatch';
// Create PeerPigeon mesh instance
const mesh = new PeerPigeonMesh({
networkName: 'document-collaboration',
enableWebDHT: true
});
await mesh.init();
await mesh.connect('ws://localhost:3000');
// Create a collaboration engine with mesh integration
// Automatically tracks ALL peers (direct + indirect) and handles message passing
const collaboration = new CollaborationEngine({
peerId: mesh.getStatus().peerId,
namespace: 'document-collaboration',
conflictResolution: ConflictResolutionStrategy.VECTOR_CLOCK,
syncInterval: 5000,
mesh: mesh // Enables automatic peer discovery and message passing
});
// Listen for state updates
collaboration.on(CollaborationEvent.STATE_UPDATED, (update) => {
console.log('State updated:', update);
});
// Listen for conflict resolution
collaboration.on(CollaborationEvent.CONFLICT_RESOLVED, (resolution) => {
console.log('Conflict resolved:', resolution);
});
// Update local state - automatically synced with all peers in the mesh
collaboration.updateState({
documentText: 'Hello, world!',
cursor: { line: 1, column: 0 }
});
// Handle messages from other peers
collaboration.handleMessage(message);
`
`typescript
import { VectorClock } from 'pigeonmatch';
// Create vector clocks for distributed time tracking
const clock1 = new VectorClock();
const clock2 = new VectorClock();
// Increment clocks
clock1.increment('peer-1');
clock2.increment('peer-2');
// Compare clocks
if (clock1.happensBefore(clock2)) {
console.log('Event 1 happened before event 2');
} else if (clock1.happensAfter(clock2)) {
console.log('Event 1 happened after event 2');
} else {
console.log('Events are concurrent');
}
// Merge clocks for synchronization
clock1.merge(clock2);
`
PigeonMatch leverages PeerPigeon's native network namespace support for isolating peer groups. Create separate PeerPigeon mesh instances with different networkName configurations:
`typescript
import { PeerPigeonMesh } from 'peerpigeon';
import { MatchmakingEngine } from 'pigeonmatch';
// Create isolated mesh networks using PeerPigeon's native namespace support
const gameMesh = new PeerPigeonMesh({ networkName: 'game-lobby' });
const chatMesh = new PeerPigeonMesh({ networkName: 'chat-room' });
await gameMesh.connect('ws://localhost:3000');
await chatMesh.connect('ws://localhost:3000');
// Create matchmaking engines for each namespace
const gameMatchmaker = new MatchmakingEngine({
minPeers: 2,
maxPeers: 4,
namespace: 'game-lobby' // Used for match identification
});
const chatMatchmaker = new MatchmakingEngine({
minPeers: 2,
maxPeers: 10,
namespace: 'chat-room'
});
// Peers in different PeerPigeon meshes won't see each other
`
PigeonMatch integrates deeply with PeerPigeon's mesh networking to automatically track all peers in the network, including:
- Direct Peers: Peers with direct WebRTC connections
- Indirect Peers: Peers discovered through PeerPigeon's gossip protocol
When you provide a mesh parameter to the engines:
1. Automatic Discovery: The engine listens to PeerPigeon's peerDiscovered events to track ALL peers in the mesh, not just those directly connected
2. Gossip Protocol: PeerPigeon's gossip protocol ensures peer information propagates throughout the entire mesh
3. Dynamic Updates: As peers join/leave the mesh, the engines automatically update their peer lists
4. Message Routing: Messages are automatically routed through the mesh, reaching indirect peers via relay
`typescript
// In a mesh with 10 peers where:
// - Peer A is directly connected to Peers B and C
// - Peer D is only connected to Peer C (indirect to Peer A)
const mesh = new PeerPigeonMesh({ networkName: 'game' });
await mesh.connect('ws://localhost:3000');
const matchmaker = new MatchmakingEngine({
minPeers: 4,
maxPeers: 8,
mesh: mesh // Enables mesh integration
});
// Peer A's matchmaker will automatically track:
// - Peer B (direct)
// - Peer C (direct)
// - Peer D (indirect via C)
// - All other discovered peers in the mesh
// When a match is created, it can include ANY combination of peers,
// whether directly or indirectly connected
`
- Scalability: Match across the entire mesh, not just direct connections
- Resilience: Peers can communicate even when not directly connected
- Simplicity: No manual peer tracking required
- Efficiency: Leverages PeerPigeon's optimized routing and gossip protocol
#### Constructor Options
`typescript`
interface MatchmakingConfig {
minPeers: number; // Minimum peers required
maxPeers: number; // Maximum peers allowed
matchTimeout?: number; // Timeout in milliseconds
namespace?: string; // Network namespace
matchCriteria?: object; // Custom matching criteria
mesh?: any; // PeerPigeonMesh instance for auto peer discovery
}
Note: When mesh is provided, peers are automatically discovered from the mesh. You can still manually add peers with custom metadata using addPeer().
#### Methods
- addPeer(peer: Peer): void - Add a peer to matchmakingremovePeer(peerId: string): boolean
- - Remove a peergetPeer(peerId: string): Peer | undefined
- - Get peer by IDgetAllPeers(): Peer[]
- - Get all peersgetAllMatches(): MatchGroup[]
- - Get all active matchesgetStats()
- - Get matchmaking statistics
#### Events
- peer:joined - A peer joined the matchmaking poolpeer:left
- - A peer left the matchmaking poolmatch:found
- - A match was foundmatch:ready
- - A match is ready to startmatch:failed
- - Matchmaking failedmatch:disbanded
- - A match was disbanded
#### Constructor Options
`typescript`
interface CollaborationConfig {
peerId: string; // Local peer ID
namespace?: string; // Network namespace
conflictResolution?: ConflictResolutionStrategy;
syncInterval?: number; // Sync interval in ms
mesh?: any; // PeerPigeonMesh instance for auto peer discovery and messaging
}
Note: When mesh is provided, peers are automatically discovered and messages are automatically sent through the mesh network.
#### Methods
- updateState(state: any): void - Update local stategetState(): any
- - Get current local stategetPeerState(peerId: string): any
- - Get peer's statehandleMessage(message: PeerMessage): void
- - Handle peer messageaddPeer(peer: Peer): void
- - Add a peerremovePeer(peerId: string): void
- - Remove a peergetVectorClock(): VectorClock
- - Get local vector clock
#### Events
- state:updated - State was updatedconflict:detected
- - A conflict was detectedconflict:resolved
- - A conflict was resolvedsync:requested
- - Sync was requestedsync:completed
- - Sync completed
#### Methods
- increment(peerId: string): void - Increment clock for peermerge(other: VectorClock): void
- - Merge with another clockcompare(other: VectorClock): number
- - Compare clocks (-1, 0, 1)happensBefore(other: VectorClock): boolean
- - Check orderinghappensAfter(other: VectorClock): boolean
- - Check orderingisConcurrent(other: VectorClock): boolean
- - Check concurrencyclone(): VectorClock
- - Clone the clocktoJSON(): object
- - Serialize to JSONfromJSON(obj: object): VectorClock
- - Deserialize from JSON
PigeonMatch is designed to work seamlessly with Vue 3 and Vite:
`typescript
// In your Vue component
import { ref, onMounted, onUnmounted } from 'vue';
import { MatchmakingEngine, MatchmakingEvent } from 'pigeonmatch';
export default {
setup() {
const matchmaker = ref
const peers = ref([]);
onMounted(() => {
matchmaker.value = new MatchmakingEngine({
minPeers: 2,
maxPeers: 4,
namespace: 'game'
});
matchmaker.value.on(MatchmakingEvent.PEER_JOINED, (peer) => {
peers.value.push(peer);
});
});
onUnmounted(() => {
matchmaker.value?.removeAllListeners();
});
return { peers };
}
};
``
- Multiplayer Games: Match players and synchronize game state
- Collaborative Editing: Real-time document collaboration with conflict resolution
- Video Chat Rooms: Manage peer connections in virtual rooms
- Distributed Computing: Coordinate work across multiple peers
- Decentralized Apps: Build dApps with peer-to-peer communication
PigeonMatch uses a combination of proven distributed systems concepts:
1. Vector Clocks: Track causality and detect concurrent events
2. PeerPigeon Network Namespaces: Leverage PeerPigeon's native namespace isolation for separate peer groups
3. Event-Driven Architecture: React to state changes and peer events
4. Conflict Resolution Strategies: Multiple strategies for handling conflicts
MIT
Contributions are welcome! Please open an issue or submit a pull request.
- PeerPigeon - WebRTC mesh networking library
- PigeonHub - Decentralized mesh network with signaling