onilib
Version:
A modular Node.js library for real-time online integration in games and web applications
336 lines (281 loc) โข 9.18 kB
JavaScript
// Exemplo bรกsico de uso da ONILib
const { NodeOnlineIntegration } = require('../src/index.js');
// Configuration for the example server
const config = {
name: 'basic-game-server',
environment: 'development',
// Server ports
port: 3000,
host: '0.0.0.0',
// Authentication
auth: {
jwtSecret: 'example-secret-key',
jwtExpiresIn: '24h',
apiKeys: ['demo_api_key_123']
},
// WebSocket/Realtime
realtime: {
port: 8080,
maxConnections: 100,
heartbeatInterval: 30000,
authRequired: true
},
// Storage (using SQLite for this example)
storage: {
type: 'sqlite',
path: './data/example.db'
},
// Matchmaking
matchmaking: {
maxPlayersPerMatch: 2,
matchTimeout: 30000,
queueTimeout: 300000,
enableSkillMatching: true
},
// P2P/WebRTC
p2p: {
enableRelay: false,
maxPeersPerRoom: 4,
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' }
]
},
// Admin panel
admin: {
port: 3001,
authRequired: true,
enableCors: true
}
};
async function startServer() {
console.log('๐ Iniciando servidor ONILib...');
// Create NOI instance
const noi = new NodeOnlineIntegration(config);
try {
// Start the server
await noi.start();
// Get module references
const realtime = noi.getModule('realtime');
const matchmaking = noi.getModule('matchmaking');
const storage = noi.getModule('storage');
const p2p = noi.getModule('p2p');
const auth = noi.getModule('auth');
console.log('โ
Servidor ONILib iniciado com sucesso!');
console.log(`๐ก WebSocket server: ws://localhost:${config.realtime.port}`);
console.log(`๐ Admin panel: http://localhost:${config.admin.port}`);
console.log(`๐ Demo API Key: ${config.auth.apiKeys[0]}`);
// Setup custom message handlers
setupMessageHandlers(realtime, matchmaking, storage, p2p);
// Setup matchmaking events
setupMatchmakingEvents(matchmaking, realtime, storage);
// Setup P2P events
setupP2PEvents(p2p, realtime);
// Create some demo data
await createDemoData(storage, auth);
console.log('\n๐ Available features:');
console.log(' โข Authentication (JWT & API Key)');
console.log(' โข Real-time messaging with rooms');
console.log(' โข Matchmaking with skill-based matching');
console.log(' โข P2P WebRTC signaling');
console.log(' โข Persistent storage (SQLite)');
console.log(' โข Admin REST API');
console.log('\n๐ฎ Try the example client:');
console.log(' Open examples/client.html in your browser');
} catch (error) {
console.error('โ Erro ao iniciar servidor ONILib:', error);
process.exit(1);
}
}
function setupMessageHandlers(realtime, matchmaking, storage, p2p) {
// Custom game message handler
realtime.registerHandler('game_action', async (client, message) => {
console.log(`๐ฎ Game action from ${client.id}:`, message.data);
// Store the action in database
await storage.set(`action:${client.id}:${Date.now()}`, {
playerId: client.id,
action: message.data.action,
timestamp: Date.now(),
roomId: client.currentRoom
});
// Broadcast to room members
if (client.currentRoom) {
realtime.broadcastToRoom(client.currentRoom, {
type: 'game_action_broadcast',
data: {
playerId: client.id,
action: message.data.action,
timestamp: Date.now()
}
}, client.id); // Exclude sender
}
});
// Player status update
realtime.registerHandler('player_status', async (client, message) => {
const status = message.data.status;
// Update player status in storage
await storage.set(`player:${client.id}:status`, {
status,
lastUpdate: Date.now()
});
// Notify room members
if (client.currentRoom) {
realtime.broadcastToRoom(client.currentRoom, {
type: 'player_status_update',
data: {
playerId: client.id,
status,
timestamp: Date.now()
}
}, client.id);
}
console.log(`๐ค Player ${client.id} status: ${status}`);
});
// Chat message handler
realtime.registerHandler('chat_message', async (client, message) => {
const chatMessage = {
id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
playerId: client.id,
text: message.data.text,
timestamp: Date.now(),
roomId: client.currentRoom
};
// Store chat message
await storage.set(`chat:${chatMessage.id}`, chatMessage);
// Broadcast to room
if (client.currentRoom) {
realtime.broadcastToRoom(client.currentRoom, {
type: 'chat_message_broadcast',
data: chatMessage
});
}
console.log(`๐ฌ Chat from ${client.id}: ${message.data.text}`);
});
}
function setupMatchmakingEvents(matchmaking, realtime, storage) {
// When a match is created
matchmaking.on('match:created', async (match) => {
console.log(`๐ฏ Match created: ${match.id} with ${match.players.length} players`);
// Store match data
await storage.set(`match:${match.id}`, {
id: match.id,
players: match.players.map(p => ({ id: p.id, skill: p.skill })),
status: 'created',
createdAt: Date.now()
});
});
// When a match starts
matchmaking.on('match:started', async (match) => {
console.log(`๐ Match started: ${match.id}`);
// Update match status
const matchData = await storage.get(`match:${match.id}`);
if (matchData) {
matchData.status = 'started';
matchData.startedAt = Date.now();
await storage.set(`match:${match.id}`, matchData);
}
// Create a dedicated room for the match
const roomId = `match_${match.id}`;
// Send game start notification to all players
for (const player of match.players) {
realtime.sendToClient(player.client, {
type: 'match_started',
data: {
matchId: match.id,
roomId,
players: match.players.map(p => ({ id: p.id, skill: p.skill })),
gameMode: 'default'
}
});
// Auto-join players to match room
realtime.joinRoom(player.client, roomId);
}
});
// When a match ends
matchmaking.on('match:ended', async (match) => {
console.log(`๐ Match ended: ${match.id}`);
// Update match status
const matchData = await storage.get(`match:${match.id}`);
if (matchData) {
matchData.status = 'ended';
matchData.endedAt = Date.now();
await storage.set(`match:${match.id}`, matchData);
}
});
}
function setupP2PEvents(p2p, realtime) {
// When a peer joins a P2P room
p2p.on('peer:joined_room', ({ peer, roomId }) => {
console.log(`๐ Peer ${peer.id} joined P2P room: ${roomId}`);
// Notify other peers in the room
const room = p2p.rooms.get(roomId);
if (room) {
for (const otherPeer of room.peers.values()) {
if (otherPeer.id !== peer.id) {
realtime.sendToClient(otherPeer.client, {
type: 'p2p_peer_joined',
data: {
peerId: peer.id,
roomId
}
});
}
}
}
});
// When a peer leaves a P2P room
p2p.on('peer:left_room', ({ peer, roomId }) => {
console.log(`๐ช Peer ${peer.id} left P2P room: ${roomId}`);
// Notify remaining peers
const room = p2p.rooms.get(roomId);
if (room) {
for (const otherPeer of room.peers.values()) {
realtime.sendToClient(otherPeer.client, {
type: 'p2p_peer_left',
data: {
peerId: peer.id,
roomId
}
});
}
}
});
}
async function createDemoData(storage, auth) {
console.log('๐ Creating demo data...');
// Create demo users
const demoUsers = [
{ id: 'user1', username: 'Alice', skill: 1200 },
{ id: 'user2', username: 'Bob', skill: 1150 },
{ id: 'user3', username: 'Charlie', skill: 1300 }
];
for (const user of demoUsers) {
await storage.set(`user:${user.id}`, user);
// Create JWT token for demo user
const token = auth.generateJWT({ userId: user.id, username: user.username });
console.log(`๐ Demo JWT for ${user.username}: ${token}`);
}
// Create demo game rooms
const demoRooms = [
{ id: 'lobby', name: 'Main Lobby', maxPlayers: 50 },
{ id: 'casual', name: 'Casual Games', maxPlayers: 10 },
{ id: 'ranked', name: 'Ranked Matches', maxPlayers: 8 }
];
for (const room of demoRooms) {
await storage.set(`room:${room.id}`, room);
}
console.log('โ
Demo data created');
}
// Graceful shutdown
process.on('SIGINT', async () => {
console.log('\n๐ Shutting down server...');
process.exit(0);
});
process.on('SIGTERM', async () => {
console.log('\n๐ Shutting down server...');
process.exit(0);
});
// Start the server
if (require.main === module) {
startServer().catch(console.error);
}
module.exports = { startServer, config };