@kzheart_/mc-pilot 0.4.0 → 0.4.1

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.
@@ -60,6 +60,8 @@ export declare class ClientInstanceManager {
60
60
  inWorld: boolean;
61
61
  position: unknown;
62
62
  }>;
63
+ private buildDiagnostics;
64
+ private formatDiagnostics;
63
65
  getClient(name?: string): Promise<ClientRuntimeEntry>;
64
66
  loadMeta(clientName: string): Promise<ClientInstanceMeta>;
65
67
  updateMeta(clientName: string, updates: Partial<ClientInstanceMeta>): Promise<ClientInstanceMeta>;
@@ -190,6 +190,7 @@ export class ClientInstanceManager {
190
190
  const requireWorld = options.requireWorld ?? true;
191
191
  // 阶段 A:等 WS 连通
192
192
  let connected = false;
193
+ let lastConnectError;
193
194
  while (Date.now() < deadline) {
194
195
  try {
195
196
  const ws = new WebSocketClient(wsUrl);
@@ -197,12 +198,22 @@ export class ClientInstanceManager {
197
198
  connected = true;
198
199
  break;
199
200
  }
200
- catch {
201
+ catch (err) {
202
+ lastConnectError = err instanceof Error ? err.message : String(err);
201
203
  await new Promise((resolve) => setTimeout(resolve, 500));
202
204
  }
203
205
  }
204
206
  if (!connected) {
205
- throw new MctError({ code: "TIMEOUT", message: `Timed out connecting to client ${clientName} on ${wsUrl}` }, 2);
207
+ const diag = this.buildDiagnostics(entry.pid, entry.wsPort, {
208
+ wsConnected: false,
209
+ inWorld: false,
210
+ lastError: lastConnectError
211
+ });
212
+ throw new MctError({
213
+ code: "TIMEOUT",
214
+ message: `Timed out after ${timeoutSeconds}s waiting for client ${clientName} (${wsUrl}). ${this.formatDiagnostics(diag)}`,
215
+ details: diag
216
+ }, 2);
206
217
  }
207
218
  if (!requireWorld) {
208
219
  return { connected: true, url: wsUrl };
@@ -221,16 +232,47 @@ export class ClientInstanceManager {
221
232
  break;
222
233
  }
223
234
  }
224
- catch {
225
- // 连接瞬断等偶发错误,继续轮询
235
+ catch (err) {
236
+ lastErrorCode = err instanceof Error ? `WS_ERROR(${err.message})` : "WS_ERROR";
226
237
  }
227
238
  await new Promise((resolve) => setTimeout(resolve, 500));
228
239
  }
240
+ const diag = this.buildDiagnostics(entry.pid, entry.wsPort, {
241
+ wsConnected: true,
242
+ inWorld: false,
243
+ lastError: lastErrorCode
244
+ });
229
245
  throw new MctError({
230
246
  code: "TIMEOUT",
231
- message: `Client ${clientName} connected (${wsUrl}) but did not join a world (last status: ${lastErrorCode}). Tip: try \`mct client reconnect --address <server>\` or \`mct client launch --force\`.`
247
+ message: `Timed out after ${timeoutSeconds}s waiting for client ${clientName} to join a world (${wsUrl}). ${this.formatDiagnostics(diag)} Tip: try \`mct client reconnect --address <server>\` or \`mct client launch --force\`.`,
248
+ details: diag
232
249
  }, 2);
233
250
  }
251
+ buildDiagnostics(pid, wsPort, extras) {
252
+ const processAlive = isProcessRunning(pid);
253
+ const portListening = getListeningPids(wsPort).length > 0;
254
+ return {
255
+ pid,
256
+ processAlive,
257
+ wsPort,
258
+ portListening,
259
+ wsConnected: extras.wsConnected,
260
+ inWorld: extras.inWorld,
261
+ lastError: extras.lastError
262
+ };
263
+ }
264
+ formatDiagnostics(diag) {
265
+ const parts = [
266
+ `processAlive=${diag.processAlive}`,
267
+ `portListening=${diag.portListening}`,
268
+ `wsConnected=${diag.wsConnected}`,
269
+ `inWorld=${diag.inWorld}`
270
+ ];
271
+ if (diag.lastError) {
272
+ parts.push(`lastError=${diag.lastError}`);
273
+ }
274
+ return `Diagnostics: ${parts.join(", ")}.`;
275
+ }
234
276
  async getClient(name) {
235
277
  const state = await this.globalState.readClientState();
236
278
  const resolvedName = name ?? state.defaultClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kzheart_/mc-pilot",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Minecraft plugin/mod automated testing CLI – control a real Minecraft client to simulate player actions",
5
5
  "type": "module",
6
6
  "bin": {