sam-coder-cli 1.0.22 → 1.0.24
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.
- package/bin/multiplayer-client.js +97 -44
- package/package.json +1 -1
|
@@ -19,12 +19,33 @@ async function isPortInUse(port) {
|
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
async function findAvailablePort(startPort = 8080, maxAttempts = 10) {
|
|
23
|
+
let port = startPort;
|
|
24
|
+
let attempts = 0;
|
|
25
|
+
|
|
26
|
+
while (attempts < maxAttempts) {
|
|
27
|
+
const inUse = await isPortInUse(port);
|
|
28
|
+
if (!inUse) {
|
|
29
|
+
return port;
|
|
30
|
+
}
|
|
31
|
+
port++;
|
|
32
|
+
attempts++;
|
|
33
|
+
}
|
|
34
|
+
throw new Error(`Could not find an available port after ${maxAttempts} attempts`);
|
|
35
|
+
}
|
|
36
|
+
|
|
22
37
|
async function ensureServerRunning(port = 8080) {
|
|
23
|
-
|
|
24
|
-
|
|
38
|
+
try {
|
|
39
|
+
const availablePort = await findAvailablePort(port);
|
|
40
|
+
const isDefaultPort = (availablePort === port);
|
|
41
|
+
|
|
42
|
+
if (!isDefaultPort) {
|
|
43
|
+
console.log(chalk.yellow(`Port ${port} is in use, trying port ${availablePort}...`));
|
|
44
|
+
}
|
|
45
|
+
|
|
25
46
|
console.log('Starting local multiplayer server...');
|
|
26
47
|
// Start server in a detached process
|
|
27
|
-
const serverProcess = spawn('node', [__filename, '--server', '--port',
|
|
48
|
+
const serverProcess = spawn('node', [__filename, '--server', '--port', availablePort.toString()], {
|
|
28
49
|
detached: true,
|
|
29
50
|
stdio: 'ignore',
|
|
30
51
|
windowsHide: true
|
|
@@ -34,9 +55,12 @@ async function ensureServerRunning(port = 8080) {
|
|
|
34
55
|
|
|
35
56
|
// Wait for server to start
|
|
36
57
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
37
|
-
console.log(
|
|
58
|
+
console.log(chalk.green(`Local multiplayer server started on port ${availablePort}`));
|
|
59
|
+
return `ws://localhost:${availablePort}`;
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error(chalk.red('Failed to start multiplayer server:'), error.message);
|
|
62
|
+
throw error;
|
|
38
63
|
}
|
|
39
|
-
return `ws://localhost:${port}`;
|
|
40
64
|
}
|
|
41
65
|
|
|
42
66
|
class MultiplayerServer {
|
|
@@ -248,49 +272,78 @@ class MultiplayerClient extends EventEmitter {
|
|
|
248
272
|
}
|
|
249
273
|
|
|
250
274
|
async connect() {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
this.serverUrl = await ensureServerRunning(this.port);
|
|
254
|
-
|
|
255
|
-
this.ws = new WebSocket(this.serverUrl);
|
|
256
|
-
|
|
257
|
-
this.ws.on('open', () => {
|
|
258
|
-
this.connected = true;
|
|
259
|
-
this.emit('connected');
|
|
260
|
-
console.log(chalk.green('✅ Connected to multiplayer server'));
|
|
261
|
-
|
|
262
|
-
// Send client info immediately after connection
|
|
263
|
-
this.updateClientInfo({
|
|
264
|
-
name: this.name,
|
|
265
|
-
role: this.role,
|
|
266
|
-
model: this.model
|
|
267
|
-
});
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
this.ws.on('message', (data) => {
|
|
275
|
+
return new Promise((resolve, reject) => {
|
|
276
|
+
const connectWithRetry = async () => {
|
|
271
277
|
try {
|
|
272
|
-
|
|
273
|
-
this.
|
|
278
|
+
// If no server URL is provided, try to start a local server
|
|
279
|
+
if (this.serverUrl === 'ws://localhost:8080') {
|
|
280
|
+
try {
|
|
281
|
+
this.serverUrl = await ensureServerRunning(8080);
|
|
282
|
+
} catch (error) {
|
|
283
|
+
console.error(chalk.red('Failed to start local server:'), error.message);
|
|
284
|
+
reject(error);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
console.log(chalk.blue(`Connecting to ${this.serverUrl}...`));
|
|
290
|
+
this.ws = new WebSocket(this.serverUrl);
|
|
291
|
+
|
|
292
|
+
const connectionTimeout = setTimeout(() => {
|
|
293
|
+
this.ws.terminate();
|
|
294
|
+
reject(new Error('Connection timeout'));
|
|
295
|
+
}, 10000); // 10 seconds timeout
|
|
296
|
+
|
|
297
|
+
this.ws.on('open', () => {
|
|
298
|
+
clearTimeout(connectionTimeout);
|
|
299
|
+
this.connected = true;
|
|
300
|
+
console.log(chalk.green('✅ Connected to multiplayer server'));
|
|
301
|
+
|
|
302
|
+
// Send client info
|
|
303
|
+
this.send({
|
|
304
|
+
type: 'client_info',
|
|
305
|
+
clientId: this.clientId,
|
|
306
|
+
name: this.name,
|
|
307
|
+
role: this.role,
|
|
308
|
+
model: this.model
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
this.emit('connected');
|
|
312
|
+
resolve();
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
this.ws.on('message', (data) => {
|
|
316
|
+
try {
|
|
317
|
+
const message = JSON.parse(data);
|
|
318
|
+
this.handleMessage(message);
|
|
319
|
+
} catch (error) {
|
|
320
|
+
console.error('Error parsing message:', error);
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
this.ws.on('close', () => {
|
|
325
|
+
this.connected = false;
|
|
326
|
+
this.emit('disconnected');
|
|
327
|
+
console.log(chalk.yellow('\n🔌 Disconnected from multiplayer server'));
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
this.ws.on('error', (error) => {
|
|
331
|
+
clearTimeout(connectionTimeout);
|
|
332
|
+
console.error('WebSocket error:', error.message);
|
|
333
|
+
if (!this.connected) {
|
|
334
|
+
reject(error);
|
|
335
|
+
}
|
|
336
|
+
this.emit('error', error);
|
|
337
|
+
});
|
|
338
|
+
|
|
274
339
|
} catch (error) {
|
|
275
|
-
console.error('
|
|
340
|
+
console.error('Connection error:', error.message);
|
|
341
|
+
reject(error);
|
|
276
342
|
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
this.ws.on('close', () => {
|
|
280
|
-
this.connected = false;
|
|
281
|
-
this.emit('disconnected');
|
|
282
|
-
console.log(chalk.yellow('\n🔌 Disconnected from multiplayer server'));
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
this.ws.on('error', (error) => {
|
|
286
|
-
console.error('WebSocket error:', error);
|
|
287
|
-
this.emit('error', error);
|
|
288
|
-
});
|
|
343
|
+
};
|
|
289
344
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
this.emit('error', error);
|
|
293
|
-
}
|
|
345
|
+
connectWithRetry();
|
|
346
|
+
});
|
|
294
347
|
}
|
|
295
348
|
|
|
296
349
|
handleMessage(message) {
|