oriverse-engine 0.1.10 → 0.1.12
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/LICENSE.md +30 -30
- package/README.md +8 -8
- package/dist/AGENT_ONBOARDING.md +74 -74
- package/dist/CODEX_PROMPT.md +7 -7
- package/dist/ktx_bridge.js +17 -0
- package/dist/oriverse_wgpu.d.ts +75 -45
- package/dist/oriverse_wgpu.js +352 -133
- package/dist/oriverse_wgpu_bg.wasm +0 -0
- package/dist/oriverse_wgpu_bg.wasm.d.ts +51 -44
- package/dist/shader_prewarm_manifest.json +1 -0
- package/dist/snippets/oriverse_market_client-0cd3013288f3c49c/inline0.js +39 -2
- package/dist/snippets/oriverse_market_client-0cd3013288f3c49c/inline1.js +33 -38
- package/dist/snippets/oriverse_market_client-0cd3013288f3c49c/inline2.js +2 -34
- package/dist/snippets/oriverse_networking_shared-e43478064e11e46c/inline0.js +40 -32
- package/dist/snippets/oriverse_networking_shared-e43478064e11e46c/inline1.js +32 -21
- package/dist/snippets/oriverse_user_client-a55220d4991e3856/src/library_capture_idb.js +54 -0
- package/dist/snippets/oriverse_wgpu-255445ce6d9a0851/inline0.js +27 -32
- package/dist/snippets/oriverse_wgpu-255445ce6d9a0851/inline1.js +58 -26
- package/dist/snippets/oriverse_wgpu-255445ce6d9a0851/inline2.js +31 -58
- package/dist/starter/AGENTS.md +2 -2
- package/dist/starter/CLAUDE.md +2 -2
- package/dist/starter/game.html +6 -6
- package/dist/templates/game_cdn.html +6 -6
- package/dist/weave_documentation.txt +698 -393
- package/package.json +1 -1
|
@@ -1,4 +1,41 @@
|
|
|
1
1
|
|
|
2
|
-
export function
|
|
3
|
-
|
|
2
|
+
export function marketClientReadIndexedDbValue(dbName, storeName, key) {
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
const open = indexedDB.open(dbName);
|
|
5
|
+
open.onupgradeneeded = () => {
|
|
6
|
+
try {
|
|
7
|
+
const db = open.result;
|
|
8
|
+
if (!db.objectStoreNames.contains(storeName)) db.createObjectStore(storeName);
|
|
9
|
+
} catch (error) {
|
|
10
|
+
reject(error);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
open.onerror = () => reject(open.error || new Error('indexedDB open error'));
|
|
14
|
+
open.onblocked = () => reject(new Error('indexedDB open blocked'));
|
|
15
|
+
open.onsuccess = () => {
|
|
16
|
+
const db = open.result;
|
|
17
|
+
const close = () => { try { db.close(); } catch (_) {} };
|
|
18
|
+
try {
|
|
19
|
+
if (!db.objectStoreNames.contains(storeName)) {
|
|
20
|
+
close();
|
|
21
|
+
resolve(undefined);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const get = db.transaction(storeName, 'readonly').objectStore(storeName).get(key);
|
|
25
|
+
get.onsuccess = () => {
|
|
26
|
+
const value = get.result;
|
|
27
|
+
close();
|
|
28
|
+
resolve(value);
|
|
29
|
+
};
|
|
30
|
+
get.onerror = () => {
|
|
31
|
+
const error = get.error || new Error('indexedDB get error');
|
|
32
|
+
close();
|
|
33
|
+
reject(error);
|
|
34
|
+
};
|
|
35
|
+
} catch (error) {
|
|
36
|
+
close();
|
|
37
|
+
reject(error);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
});
|
|
4
41
|
}
|
|
@@ -1,41 +1,36 @@
|
|
|
1
1
|
|
|
2
|
-
export function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const value = get.result;
|
|
27
|
-
close();
|
|
28
|
-
resolve(value);
|
|
29
|
-
};
|
|
30
|
-
get.onerror = () => {
|
|
31
|
-
const error = get.error || new Error('indexedDB get error');
|
|
32
|
-
close();
|
|
33
|
-
reject(error);
|
|
34
|
-
};
|
|
35
|
-
} catch (error) {
|
|
36
|
-
close();
|
|
37
|
-
reject(error);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
2
|
+
export function marketClientInitMessageBridge(worker) {
|
|
3
|
+
if (!worker || typeof window === 'undefined') throw new Error('Worker and window required');
|
|
4
|
+
if (window.marketClientMessageBridgeInitialized) return;
|
|
5
|
+
window.marketClientMessageBridgeInitialized = true;
|
|
6
|
+
|
|
7
|
+
window.top.marketClientWorker = worker;
|
|
8
|
+
worker.addEventListener('message', (e) => {
|
|
9
|
+
const data = e.data;
|
|
10
|
+
if (data?.type === 'market-client-open-url' && data.value) window.open(data.value, '_blank');
|
|
11
|
+
else if (data?.type === 'market-client-open-url-popup' && data.value) {
|
|
12
|
+
const w = Math.min(560, Math.floor(screen.availWidth * 0.4));
|
|
13
|
+
const h = Math.min(860, Math.floor(screen.availHeight * 0.9));
|
|
14
|
+
const left = (screen.availLeft ?? 0) + screen.availWidth - w - 8;
|
|
15
|
+
window.open(data.value, 'oriverse_connect_ai', `popup,width=${w},height=${h},left=${left},top=40`);
|
|
16
|
+
}
|
|
17
|
+
else if (data?.type?.startsWith('market-client-')) {
|
|
18
|
+
window.top.postMessage(data, '*');
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export function marketClientInitMessageListener(callback) {
|
|
23
|
+
const target = typeof window !== 'undefined' ? window.top : (typeof self !== 'undefined' ? self : globalThis);
|
|
24
|
+
target.addEventListener('message', (e) => {
|
|
25
|
+
if (e.data?.type) callback(e.data.type);
|
|
40
26
|
});
|
|
41
27
|
}
|
|
28
|
+
export function marketClientPostMessage(messageType, value) {
|
|
29
|
+
const message = { type: messageType, ...(value != null && { value }) };
|
|
30
|
+
if (typeof window !== 'undefined') {
|
|
31
|
+
window.top.postMessage(message, '*');
|
|
32
|
+
} else {
|
|
33
|
+
const g = typeof self !== 'undefined' ? self : globalThis;
|
|
34
|
+
g.postMessage(message);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -1,36 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
export function
|
|
3
|
-
|
|
4
|
-
if (window.marketClientMessageBridgeInitialized) return;
|
|
5
|
-
window.marketClientMessageBridgeInitialized = true;
|
|
6
|
-
|
|
7
|
-
window.top.marketClientWorker = worker;
|
|
8
|
-
worker.addEventListener('message', (e) => {
|
|
9
|
-
const data = e.data;
|
|
10
|
-
if (data?.type === 'market-client-open-url' && data.value) window.open(data.value, '_blank');
|
|
11
|
-
else if (data?.type === 'market-client-open-url-popup' && data.value) {
|
|
12
|
-
const w = Math.min(560, Math.floor(screen.availWidth * 0.4));
|
|
13
|
-
const h = Math.min(860, Math.floor(screen.availHeight * 0.9));
|
|
14
|
-
const left = (screen.availLeft ?? 0) + screen.availWidth - w - 8;
|
|
15
|
-
window.open(data.value, 'oriverse_connect_ai', `popup,width=${w},height=${h},left=${left},top=40`);
|
|
16
|
-
}
|
|
17
|
-
else if (data?.type?.startsWith('market-client-')) {
|
|
18
|
-
window.top.postMessage(data, '*');
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
export function marketClientInitMessageListener(callback) {
|
|
23
|
-
const target = typeof window !== 'undefined' ? window.top : (typeof self !== 'undefined' ? self : globalThis);
|
|
24
|
-
target.addEventListener('message', (e) => {
|
|
25
|
-
if (e.data?.type) callback(e.data.type);
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
export function marketClientPostMessage(messageType, value) {
|
|
29
|
-
const message = { type: messageType, ...(value != null && { value }) };
|
|
30
|
-
if (typeof window !== 'undefined') {
|
|
31
|
-
window.top.postMessage(message, '*');
|
|
32
|
-
} else {
|
|
33
|
-
const g = typeof self !== 'undefined' ? self : globalThis;
|
|
34
|
-
g.postMessage(message);
|
|
35
|
-
}
|
|
2
|
+
export function marketClientPageHostname() {
|
|
3
|
+
try { return (location && location.hostname) || ''; } catch (e) { return ''; }
|
|
36
4
|
}
|
|
@@ -1,33 +1,41 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
2
|
+
// relay candidates: relayProtocol is the TURN transport (udp/tcp/tls); protocol is always udp.
|
|
3
|
+
export function get_candidate_pairs(stats) {
|
|
4
|
+
const reports = Array.from(stats.values());
|
|
5
|
+
const byId = new Map(reports.map(s => [s.id, s]));
|
|
6
|
+
return reports.filter(s => s.type === 'candidate-pair').map(pair => {
|
|
7
|
+
const local = byId.get(pair.localCandidateId) || {};
|
|
8
|
+
const remote = byId.get(pair.remoteCandidateId) || {};
|
|
9
|
+
return {
|
|
10
|
+
state: pair.state || '', nominated: !!pair.nominated,
|
|
11
|
+
localType: local.candidateType || '', localProtocol: (local.candidateType === 'relay' && local.relayProtocol) || local.protocol || '',
|
|
12
|
+
remoteType: remote.candidateType || '', remoteProtocol: remote.protocol || '',
|
|
13
|
+
remoteIp: remote.address || remote.ip || '', remotePort: remote.port || 0,
|
|
14
|
+
requestsSent: pair.requestsSent || 0, requestsReceived: pair.requestsReceived || 0,
|
|
15
|
+
responsesSent: pair.responsesSent || 0, responsesReceived: pair.responsesReceived || 0,
|
|
16
|
+
bytesSent: pair.bytesSent || 0, bytesReceived: pair.bytesReceived || 0,
|
|
17
|
+
rttMs: pair.currentRoundTripTime != null ? pair.currentRoundTripTime * 1000 : -1
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export function get_selected_candidate_info(stats) {
|
|
22
|
+
const reports = Array.from(stats.values());
|
|
23
|
+
const pair = reports.find(s => s.type === 'candidate-pair' && s.nominated);
|
|
24
|
+
if (!pair) return null;
|
|
25
|
+
const local = reports.find(s => s.type === 'local-candidate' && s.id === pair.localCandidateId);
|
|
26
|
+
const remote = reports.find(s => s.type === 'remote-candidate' && s.id === pair.remoteCandidateId);
|
|
27
|
+
if (!local || !remote) return null;
|
|
28
|
+
return {
|
|
29
|
+
state: pair.state || '',
|
|
30
|
+
localType: local.candidateType || '',
|
|
31
|
+
localAddr: `${local.address || local.ip || 'unknown'}:${local.port || 0}`,
|
|
32
|
+
localProtocol: (local.candidateType === 'relay' && local.relayProtocol) || local.protocol || '',
|
|
33
|
+
remoteType: remote.candidateType || '',
|
|
34
|
+
remoteAddr: `${remote.address || remote.ip || 'unknown'}:${remote.port || 0}`,
|
|
35
|
+
remoteProtocol: remote.protocol || '',
|
|
36
|
+
rttMs: pair.currentRoundTripTime != null ? pair.currentRoundTripTime * 1000 : -1,
|
|
37
|
+
txBytes: pair.bytesSent || 0,
|
|
38
|
+
rxBytes: pair.bytesReceived || 0,
|
|
39
|
+
availOutBps: pair.availableOutgoingBitrate != null ? pair.availableOutgoingBitrate : -1
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
|
|
2
|
-
export function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
2
|
+
export function webRtcReadIndexedDbValue(dbName, storeName, key) {
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
const open = indexedDB.open(dbName);
|
|
5
|
+
open.onupgradeneeded = () => {
|
|
6
|
+
try {
|
|
7
|
+
const db = open.result;
|
|
8
|
+
if (!db.objectStoreNames.contains(storeName)) db.createObjectStore(storeName);
|
|
9
|
+
} catch (error) {
|
|
10
|
+
reject(error);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
open.onerror = () => reject(open.error || new Error('indexedDB open error'));
|
|
14
|
+
open.onblocked = () => reject(new Error('indexedDB open blocked'));
|
|
15
|
+
open.onsuccess = () => {
|
|
16
|
+
const db = open.result;
|
|
17
|
+
const close = () => { try { db.close(); } catch (_) {} };
|
|
18
|
+
try {
|
|
19
|
+
if (!db.objectStoreNames.contains(storeName)) {
|
|
20
|
+
close();
|
|
21
|
+
resolve(undefined);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const get = db.transaction(storeName, 'readonly').objectStore(storeName).get(key);
|
|
25
|
+
get.onsuccess = () => { const value = get.result; close(); resolve(value); };
|
|
26
|
+
get.onerror = () => { const error = get.error || new Error('indexedDB get error'); close(); reject(error); };
|
|
27
|
+
} catch (error) {
|
|
28
|
+
close();
|
|
29
|
+
reject(error);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Storage adapter only: eligibility, capacities, leases and retries are Rust-owned.
|
|
2
|
+
const empty = () => ({format:1,revision:0,batches:{},jobs:{},cooldowns:{}});
|
|
3
|
+
export function libraryQueueIo(command) {
|
|
4
|
+
const c = JSON.parse(command);
|
|
5
|
+
return new Promise((resolve,reject) => {
|
|
6
|
+
const open = indexedDB.open('oriverse_library_capture',1);
|
|
7
|
+
let cancelled = false;
|
|
8
|
+
const fail = e => { cancelled = true; reject(String(e?.message || e || 'library storage failed')); };
|
|
9
|
+
open.onupgradeneeded = () => {
|
|
10
|
+
open.result.createObjectStore('meta');
|
|
11
|
+
open.result.createObjectStore('blobs');
|
|
12
|
+
};
|
|
13
|
+
open.onblocked = () => fail('library storage upgrade blocked; close older editor tabs');
|
|
14
|
+
open.onerror = () => fail(open.error);
|
|
15
|
+
open.onsuccess = () => {
|
|
16
|
+
const db = open.result;
|
|
17
|
+
if(cancelled) { db.close(); return; }
|
|
18
|
+
db.onversionchange = () => db.close();
|
|
19
|
+
let tx, result;
|
|
20
|
+
try { tx = db.transaction(['meta','blobs'],c.op==='commit'?'readwrite':'readonly',c.op==='commit'?{durability:'strict'}:{}); }
|
|
21
|
+
catch(e) { db.close(); fail(e); return; }
|
|
22
|
+
tx.onabort = () => { db.close(); fail(tx.error || 'library transaction aborted'); };
|
|
23
|
+
tx.onerror = () => {}; // abort owns the result; request success is not commit.
|
|
24
|
+
tx.oncomplete = () => { db.close(); resolve(result); };
|
|
25
|
+
const meta=tx.objectStore('meta'),blobs=tx.objectStore('blobs');
|
|
26
|
+
if(c.op==='blob') {
|
|
27
|
+
const get=blobs.get(c.id);
|
|
28
|
+
get.onsuccess=()=>{ if(typeof get.result!=='string') { tx.abort(); return; } result=get.result; };
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const get=meta.get('index');
|
|
32
|
+
get.onsuccess=()=>{
|
|
33
|
+
try {
|
|
34
|
+
const old=get.result || empty();
|
|
35
|
+
if(c.op==='read') { result=JSON.stringify(old); return; }
|
|
36
|
+
if(c.op!=='commit' || old.format!==1) throw Error('unsupported library queue operation/schema');
|
|
37
|
+
if(old.revision!==c.expected) { result='false'; return; }
|
|
38
|
+
const live=new Set(c.live);
|
|
39
|
+
for(const [id,text] of Object.entries(c.writes)) if(live.has(id)) blobs.put(text,id);
|
|
40
|
+
// Old missing blobs must not block claiming/rejecting their own
|
|
41
|
+
// damaged records. Every newly admitted reference must exist.
|
|
42
|
+
const previous=new Set([...Object.values(old.jobs),...Object.values(old.batches)].map(r=>r.blob||r.source).filter(Boolean));
|
|
43
|
+
for(const id of live) { if(previous.has(id)) continue;
|
|
44
|
+
const check=blobs.getKey(id);
|
|
45
|
+
check.onsuccess=()=>{if(check.result===undefined) tx.abort();};
|
|
46
|
+
}
|
|
47
|
+
const cursor=c.collect===false?null:blobs.openKeyCursor();
|
|
48
|
+
if(cursor) cursor.onsuccess=()=>{const row=cursor.result;if(row){if(!live.has(row.key)) blobs.delete(row.key);row.continue();}};
|
|
49
|
+
meta.put(c.index,'index');result='true';
|
|
50
|
+
} catch(e) { tx.abort(); }
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
}
|
|
@@ -1,33 +1,28 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
reject(error);
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
});
|
|
33
|
-
}
|
|
2
|
+
export function __ori_install_webgpu_error_tap(sink) {
|
|
3
|
+
try {
|
|
4
|
+
if (typeof GPUAdapter === 'undefined' || GPUAdapter.prototype.__ori_err_tap) return;
|
|
5
|
+
GPUAdapter.prototype.__ori_err_tap = true;
|
|
6
|
+
const orig = GPUAdapter.prototype.requestDevice;
|
|
7
|
+
GPUAdapter.prototype.requestDevice = async function(desc) {
|
|
8
|
+
const device = await orig.call(this, desc);
|
|
9
|
+
// Only the engine's own device (wgpu_base::APP_DEVICE_LABEL) may escalate to the
|
|
10
|
+
// fatal path. Foreign devices — the index.html [pre_shader] throwaway runs at
|
|
11
|
+
// DEFAULT limits and its replay errors are fail-open by contract — still log
|
|
12
|
+
// through the sink for ring/field visibility (07Aug26 first-contact crash: a
|
|
13
|
+
// throwaway-device validation error killed a healthy boot).
|
|
14
|
+
const isApp = !!(desc && desc.label === 'oriverse-app-device');
|
|
15
|
+
if (isApp) { try { window.__ori_gpu_device = device; } catch (_) {} }
|
|
16
|
+
try {
|
|
17
|
+
device.addEventListener('uncapturederror', function(event) {
|
|
18
|
+
const e = event.error;
|
|
19
|
+
const name = (e && e.constructor && e.constructor.name) || 'GPUError';
|
|
20
|
+
const msg = (e && e.message) || '';
|
|
21
|
+
try { sink(name, msg, isApp); } catch (_) {}
|
|
22
|
+
try { console.error(isApp ? '[raw_webgpu_uncaptured]' : '[raw_webgpu_uncaptured_foreign]', name, msg); } catch (_) {}
|
|
23
|
+
});
|
|
24
|
+
} catch (_) {}
|
|
25
|
+
return device;
|
|
26
|
+
};
|
|
27
|
+
} catch (_) {}
|
|
28
|
+
}
|
|
@@ -1,28 +1,60 @@
|
|
|
1
1
|
|
|
2
|
-
export function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
2
|
+
export function observeDevicePixels(canvas, onSize) {
|
|
3
|
+
const hasDPCB = (() => {
|
|
4
|
+
try { return 'devicePixelContentBoxSize' in ResizeObserverEntry.prototype; } catch { return false; }
|
|
5
|
+
})();
|
|
6
|
+
|
|
7
|
+
// Compute current CSS and device-pixel sizes and call onSize(dpW, dpH, effectiveDpr)
|
|
8
|
+
function fireNow() {
|
|
9
|
+
let cssW, cssH, dpW, dpH;
|
|
10
|
+
if (hasDPCB && canvas.__lastROEntry) {
|
|
11
|
+
const e = canvas.__lastROEntry;
|
|
12
|
+
dpW = e.devicePixelContentBoxSize[0].inlineSize;
|
|
13
|
+
dpH = e.devicePixelContentBoxSize[0].blockSize;
|
|
14
|
+
cssW = e.contentBoxSize[0].inlineSize;
|
|
15
|
+
cssH = e.contentBoxSize[0].blockSize;
|
|
16
|
+
} else {
|
|
17
|
+
const rect = canvas.getBoundingClientRect();
|
|
18
|
+
const dpr = window.devicePixelRatio || 1;
|
|
19
|
+
cssW = rect.width; cssH = rect.height;
|
|
20
|
+
dpW = Math.max(1, Math.round(cssW * dpr));
|
|
21
|
+
dpH = Math.max(1, Math.round(cssH * dpr));
|
|
22
|
+
}
|
|
23
|
+
const dprEff = cssW > 0 ? (dpW / cssW) : (window.devicePixelRatio || 1);
|
|
24
|
+
onSize(dpW >>> 0, dpH >>> 0, dprEff);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const ro = new ResizeObserver(entries => {
|
|
28
|
+
// Save the last entry for precise device-pixel info.
|
|
29
|
+
canvas.__lastROEntry = entries[0];
|
|
30
|
+
fireNow();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
try { ro.observe(canvas, { box: 'device-pixel-content-box' }); }
|
|
34
|
+
catch { ro.observe(canvas); }
|
|
35
|
+
|
|
36
|
+
// DPR changes (zoom / moving across monitors) don't always reflow. Listen explicitly.
|
|
37
|
+
let mq = matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
|
|
38
|
+
const onMQ = () => {
|
|
39
|
+
// Force a non-layout-janking "poke" to trigger RO in some browsers.
|
|
40
|
+
const t = canvas.style.transform;
|
|
41
|
+
canvas.style.transform = 'translateZ(0)'; canvas.style.transform = t;
|
|
42
|
+
fireNow();
|
|
43
|
+
// Re-arm listener for the new DPR.
|
|
44
|
+
mq.removeEventListener?.('change', onMQ);
|
|
45
|
+
mq = matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
|
|
46
|
+
mq.addEventListener?.('change', onMQ);
|
|
47
|
+
};
|
|
48
|
+
mq.addEventListener?.('change', onMQ);
|
|
49
|
+
window.addEventListener('pageshow', onMQ);
|
|
50
|
+
|
|
51
|
+
// Fire once now so we start sized correctly.
|
|
52
|
+
Promise.resolve().then(fireNow);
|
|
53
|
+
|
|
54
|
+
// Return disposer
|
|
55
|
+
return () => {
|
|
56
|
+
try { ro.disconnect(); } catch {}
|
|
57
|
+
try { mq.removeEventListener?.('change', onMQ); } catch {}
|
|
58
|
+
try { window.removeEventListener('pageshow', onMQ); } catch {}
|
|
59
|
+
};
|
|
28
60
|
}
|
|
@@ -1,60 +1,33 @@
|
|
|
1
1
|
|
|
2
|
-
export function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
2
|
+
export function mcpRelayReadIndexedDbValue(dbName, storeName, key) {
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
const open = indexedDB.open(dbName);
|
|
5
|
+
open.onupgradeneeded = () => {
|
|
6
|
+
try {
|
|
7
|
+
const db = open.result;
|
|
8
|
+
if (!db.objectStoreNames.contains(storeName)) db.createObjectStore(storeName);
|
|
9
|
+
} catch (error) {
|
|
10
|
+
reject(error);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
open.onerror = () => reject(open.error || new Error('indexedDB open error'));
|
|
14
|
+
open.onblocked = () => reject(new Error('indexedDB open blocked'));
|
|
15
|
+
open.onsuccess = () => {
|
|
16
|
+
const db = open.result;
|
|
17
|
+
const close = () => { try { db.close(); } catch (_) {} };
|
|
18
|
+
try {
|
|
19
|
+
if (!db.objectStoreNames.contains(storeName)) {
|
|
20
|
+
close();
|
|
21
|
+
resolve(undefined);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const get = db.transaction(storeName, 'readonly').objectStore(storeName).get(key);
|
|
25
|
+
get.onsuccess = () => { const value = get.result; close(); resolve(value); };
|
|
26
|
+
get.onerror = () => { const error = get.error || new Error('indexedDB get error'); close(); reject(error); };
|
|
27
|
+
} catch (error) {
|
|
28
|
+
close();
|
|
29
|
+
reject(error);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
});
|
|
22
33
|
}
|
|
23
|
-
const dprEff = cssW > 0 ? (dpW / cssW) : (window.devicePixelRatio || 1);
|
|
24
|
-
onSize(dpW >>> 0, dpH >>> 0, dprEff);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const ro = new ResizeObserver(entries => {
|
|
28
|
-
// Save the last entry for precise device-pixel info.
|
|
29
|
-
canvas.__lastROEntry = entries[0];
|
|
30
|
-
fireNow();
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
try { ro.observe(canvas, { box: 'device-pixel-content-box' }); }
|
|
34
|
-
catch { ro.observe(canvas); }
|
|
35
|
-
|
|
36
|
-
// DPR changes (zoom / moving across monitors) don't always reflow. Listen explicitly.
|
|
37
|
-
let mq = matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
|
|
38
|
-
const onMQ = () => {
|
|
39
|
-
// Force a non-layout-janking "poke" to trigger RO in some browsers.
|
|
40
|
-
const t = canvas.style.transform;
|
|
41
|
-
canvas.style.transform = 'translateZ(0)'; canvas.style.transform = t;
|
|
42
|
-
fireNow();
|
|
43
|
-
// Re-arm listener for the new DPR.
|
|
44
|
-
mq.removeEventListener?.('change', onMQ);
|
|
45
|
-
mq = matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
|
|
46
|
-
mq.addEventListener?.('change', onMQ);
|
|
47
|
-
};
|
|
48
|
-
mq.addEventListener?.('change', onMQ);
|
|
49
|
-
window.addEventListener('pageshow', onMQ);
|
|
50
|
-
|
|
51
|
-
// Fire once now so we start sized correctly.
|
|
52
|
-
Promise.resolve().then(fireNow);
|
|
53
|
-
|
|
54
|
-
// Return disposer
|
|
55
|
-
return () => {
|
|
56
|
-
try { ro.disconnect(); } catch {}
|
|
57
|
-
try { mq.removeEventListener?.('change', onMQ); } catch {}
|
|
58
|
-
try { window.removeEventListener('pageshow', onMQ); } catch {}
|
|
59
|
-
};
|
|
60
|
-
}
|
package/dist/starter/AGENTS.md
CHANGED
|
@@ -11,9 +11,9 @@ loader scripts or engine URLs.
|
|
|
11
11
|
|
|
12
12
|
## Before writing Weave, read the guide
|
|
13
13
|
|
|
14
|
-
- https://unpkg.com/oriverse-engine@0.1.
|
|
14
|
+
- https://unpkg.com/oriverse-engine@0.1.12/dist/GAME_AUTHORING.md — authoring patterns + 3 complete tested
|
|
15
15
|
example games (coin collector, dodge blocks, target range) to pattern-match from.
|
|
16
|
-
- https://unpkg.com/oriverse-engine@0.1.
|
|
16
|
+
- https://unpkg.com/oriverse-engine@0.1.12/dist/weave_documentation.txt — full language + API reference.
|
|
17
17
|
|
|
18
18
|
Key constraints: content must be fully procedural (primitive models `"cube"`,
|
|
19
19
|
`"sphere"`, ..., `#mesh`, `#texture` — no market/network assets); units are cm with Z
|
package/dist/starter/CLAUDE.md
CHANGED
|
@@ -11,9 +11,9 @@ loader scripts or engine URLs.
|
|
|
11
11
|
|
|
12
12
|
## Before writing Weave, read the guide
|
|
13
13
|
|
|
14
|
-
- https://unpkg.com/oriverse-engine@0.1.
|
|
14
|
+
- https://unpkg.com/oriverse-engine@0.1.12/dist/GAME_AUTHORING.md — authoring patterns + 3 complete tested
|
|
15
15
|
example games (coin collector, dodge blocks, target range) to pattern-match from.
|
|
16
|
-
- https://unpkg.com/oriverse-engine@0.1.
|
|
16
|
+
- https://unpkg.com/oriverse-engine@0.1.12/dist/weave_documentation.txt — full language + API reference.
|
|
17
17
|
|
|
18
18
|
Key constraints: content must be fully procedural (primitive models `"cube"`,
|
|
19
19
|
`"sphere"`, ..., `#mesh`, `#texture` — no market/network assets); units are cm with Z
|