spoint 0.1.668 → 0.1.670

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.
@@ -0,0 +1,49 @@
1
+ // Boot-diagnostics helpers for app.js: shadow-cascade-count resolution (device-aware default the
2
+ // shadow pipeline registry itself has no knowledge of) and the single boot-failure overlay renderer,
3
+ // reused by every early-boot catch site (WebGL2-context-creation failure, window.onerror,
4
+ // unhandledrejection). Split out as the only two functions in app.js's top-level boot script with no
5
+ // interleaved side-effecting script logic immediately around them -- app.js itself is a flat top-to-
6
+ // bottom boot sequence, not a factory, so most of it cannot be safely cut without risking a module-eval
7
+ // ordering regression; these two are genuinely self-contained.
8
+
9
+ import { QualityPresets } from './core/QualityPresets.js'
10
+
11
+ function _shadowCascadeCountForBoot(deviceInfo) {
12
+ const explicit = typeof window !== 'undefined' ? window.__shadowCascades : undefined
13
+ if (Number.isFinite(explicit)) return Math.max(1, Math.min(3, Math.round(explicit)))
14
+ const presetName = QualityPresets.getPersisted() || QualityPresets.chooseInitialPreset(deviceInfo)
15
+ const byTier = { Low: 1, Medium: 1, High: 2, Ultra: 3 }
16
+ return byTier[presetName] || 1
17
+ }
18
+
19
+ // Single boot-failure overlay renderer, reused by both the WebGL2-specific catch below AND the
20
+ // generic window.onerror/unhandledrejection listeners -- one visual style for "the client failed
21
+ // to boot" regardless of WHERE in the boot sequence it failed, instead of a blank canvas / silently
22
+ // stuck loading screen. Idempotent (a data-flag guards double-render across multiple errors racing
23
+ // in, e.g. a synchronous throw immediately followed by a rejected promise from the same root cause).
24
+ let _bootFailureShown = false
25
+ function _showBootFailureOverlay(title, detail) {
26
+ if (_bootFailureShown) return
27
+ _bootFailureShown = true
28
+ try {
29
+ const o = document.createElement('div')
30
+ o.setAttribute('role', 'alert')
31
+ o.style.cssText = 'position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center;padding:24px;background:#0b0e14;color:#e6e6e6;font:16px/1.5 system-ui,sans-serif;text-align:center'
32
+ const titleEl = document.createElement('div')
33
+ titleEl.style.cssText = 'font-size:22px;font-weight:600;margin-bottom:12px'
34
+ titleEl.textContent = title
35
+ const detailEl = document.createElement('div')
36
+ detailEl.style.cssText = 'max-width:640px;white-space:pre-wrap;word-break:break-word;font:13px/1.5 ui-monospace,monospace;opacity:0.85;margin-top:8px;text-align:left'
37
+ detailEl.textContent = detail || ''
38
+ const wrap = document.createElement('div')
39
+ wrap.style.cssText = 'max-width:640px'
40
+ wrap.appendChild(titleEl)
41
+ wrap.appendChild(detailEl)
42
+ o.appendChild(wrap)
43
+ document.body.appendChild(o)
44
+ const ls = document.getElementById('loading-screen') || document.querySelector('.loading-screen')
45
+ if (ls) ls.style.display = 'none'
46
+ } catch (_) { /* overlay itself must never throw during an already-failing boot */ }
47
+ }
48
+
49
+ export { _shadowCascadeCountForBoot, _showBootFailureOverlay }
package/client/app.js CHANGED
@@ -62,6 +62,7 @@ import { getSharedStreamingScheduler } from './core/StreamingScheduler.js'
62
62
  import { createPlacementScheduler } from './core/PlacementScheduler.js'
63
63
  import { getSharedCacheRevalidationSweep } from './core/CacheRevalidationSweep.js'
64
64
  import { QualityPresets, installQualityPresets } from './core/QualityPresets.js'
65
+ import { _shadowCascadeCountForBoot, _showBootFailureOverlay } from './BootFailureOverlay.js'
65
66
  import { createSettingsMenu } from './hud/SettingsMenu.js'
66
67
  import { createPauseMenu } from './hud/PauseMenu.js'
67
68
  import { createEmoteWheel } from './hud/EmoteWheel.js'
@@ -118,48 +119,6 @@ if (typeof window !== 'undefined') window.__deviceInfo = _deviceInfoEarly
118
119
  // Device-tier default for ShadowPipeline's cascade count (shadowCascades RenderControls knob, doc'd
119
120
  // in RenderControls.js: Low/Medium=1, High=2, Ultra=3). RenderControls.get() itself only ever returns
120
121
  // an explicit window.__shadowCascades override or the registry's static default (1) -- it has no
121
- // device-awareness of its own -- so a real tier default has to be resolved here, once, the same way
122
- // QualityPresets.autoApplyPersisted resolves a tier below (persisted user choice wins, else the same
123
- // chooseInitialPreset heuristic), and passed into createShadowPipeline explicitly. window.__shadowCascades
124
- // (if pre-set before this script runs, e.g. by a test harness) always wins over both.
125
- function _shadowCascadeCountForBoot(deviceInfo) {
126
- const explicit = typeof window !== 'undefined' ? window.__shadowCascades : undefined
127
- if (Number.isFinite(explicit)) return Math.max(1, Math.min(3, Math.round(explicit)))
128
- const presetName = QualityPresets.getPersisted() || QualityPresets.chooseInitialPreset(deviceInfo)
129
- const byTier = { Low: 1, Medium: 1, High: 2, Ultra: 3 }
130
- return byTier[presetName] || 1
131
- }
132
-
133
- // Single boot-failure overlay renderer, reused by both the WebGL2-specific catch below AND the
134
- // generic window.onerror/unhandledrejection listeners -- one visual style for "the client failed
135
- // to boot" regardless of WHERE in the boot sequence it failed, instead of a blank canvas / silently
136
- // stuck loading screen. Idempotent (a data-flag guards double-render across multiple errors racing
137
- // in, e.g. a synchronous throw immediately followed by a rejected promise from the same root cause).
138
- let _bootFailureShown = false
139
- function _showBootFailureOverlay(title, detail) {
140
- if (_bootFailureShown) return
141
- _bootFailureShown = true
142
- try {
143
- const o = document.createElement('div')
144
- o.setAttribute('role', 'alert')
145
- o.style.cssText = 'position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center;padding:24px;background:#0b0e14;color:#e6e6e6;font:16px/1.5 system-ui,sans-serif;text-align:center'
146
- const titleEl = document.createElement('div')
147
- titleEl.style.cssText = 'font-size:22px;font-weight:600;margin-bottom:12px'
148
- titleEl.textContent = title
149
- const detailEl = document.createElement('div')
150
- detailEl.style.cssText = 'max-width:640px;white-space:pre-wrap;word-break:break-word;font:13px/1.5 ui-monospace,monospace;opacity:0.85;margin-top:8px;text-align:left'
151
- detailEl.textContent = detail || ''
152
- const wrap = document.createElement('div')
153
- wrap.style.cssText = 'max-width:640px'
154
- wrap.appendChild(titleEl)
155
- wrap.appendChild(detailEl)
156
- o.appendChild(wrap)
157
- document.body.appendChild(o)
158
- const ls = document.getElementById('loading-screen') || document.querySelector('.loading-screen')
159
- if (ls) ls.style.display = 'none'
160
- } catch (_) { /* overlay itself must never throw during an already-failing boot */ }
161
- }
162
-
163
122
  // Generic boot-failure safety net: ANY uncaught error or unhandled promise rejection during client
164
123
  // boot (not just the WebGL2-context-creation case caught explicitly below) renders the same overlay
165
124
  // style with the real error message/stack, instead of leaving the user staring at a stuck loading
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spoint",
3
- "version": "0.1.668",
3
+ "version": "0.1.670",
4
4
  "description": "Physics and netcode SDK for multiplayer game servers",
5
5
  "type": "module",
6
6
  "workspaces": [