minecraft-dev-starter 0.1.4 → 0.1.5

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/README.md CHANGED
@@ -60,6 +60,7 @@ dsh plugin --profile desktop remove minecraft-dev-starter
60
60
  name: minecraft-dev-starter
61
61
  config:
62
62
  autoOpenLogTab: true
63
+ logDock: right # right:DSH 原生右侧栏;bottom:dsh-better-sidebar 的底部工作台
63
64
  readyTimeoutMs: 90000
64
65
  logRingLines: 2000
65
66
  ```
@@ -67,9 +68,12 @@ dsh plugin --profile desktop remove minecraft-dev-starter
67
68
  | 配置项 | 类型 | 默认值 | 说明 |
68
69
  |---|---|---|---|
69
70
  | `autoOpenLogTab` | boolean | `true` | 启动后自动打开运行日志标签页 |
71
+ | `logDock` | `right` \| `bottom` | `right` | 日志打开位置。`bottom` 需要安装 dsh-better-sidebar;未安装时自动回退到右侧栏 |
70
72
  | `readyTimeoutMs` | number | `90000` | 等待进入运行状态的超时时间;超时不计为失败 |
71
73
  | `logRingLines` | number | `2000` | 内存中保留的日志行数;磁盘上的日志始终完整 |
72
74
 
75
+ `logDock` 只影响「自动打开」与面板里的「打开日志」按钮;无论配置为何,两个标签页都同时存在于原生右侧栏与 better-sidebar 的页签列表中,可随时手动打开。
76
+
73
77
  ## 兼容范围
74
78
 
75
79
  | 平台 | 版本范围 | 说明 |
package/lib/client.js CHANGED
@@ -238,9 +238,19 @@ async function call(method, payload) {
238
238
  return body.result;
239
239
  }
240
240
 
241
+ // src/client/dock.js
242
+ var LOG_DOCK_RIGHT = "right";
243
+ var LOG_DOCK_BOTTOM = "bottom";
244
+ function chooseLogDock(config, hasBetterSidebar) {
245
+ if (hasBetterSidebar !== true) return LOG_DOCK_RIGHT;
246
+ return config?.logDock === LOG_DOCK_BOTTOM ? LOG_DOCK_BOTTOM : LOG_DOCK_RIGHT;
247
+ }
248
+
241
249
  // src/client/runtime.js
242
250
  var DETAIL_KIND = "mcdev.detail";
243
251
  var LOG_KIND = "mcdev.logs";
252
+ var BETTER_DETAIL_ID = "minecraft-dev-starter:project";
253
+ var BETTER_LOG_ID = "minecraft-dev-starter:logs";
244
254
  var runtime = {};
245
255
  function open(kind) {
246
256
  const sidebar = runtime.ctx?.sidebarRight;
@@ -252,10 +262,25 @@ function open(kind) {
252
262
  return false;
253
263
  }
254
264
  }
265
+ function betterSidebar() {
266
+ try {
267
+ return runtime.ctx?.get?.("betterSidebar", false);
268
+ } catch {
269
+ return void 0;
270
+ }
271
+ }
255
272
  function openDetailTab() {
256
273
  return open(DETAIL_KIND);
257
274
  }
258
- function openLogTab() {
275
+ function openLogTab(config) {
276
+ const service = betterSidebar();
277
+ if (chooseLogDock(config, service !== void 0) === LOG_DOCK_BOTTOM) {
278
+ try {
279
+ service.openTab({ type: BETTER_LOG_ID, title: "\u8FD0\u884C\u65E5\u5FD7", target: "bottom" });
280
+ return true;
281
+ } catch {
282
+ }
283
+ }
259
284
  return open(LOG_KIND);
260
285
  }
261
286
 
@@ -296,15 +321,15 @@ var store = createStore({
296
321
  flyoutOpen: false,
297
322
  /** @type {Record<string, string>} 每个工程记住的目标 key */
298
323
  selection: readSelection(),
299
- /** @type {{ autoOpenLogTab?: boolean }} 宿主下发的部署配置 */
300
- config: { autoOpenLogTab: true },
324
+ /** @type {{ autoOpenLogTab?: boolean, logDock?: 'right' | 'bottom' }} 宿主下发的部署配置 */
325
+ config: { autoOpenLogTab: true, logDock: "right" },
301
326
  /** @type {string | undefined} 当前会话的工作区(由胶囊从会话上下文注入) */
302
327
  workspaceRoot: void 0
303
328
  });
304
329
  async function loadStateInfo() {
305
330
  try {
306
331
  const info = await call("state.info", {});
307
- store.set({ config: { autoOpenLogTab: true, ...info?.config ?? {} } });
332
+ store.set({ config: { autoOpenLogTab: true, logDock: "right", ...info?.config ?? {} } });
308
333
  } catch {
309
334
  }
310
335
  }
@@ -396,7 +421,7 @@ async function startTarget(project, target) {
396
421
  kind: target.kind,
397
422
  module: target.module
398
423
  });
399
- if (store.get().config.autoOpenLogTab !== false) openLogTab();
424
+ if (store.get().config.autoOpenLogTab !== false) openLogTab(store.get().config);
400
425
  } catch (error) {
401
426
  launchStore.set({ error: error instanceof Error ? error.message : String(error) });
402
427
  } finally {
@@ -837,7 +862,7 @@ function DetailTab() {
837
862
  ),
838
863
  h(
839
864
  "button",
840
- { type: "button", className: "mcdev-run", onClick: () => openLogTab() },
865
+ { type: "button", className: "mcdev-run", onClick: () => openLogTab(store.get().config) },
841
866
  "\u6253\u5F00\u65E5\u5FD7"
842
867
  )
843
868
  )
@@ -1509,7 +1534,7 @@ function registerBetterSidebarTabs(ctx) {
1509
1534
  try {
1510
1535
  disposers.push(
1511
1536
  sidebar.registerTab({
1512
- id: "minecraft-dev-starter:project",
1537
+ id: BETTER_DETAIL_ID,
1513
1538
  title: PANEL_TITLE,
1514
1539
  icon: (size) => h(IconCube, { size }),
1515
1540
  component: () => h(DetailTab)
@@ -1517,7 +1542,7 @@ function registerBetterSidebarTabs(ctx) {
1517
1542
  );
1518
1543
  disposers.push(
1519
1544
  sidebar.registerTab({
1520
- id: "minecraft-dev-starter:logs",
1545
+ id: BETTER_LOG_ID,
1521
1546
  title: "\u8FD0\u884C\u65E5\u5FD7",
1522
1547
  icon: (size) => h(IconTerminal, { size }),
1523
1548
  component: () => h(LogTab)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minecraft-dev-starter",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "private": false,
5
5
  "description": "DSH plugin that detects Minecraft mod projects and launches the client from the session header, with live logs in the sidebar",
6
6
  "type": "module",
@@ -17,6 +17,7 @@ import {
17
17
  selectedProject,
18
18
  startTarget,
19
19
  stopLaunch,
20
+ store,
20
21
  useLaunches,
21
22
  useStoreState,
22
23
  } from './state.js'
@@ -122,7 +123,7 @@ export function DetailTab() {
122
123
  ),
123
124
  h(
124
125
  'button',
125
- { type: 'button', className: 'mcdev-run', onClick: () => openLogTab() },
126
+ { type: 'button', className: 'mcdev-run', onClick: () => openLogTab(store.get().config) },
126
127
  '打开日志',
127
128
  ),
128
129
  ),
@@ -0,0 +1,20 @@
1
+ /**
2
+ * 日志标签的落点选择。
3
+ *
4
+ * 右列属于 DSH 原生右侧栏;底部工作台是 dsh-better-sidebar 提供的。
5
+ * 未安装 better-sidebar 时只能落在右侧栏,配置值在这种情况下被忽略。
6
+ * @module minecraft-dev-starter/client/dock
7
+ */
8
+
9
+ export const LOG_DOCK_RIGHT = 'right'
10
+ export const LOG_DOCK_BOTTOM = 'bottom'
11
+
12
+ /**
13
+ * @param {{ logDock?: string } | undefined} config
14
+ * @param {boolean} hasBetterSidebar
15
+ * @returns {'right' | 'bottom'}
16
+ */
17
+ export function chooseLogDock(config, hasBetterSidebar) {
18
+ if (hasBetterSidebar !== true) return LOG_DOCK_RIGHT
19
+ return config?.logDock === LOG_DOCK_BOTTOM ? LOG_DOCK_BOTTOM : LOG_DOCK_RIGHT
20
+ }
@@ -17,7 +17,7 @@ import { LogTab } from './LogTab.js'
17
17
  import { report } from './debug.js'
18
18
  import { h } from './h.js'
19
19
  import { IconCube, IconTerminal } from './icons.js'
20
- import { DETAIL_KIND, LOG_KIND, runtime } from './runtime.js'
20
+ import { BETTER_DETAIL_ID, BETTER_LOG_ID, DETAIL_KIND, LOG_KIND, runtime } from './runtime.js'
21
21
  import { ensureStyles } from './styles.js'
22
22
 
23
23
  export const name = 'mcdev-client'
@@ -99,7 +99,7 @@ function registerBetterSidebarTabs(ctx) {
99
99
  try {
100
100
  disposers.push(
101
101
  sidebar.registerTab({
102
- id: 'minecraft-dev-starter:project',
102
+ id: BETTER_DETAIL_ID,
103
103
  title: PANEL_TITLE,
104
104
  icon: (size) => h(IconCube, { size }),
105
105
  component: () => h(DetailTab),
@@ -107,7 +107,7 @@ function registerBetterSidebarTabs(ctx) {
107
107
  )
108
108
  disposers.push(
109
109
  sidebar.registerTab({
110
- id: 'minecraft-dev-starter:logs',
110
+ id: BETTER_LOG_ID,
111
111
  title: '运行日志',
112
112
  icon: (size) => h(IconTerminal, { size }),
113
113
  component: () => h(LogTab),
@@ -6,12 +6,18 @@
6
6
  * @module minecraft-dev-starter/client/runtime
7
7
  */
8
8
 
9
- /** 右侧栏「MC 工程」详情标签的 kind。 */
9
+ import { chooseLogDock, LOG_DOCK_BOTTOM } from './dock.js'
10
+
11
+ /** 右侧栏「Mod Dev」详情标签的 kind。 */
10
12
  export const DETAIL_KIND = 'mcdev.detail'
11
13
 
12
14
  /** 右侧栏「运行日志」标签的 kind。 */
13
15
  export const LOG_KIND = 'mcdev.logs'
14
16
 
17
+ /** 向 dsh-better-sidebar 注册时用的 tab id;打开底部工作台需要同一个 id。 */
18
+ export const BETTER_DETAIL_ID = 'minecraft-dev-starter:project'
19
+ export const BETTER_LOG_ID = 'minecraft-dev-starter:logs'
20
+
15
21
  /** @type {{ ctx?: any }} */
16
22
  export const runtime = {}
17
23
 
@@ -30,12 +36,39 @@ function open(kind) {
30
36
  }
31
37
  }
32
38
 
39
+ /**
40
+ * 取可选的 better-sidebar 服务;未安装时返回 undefined(不抛错)。
41
+ * @returns {any}
42
+ */
43
+ export function betterSidebar() {
44
+ try {
45
+ return runtime.ctx?.get?.('betterSidebar', false)
46
+ } catch {
47
+ return undefined
48
+ }
49
+ }
50
+
33
51
  /** 打开工程详情标签(openTab 会顺带展开面板)。 */
34
52
  export function openDetailTab() {
35
53
  return open(DETAIL_KIND)
36
54
  }
37
55
 
38
- /** 打开运行日志标签。 */
39
- export function openLogTab() {
56
+ /**
57
+ * 打开运行日志标签。
58
+ *
59
+ * 落点由配置 `logDock` 决定:`bottom` 且装了 better-sidebar 时落到底部工作台,
60
+ * 其余情况一律落原生右侧栏。配置由调用方传入,避免 runtime ←→ state 循环依赖。
61
+ * @param {{ logDock?: string } | undefined} [config]
62
+ */
63
+ export function openLogTab(config) {
64
+ const service = betterSidebar()
65
+ if (chooseLogDock(config, service !== undefined) === LOG_DOCK_BOTTOM) {
66
+ try {
67
+ service.openTab({ type: BETTER_LOG_ID, title: '运行日志', target: 'bottom' })
68
+ return true
69
+ } catch {
70
+ /* 落底部失败就退回右侧栏,不吞掉日志入口 */
71
+ }
72
+ }
40
73
  return open(LOG_KIND)
41
74
  }
@@ -25,8 +25,8 @@ export const store = createStore({
25
25
  flyoutOpen: false,
26
26
  /** @type {Record<string, string>} 每个工程记住的目标 key */
27
27
  selection: readSelection(),
28
- /** @type {{ autoOpenLogTab?: boolean }} 宿主下发的部署配置 */
29
- config: { autoOpenLogTab: true },
28
+ /** @type {{ autoOpenLogTab?: boolean, logDock?: 'right' | 'bottom' }} 宿主下发的部署配置 */
29
+ config: { autoOpenLogTab: true, logDock: 'right' },
30
30
  /** @type {string | undefined} 当前会话的工作区(由胶囊从会话上下文注入) */
31
31
  workspaceRoot: undefined,
32
32
  })
@@ -37,7 +37,7 @@ export const store = createStore({
37
37
  export async function loadStateInfo() {
38
38
  try {
39
39
  const info = await call('state.info', {})
40
- store.set({ config: { autoOpenLogTab: true, ...(info?.config ?? {}) } })
40
+ store.set({ config: { autoOpenLogTab: true, logDock: 'right', ...(info?.config ?? {}) } })
41
41
  } catch {
42
42
  /* 拉不到就用默认值 */
43
43
  }
@@ -172,7 +172,7 @@ export async function startTarget(project, target) {
172
172
  module: target.module,
173
173
  })
174
174
  // 启动成功就把日志摆到人眼前(部署配置可关)
175
- if (store.get().config.autoOpenLogTab !== false) openLogTab()
175
+ if (store.get().config.autoOpenLogTab !== false) openLogTab(store.get().config)
176
176
  } catch (error) {
177
177
  launchStore.set({ error: error instanceof Error ? error.message : String(error) })
178
178
  } finally {
package/src/index.js CHANGED
@@ -117,6 +117,7 @@ function resolveWorkspaceRoot(ctx) {
117
117
  /** 部署配置默认值;patch 行的 `config` 会覆盖同名项。 */
118
118
  const DEFAULTS = {
119
119
  autoOpenLogTab: true,
120
+ logDock: 'right',
120
121
  readyTimeoutMs: 90_000,
121
122
  logRingLines: 2_000,
122
123
  }
@@ -131,7 +132,10 @@ export function apply(ctx, config = {}) {
131
132
  version: VERSION,
132
133
  resolveRoot: () => resolveWorkspaceRoot(ctx),
133
134
  resolveRoots: () => sessionCwds(ctx),
134
- config: { autoOpenLogTab: settings.autoOpenLogTab !== false },
135
+ config: {
136
+ autoOpenLogTab: settings.autoOpenLogTab !== false,
137
+ logDock: settings.logDock === 'bottom' ? 'bottom' : 'right',
138
+ },
135
139
  launchService: createLaunchService({
136
140
  readyTimeoutMs: Number(settings.readyTimeoutMs) || DEFAULTS.readyTimeoutMs,
137
141
  maxLogLines: Number(settings.logRingLines) || DEFAULTS.logRingLines,