dsh-plugin-vrmpet3d 0.1.2 → 0.1.4
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 +1 -0
- package/assets/game/levels.json +2925 -0
- package/desktop/game-visibility.cjs +65 -0
- package/desktop/main.js +58 -2
- package/desktop/preload.js +10 -0
- package/lib/client.core.js +78 -33
- package/lib/client.js +41 -11
- package/lib/client.menu.js +3 -0
- package/lib/client.scene.js +3 -2
- package/lib/config-page.js +12 -12
- package/lib/core.js +78 -33
- package/lib/desktop-page.js +16 -7
- package/lib/index.js +182 -34
- package/lib/menu.js +3 -0
- package/lib/mini-game-core.js +329 -0
- package/lib/mini-game-level-store.js +37 -0
- package/lib/mini-game-page.js +615 -0
- package/lib/mini-game.css +19 -0
- package/lib/mini-game.html +50 -0
- package/lib/model-picker.js +4 -4
- package/lib/scene.js +3 -2
- package/lib/setup-page.js +3 -3
- package/package.json +3 -3
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
5
|
+
<title>吃白饭 · 桌宠弹球</title>
|
|
6
|
+
<link rel="stylesheet" href="/vrmpet3d/window/lib/mini-game.css">
|
|
7
|
+
<style>.actions{flex-wrap:wrap}#test-controls{position:absolute;left:18px;bottom:64px;display:flex;flex-wrap:wrap;gap:8px;align-items:center;max-width:90%;padding:10px;border-radius:12px;background:#101b24e8;font-size:12px}#test-controls button{padding:6px 10px}</style>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<main id="game" aria-label="吃白饭,桌宠弹球游戏">
|
|
11
|
+
<div id="playfield">
|
|
12
|
+
<canvas id="arena" aria-label="鼠标移动横杆,左键发射,Esc 暂停"></canvas>
|
|
13
|
+
<canvas id="pet" aria-hidden="true"></canvas>
|
|
14
|
+
<div id="resume-countdown" hidden role="status" aria-live="polite" aria-atomic="true"><strong id="countdown-number">3</strong><span>准备继续 · Esc 返回暂停</span></div>
|
|
15
|
+
</div>
|
|
16
|
+
<header><div class="brand">吃白饭 <small>PET BREAKOUT</small></div><div></div><div class="controls"><button id="pause">暂停 <kbd>Esc</kbd></button><button id="fullscreen">全屏 ↗</button></div></header>
|
|
17
|
+
<div id="game-hud"><span id="level" aria-live="polite"></span><span id="score" aria-live="polite"></span></div>
|
|
18
|
+
<button id="notice" hidden></button>
|
|
19
|
+
<div id="lives" role="img" aria-label="备用 2 次机会"></div>
|
|
20
|
+
<p id="hint">移动鼠标控制横杆 · 左键发射 · Esc 暂停</p>
|
|
21
|
+
<p id="model-status" role="status">正在准备桌宠模型…</p>
|
|
22
|
+
<section id="overlay" hidden role="dialog" aria-modal="true" aria-labelledby="pause-title">
|
|
23
|
+
<fieldset id="debug-controls" class="model-controls" hidden><legend>DEBUG · 目前开放 2 关</legend>
|
|
24
|
+
<label for="debug-level">选择关卡</label><select id="debug-level"><option value="1">第1关 · DS / BALL</option><option value="2">第2关 · 蓝白大碗</option></select>
|
|
25
|
+
<small>切换关卡会重置所选关卡进度,保留当前机会和游戏设置。</small>
|
|
26
|
+
</fieldset>
|
|
27
|
+
<div class="panel"><span class="eyebrow">TAKE A LITTLE BREAK</span><h1 id="pause-title">休息一下</h1><p id="pause-copy">饭还热着,随时回来继续。</p><div id="sessions"></div><div class="actions"><button id="resume" class="primary">继续吃饭</button><button id="restart">重置当前关卡</button><button id="exit">保存并退出</button></div><p id="save-status" role="status"></p><p id="connection" role="status"></p></div>
|
|
28
|
+
<fieldset class="model-controls" hidden><legend>游戏模型</legend>
|
|
29
|
+
<label for="model-size">模型尺寸 <output id="model-size-value" for="model-size">90</output> px</label>
|
|
30
|
+
<input id="model-size" type="range" min="30" max="150" step="5" value="90">
|
|
31
|
+
<label for="spin-speed">旋转速度 <output id="spin-speed-value" for="spin-speed">7</output> rad/s</label>
|
|
32
|
+
<input id="spin-speed" type="range" min="0" max="30" step="1" value="7">
|
|
33
|
+
<label for="flight-speed">飞行速度 <output id="flight-speed-value" for="flight-speed">1</output> 倍</label>
|
|
34
|
+
<input id="flight-speed" type="range" min="0.5" max="2" step="0.1" value="1">
|
|
35
|
+
<label for="paddle-boost">每次撞杆加速 <output id="paddle-boost-value" for="paddle-boost">1.5</output> %</label>
|
|
36
|
+
<input id="paddle-boost" type="range" min="0" max="20" step="0.5" value="1.5">
|
|
37
|
+
<small>尺寸仅影响外观;自转设为 0 可停止旋转。飞行速度会改变游戏速度。</small>
|
|
38
|
+
</fieldset>
|
|
39
|
+
</section>
|
|
40
|
+
<aside id="test-controls" hidden aria-label="独立测试模式">
|
|
41
|
+
<strong>独立测试模式</strong><button id="test-rice">测试吃饭</button><button id="test-bowl">测试撞碗</button><button id="test-loss">模拟漏球</button><button id="test-clear">模拟通关</button><button id="test-notice">模拟消息</button>
|
|
42
|
+
</aside>
|
|
43
|
+
</main>
|
|
44
|
+
<script id="game-level-data" type="application/json">null</script>
|
|
45
|
+
<script src="/vrmpet3d/window/lib/core.js"></script>
|
|
46
|
+
<script src="/vrmpet3d/window/lib/client.vendor.js"></script>
|
|
47
|
+
<script src="/vrmpet3d/window/lib/scene.js"></script>
|
|
48
|
+
<script src="/vrmpet3d/window/lib/mini-game-core.js"></script>
|
|
49
|
+
<script src="/vrmpet3d/window/lib/mini-game-page.js"></script>
|
|
50
|
+
</body></html>
|
package/lib/model-picker.js
CHANGED
|
@@ -427,7 +427,7 @@
|
|
|
427
427
|
if (!doFetch) return Promise.reject(new Error(text.noFetchUpload));
|
|
428
428
|
return doFetch(path, {
|
|
429
429
|
method: 'POST',
|
|
430
|
-
credentials: '
|
|
430
|
+
credentials: 'same-origin',
|
|
431
431
|
headers: { 'content-type': 'application/json' },
|
|
432
432
|
body: JSON.stringify(body),
|
|
433
433
|
}).then(function (response) {
|
|
@@ -617,7 +617,7 @@
|
|
|
617
617
|
onStatus(text.listFailed, 'warn');
|
|
618
618
|
return Promise.resolve(null);
|
|
619
619
|
}
|
|
620
|
-
return doFetch(catalogUrl, { credentials: '
|
|
620
|
+
return doFetch(catalogUrl, { credentials: 'same-origin' })
|
|
621
621
|
.then(function (response) { return response.ok ? response.json() : null; })
|
|
622
622
|
.then(function (payload) {
|
|
623
623
|
if (!apply(payload)) onStatus(text.listFailed, 'warn');
|
|
@@ -692,10 +692,10 @@
|
|
|
692
692
|
setBusy(true, text.importingFile(name));
|
|
693
693
|
return doFetch(uploadUrl + '?file=' + encodeURIComponent(name), {
|
|
694
694
|
method: 'POST',
|
|
695
|
-
credentials: '
|
|
695
|
+
credentials: 'same-origin',
|
|
696
696
|
// The extension decided what this is; the CONTENT TYPE is what tells the host to read a raw body
|
|
697
697
|
// rather than JSON, so it is stated even when the browser has no type for the file.
|
|
698
|
-
headers: { 'content-type':
|
|
698
|
+
headers: { 'content-type': 'application/octet-stream' },
|
|
699
699
|
body: file,
|
|
700
700
|
}).then(function (response) {
|
|
701
701
|
if (!response.ok) {
|
package/lib/scene.js
CHANGED
|
@@ -2052,11 +2052,12 @@
|
|
|
2052
2052
|
* repeated GET of the same URL without touching the disk — which would make 重载模型 look like it did nothing. The
|
|
2053
2053
|
* one-shot buster from `bustModelCache` rides the query string, and is consumed here so an ordinary load stays clean.
|
|
2054
2054
|
*/
|
|
2055
|
-
|
|
2055
|
+
var reload = Boolean(this.modelBust);
|
|
2056
|
+
if (reload) {
|
|
2056
2057
|
url += (url.indexOf('?') === -1 ? '?' : '&') + 'v=' + this.modelBust;
|
|
2057
2058
|
this.modelBust = null;
|
|
2058
2059
|
}
|
|
2059
|
-
var promise = fetch(url, { credentials: '
|
|
2060
|
+
var promise = fetch(url, { credentials: 'same-origin', cache: reload ? 'reload' : 'default' })
|
|
2060
2061
|
.then(function (response) {
|
|
2061
2062
|
if (!response.ok) throw new Error('asset route returned HTTP ' + response.status);
|
|
2062
2063
|
return response.arrayBuffer();
|
package/lib/setup-page.js
CHANGED
|
@@ -301,7 +301,7 @@
|
|
|
301
301
|
function post(path, body) {
|
|
302
302
|
return fetch(path, {
|
|
303
303
|
method: 'POST',
|
|
304
|
-
credentials: '
|
|
304
|
+
credentials: 'same-origin',
|
|
305
305
|
headers: { 'content-type': 'application/json' },
|
|
306
306
|
body: JSON.stringify(body),
|
|
307
307
|
}).then(function (response) {
|
|
@@ -315,7 +315,7 @@
|
|
|
315
315
|
}
|
|
316
316
|
|
|
317
317
|
function getJson(path) {
|
|
318
|
-
return fetch(path, { credentials: '
|
|
318
|
+
return fetch(path, { credentials: 'same-origin' })
|
|
319
319
|
.then(function (response) { return response.ok ? response.json() : null; })
|
|
320
320
|
.catch(function () { return null; });
|
|
321
321
|
}
|
|
@@ -517,7 +517,7 @@
|
|
|
517
517
|
function renderRuntimeNote() {
|
|
518
518
|
var line = el('setup-runtime-path');
|
|
519
519
|
if (!line || typeof fetch !== 'function') return;
|
|
520
|
-
fetch('/vrmpet3d/desktop', { credentials: '
|
|
520
|
+
fetch('/vrmpet3d/desktop', { credentials: 'same-origin' })
|
|
521
521
|
.then(function (response) { return response.ok ? response.json() : null; })
|
|
522
522
|
.then(function (status) {
|
|
523
523
|
var dir = status && typeof status.runtimeDir === 'string' ? status.runtimeDir : '';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-vrmpet3d",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "DeepSeek Harness 的 VRM 3D 桌宠:任务状态联动、独立悬浮窗、模型动作与 AI 碎碎念。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -36,7 +36,6 @@
|
|
|
36
36
|
]
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
|
-
"displayName": "桌宠 3D · VRM Pet 3D",
|
|
40
39
|
"repository": {
|
|
41
40
|
"type": "git",
|
|
42
41
|
"url": "https://github.com/drliuhuan/dsh-plugin-vrmpet3d.git"
|
|
@@ -53,5 +52,6 @@
|
|
|
53
52
|
"vrma",
|
|
54
53
|
"threejs",
|
|
55
54
|
"electron"
|
|
56
|
-
]
|
|
55
|
+
],
|
|
56
|
+
"displayName": "桌宠 3D · VRM Pet 3D"
|
|
57
57
|
}
|