gamekit777 0.1.6 → 0.1.7
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/create-game/scaffold.ts +72 -15
- package/create-game/template/base/game.meta.json +9 -0
- package/create-game/template/{game.ts.tmpl → base/game.ts} +15 -11
- package/create-game/template/{package.json.tmpl → base/package.json} +7 -3
- package/create-game/template/{src/components/App.svelte.tmpl → base/src/components/App.svelte} +8 -3
- package/create-game/template/{src/context.svelte.ts.tmpl → base/src/context.svelte.ts} +5 -5
- package/create-game/template/{src → base/src}/rules/const.ts +2 -1
- package/create-game/template/{src/rules/restore.ts.tmpl → base/src/rules/restore.ts} +7 -5
- package/create-game/template/{src/rules/schema.ts.tmpl → base/src/rules/schema.ts} +2 -2
- package/create-game/template/{src/rules/simulate.ts.tmpl → base/src/rules/simulate.ts} +2 -2
- package/create-game/template/{src/rules/types.ts.tmpl → base/src/rules/types.ts} +2 -2
- package/create-game/template/{src/state/game.svelte.ts.tmpl → base/src/state/game.svelte.ts} +14 -7
- package/create-game/template/{src/view/mount.svelte.ts.tmpl → base/src/view/mount.svelte.ts} +6 -4
- package/create-game/template/{src/view/present.ts.tmpl → base/src/view/present.ts} +2 -2
- package/create-game/template/{test/e2e.test.ts.tmpl → base/test/e2e.test.ts} +4 -1
- package/create-game/template/base/tsconfig.json +8 -0
- package/create-game/template/{CLAUDE.md.tmpl → overlay/CLAUDE.md.tmpl} +13 -3
- package/dev-host/DevShell.svelte +237 -73
- package/dev-host/index.ts +1 -0
- package/dev-host/layout.ts +80 -0
- package/dev-host/platform.svelte.ts +23 -4
- package/dev-host/run.ts +8 -1
- package/dev-host/theme.css +142 -10
- package/package.json +1 -1
- package/runtime/index.ts +1 -0
- package/runtime/meter.ts +72 -0
- package/runtime/registry.ts +5 -1
- package/sdk/host.ts +8 -0
- package/sdk/stage.ts +97 -11
- package/studio/app/App.svelte +92 -10
- package/studio/app/panels/PreviewPanel.svelte +4 -0
- package/studio/preview/entry.ts +10 -1
- package/studio/src/engine.ts +5 -1
- package/studio/src/mcp.ts +4 -2
- package/studio/src/studio-plugin.ts +29 -13
- package/create-game/template/game.meta.json.tmpl +0 -8
- package/create-game/template/tsconfig.json +0 -22
- /package/create-game/template/{scripts/verify.ts.tmpl → base/scripts/verify.ts} +0 -0
- /package/create-game/template/{src → base/src}/assets/critical/.gitkeep +0 -0
- /package/create-game/template/{src → base/src}/assets/lazy/.gitkeep +0 -0
- /package/create-game/template/{src/index.ts.tmpl → base/src/index.ts} +0 -0
- /package/create-game/template/{src → base/src}/styles/animations.css +0 -0
- /package/create-game/template/{src → base/src}/styles/global.css +0 -0
- /package/create-game/template/{src → base/src}/view/bridge.svelte.ts +0 -0
- /package/create-game/template/{vite.config.ts → base/vite.config.ts} +0 -0
- /package/create-game/template/{vitest.config.ts → base/vitest.config.ts} +0 -0
- /package/create-game/template/{_gitignore → overlay/_gitignore} +0 -0
package/studio/src/engine.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
|
|
6
6
|
import { join, relative } from 'node:path';
|
|
7
7
|
import { Sha256 } from 'gamekit777/sdk/hash';
|
|
8
|
+
import type { StageInfo, StageLayout } from 'gamekit777/sdk';
|
|
8
9
|
import type { Segment } from 'gamekit777/weights';
|
|
9
10
|
import { Bus } from './bus.ts';
|
|
10
11
|
import { buildMode, groupsSummary, listArtifacts, readArtifactBytes, sampleMode, type Artifact, type BuildModeOptions } from './build.ts';
|
|
@@ -31,6 +32,9 @@ export interface PreviewState {
|
|
|
31
32
|
lastError: string | null;
|
|
32
33
|
recent: unknown[];
|
|
33
34
|
consoleErrors: string[];
|
|
35
|
+
/** 机台布局与交给游戏的舞台(含安全区)。页面的切换按钮和 MCP 的 preview_set 都以这里为准 */
|
|
36
|
+
layout: StageLayout | null;
|
|
37
|
+
stage: StageInfo | null;
|
|
34
38
|
updatedAt: number;
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -85,7 +89,7 @@ export class Engine {
|
|
|
85
89
|
readonly assets: AssetStore;
|
|
86
90
|
preview: PreviewState = {
|
|
87
91
|
connected: false, config: null, mode: null, bet: null, balance: null,
|
|
88
|
-
status: null, lastError: null, recent: [], consoleErrors: [], updatedAt: 0,
|
|
92
|
+
status: null, lastError: null, recent: [], consoleErrors: [], layout: null, stage: null, updatedAt: 0,
|
|
89
93
|
};
|
|
90
94
|
#publish = new Map<string, PublishRequest>();
|
|
91
95
|
#lastFingerprint: string;
|
package/studio/src/mcp.ts
CHANGED
|
@@ -282,25 +282,27 @@ export function createMcpServer(engine: Engine): McpServer {
|
|
|
282
282
|
});
|
|
283
283
|
|
|
284
284
|
s.registerTool('preview_state', {
|
|
285
|
-
description: '预览页的当前状态:连没连、当前 config / mode / 注额 /
|
|
285
|
+
description: '预览页的当前状态:连没连、当前 config / mode / 注额 / 余额、已加载的表、最近几局、控制台报错、机台布局(desktop/mobile)与交给游戏的舞台尺寸和安全区。',
|
|
286
286
|
inputSchema: {},
|
|
287
287
|
}, async () => {
|
|
288
288
|
engine.touch();
|
|
289
289
|
const p = engine.preview;
|
|
290
290
|
if (!engine.bus.previewConnected) return out(`预览页没连着。请在浏览器打开 ${engine.urls.studio}`, { connected: false });
|
|
291
291
|
return out([`## 预览(本地表模型)`, `- mode ${p.mode},注额 ${p.bet},余额 ${p.balance}`, `- config ${JSON.stringify(p.config)}`,
|
|
292
|
+
...(p.stage ? [`- 布局 ${p.layout},舞台 ${p.stage.width}×${p.stage.height},安全区 上 ${p.stage.safe.top} 下 ${p.stage.safe.bottom}`] : []),
|
|
292
293
|
`- 最近 ${p.recent.length} 局`, ...(p.lastError ? [`- ⚠️ 最近错误:${p.lastError}`] : []),
|
|
293
294
|
...(p.consoleErrors.length ? ['', '### 控制台报错', ...p.consoleErrors.slice(-5).map((e) => `- ${e}`)] : [])].join('\n'), p);
|
|
294
295
|
});
|
|
295
296
|
|
|
296
297
|
s.registerTool('preview_set', {
|
|
297
|
-
description: '改预览的设置:config
|
|
298
|
+
description: '改预览的设置:config、注额、客户端种子、造型、极速、机台布局(desktop 桌面 / mobile 手机竖屏全屏)。局中/自动中会被平台否决,rejected 里会说。',
|
|
298
299
|
inputSchema: {
|
|
299
300
|
config: z.record(z.string(), z.unknown()).optional(),
|
|
300
301
|
bet: z.number().int().optional().describe('最小货币单位(分)'),
|
|
301
302
|
clientSeed: z.string().optional(),
|
|
302
303
|
skin: z.string().optional(),
|
|
303
304
|
turbo: z.boolean().optional(),
|
|
305
|
+
layout: z.enum(['desktop', 'mobile']).optional().describe('切机台布局。游戏不重挂,收到 host.stage 后自己重排'),
|
|
304
306
|
},
|
|
305
307
|
}, async (a) => {
|
|
306
308
|
try {
|
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* 不往游戏目录写任何文件:两个 html 从内存吐,入口用 /@fs 指回 studio 包。
|
|
7
7
|
* 不依赖游戏目录里有 index.html:脚手架出来的项目没有它,`bun run dev` 就是起 studio。 */
|
|
8
|
-
import {
|
|
9
|
-
import type { Plugin } from 'vite';
|
|
10
|
-
import { compile } from 'svelte/compiler';
|
|
8
|
+
import type { DevEnvironment, Plugin, Rollup } from 'vite';
|
|
11
9
|
import { API_PREFIX, createApi } from './api.ts';
|
|
12
10
|
import type { Engine } from './engine.ts';
|
|
13
11
|
|
|
@@ -55,18 +53,36 @@ export function studioPlugin(o: StudioPluginOptions): Plugin {
|
|
|
55
53
|
return null;
|
|
56
54
|
},
|
|
57
55
|
|
|
58
|
-
/*
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
/* svelte 组件 <style> 的兜底。
|
|
57
|
+
vite-plugin-svelte 把编译出的 CSS 挂在组件模块的 meta 上,样式虚拟模块(…svelte?svelte&type=style&lang.css)
|
|
58
|
+
用 getModuleInfo(不带 query 的文件名) 去取。两种情况取不到,它就放弃,vite 退回读文件——
|
|
59
|
+
整份 .svelte 源码被当 CSS 交给下游:模板里的 `{#if}` 变成一条条空规则,`<style>` 里的选择器没有 hash,页面整个走样。
|
|
60
|
+
1. 装成 npm 包后 gamekit777 在游戏的 node_modules 里,vite 给这类模块 id 加 ?v=<hash>,文件名对不上 id。
|
|
61
|
+
仓库内是符号链接到 packages/,走 /@fs 路径没有 ?v=,所以只有创作者机器上才坏。
|
|
62
|
+
2. 组件还没编译过就先来要样式(资源库现场编译、重连、刷新)。
|
|
63
|
+
这里按文件名在模块图里找那次编译留下的 CSS;没有就先把组件本身 transform 一遍再找——
|
|
64
|
+
不能自己 compile 一遍只取 CSS:dev 下 vite-plugin-svelte 用文件名算 scope hash(s-xxx),
|
|
65
|
+
默认的按内容算(svelte-xxx),两边对不上,等于没修。 */
|
|
66
|
+
async load(id) {
|
|
63
67
|
const m = /^([^?]+\.svelte)\?(?:.*&)?svelte(?:&.*)?&type=style(?:&|$)/.exec(id) ?? /^([^?]+\.svelte)\?(?:.*&)?type=style(?:&|$)/.exec(id);
|
|
64
68
|
const file = m?.[1];
|
|
65
|
-
if (!file
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
if (!file) return null;
|
|
70
|
+
const env = this.environment;
|
|
71
|
+
if (env.mode !== 'dev') return null;
|
|
72
|
+
const dev = env as DevEnvironment;
|
|
73
|
+
const pick = (): { code: string; map: Rollup.SourceMapInput | undefined; moduleType: 'css' } | null => {
|
|
74
|
+
for (const mod of dev.moduleGraph.getModulesByFile(file) ?? []) {
|
|
75
|
+
// 插件写的 meta 落在 info.meta 上(vite 的 ModuleInfo 代理),mod.meta 是另一份、可能是空的
|
|
76
|
+
const meta = (mod.info?.meta ?? mod.meta) as { svelte?: { css?: { code?: string; map?: Rollup.SourceMapInput } } } | undefined;
|
|
77
|
+
const css = meta?.svelte?.css;
|
|
78
|
+
if (typeof css?.code === 'string') return { code: css.code, map: css.map, moduleType: 'css' };
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
};
|
|
82
|
+
const hit = pick();
|
|
83
|
+
if (hit) return hit;
|
|
84
|
+
try { await dev.transformRequest(`/@fs${file}`); } catch { return null; }
|
|
85
|
+
return pick();
|
|
70
86
|
},
|
|
71
87
|
|
|
72
88
|
configureServer(server) {
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "@tsconfig/svelte/tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"target": "ES2022",
|
|
5
|
-
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
6
|
-
"module": "ESNext",
|
|
7
|
-
"moduleResolution": "bundler",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"noUnusedLocals": true,
|
|
10
|
-
"noUnusedParameters": true,
|
|
11
|
-
"noImplicitOverride": true,
|
|
12
|
-
"noFallthroughCasesInSwitch": true,
|
|
13
|
-
"noEmit": true,
|
|
14
|
-
"isolatedModules": true,
|
|
15
|
-
"verbatimModuleSyntax": true,
|
|
16
|
-
"skipLibCheck": true,
|
|
17
|
-
"forceConsistentCasingInFileNames": true,
|
|
18
|
-
"allowImportingTsExtensions": true,
|
|
19
|
-
"types": ["vite/client"]
|
|
20
|
-
},
|
|
21
|
-
"include": ["src", "test", "scripts", "*.ts"]
|
|
22
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|