spoint 0.1.43 → 0.1.45

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.
@@ -79,6 +79,8 @@ export class LoadingManager extends EventTarget {
79
79
  const response = await fetch(url)
80
80
  if (!response.ok) throw new Error(`HTTP ${response.status}`)
81
81
  const contentLength = parseInt(response.headers.get('content-length') || '0', 10)
82
+ const isGzip = (response.headers.get('content-encoding') || '').includes('gzip')
83
+ const useTotal = contentLength > 0 && !isGzip
82
84
  const reader = response.body.getReader()
83
85
  const chunks = []
84
86
  let receivedLength = 0
@@ -88,7 +90,7 @@ export class LoadingManager extends EventTarget {
88
90
  if (done) break
89
91
  chunks.push(value)
90
92
  receivedLength += value.length
91
- if (contentLength > 0) {
93
+ if (useTotal) {
92
94
  this.updateProgress(receivedLength, contentLength)
93
95
  }
94
96
  }
@@ -123,21 +123,23 @@ function normalizeClips(gltf, vrmVersion, vrmHumanoid) {
123
123
  return clips
124
124
  }
125
125
 
126
- let _animLibCache = null
127
- let _animLibPromise = null
126
+ let _gltfPromise = null
127
+ let _normalizedCache = null
128
+
129
+ export function preloadAnimationLibrary() {
130
+ if (_gltfPromise) return _gltfPromise
131
+ _gltfPromise = new GLTFLoader().loadAsync('/anim-lib.glb')
132
+ return _gltfPromise
133
+ }
128
134
 
129
135
  export async function loadAnimationLibrary(vrmVersion, vrmHumanoid) {
130
- if (_animLibCache) return _animLibCache
131
- if (_animLibPromise) return _animLibPromise
132
- _animLibPromise = (async () => {
133
- const loader = new GLTFLoader()
134
- const gltf = await loader.loadAsync('/anim-lib.glb')
135
- const normalizedClips = normalizeClips(gltf, vrmVersion || '1', vrmHumanoid)
136
- console.log(`[anim] Loaded animation library (${normalizedClips.size} clips):`, [...normalizedClips.keys()])
137
- _animLibCache = { normalizedClips }
138
- return _animLibCache
139
- })()
140
- return _animLibPromise
136
+ if (_normalizedCache) return _normalizedCache
137
+ const gltf = await preloadAnimationLibrary()
138
+ if (_normalizedCache) return _normalizedCache
139
+ const normalizedClips = normalizeClips(gltf, vrmVersion || '1', vrmHumanoid)
140
+ console.log(`[anim] Loaded animation library (${normalizedClips.size} clips):`, [...normalizedClips.keys()])
141
+ _normalizedCache = { normalizedClips }
142
+ return _normalizedCache
141
143
  }
142
144
 
143
145
  export function createPlayerAnimator(vrm, allClips, vrmVersion, animConfig = {}) {
package/client/app.js CHANGED
@@ -9,7 +9,7 @@ import { VRMLoaderPlugin, VRMUtils } from '@pixiv/three-vrm'
9
9
  import { PhysicsNetworkClient, InputHandler, MSG } from '/src/index.client.js'
10
10
  import { createElement, applyDiff } from 'webjsx'
11
11
  import { createCameraController } from './camera.js'
12
- import { loadAnimationLibrary, createPlayerAnimator } from './animation.js'
12
+ import { loadAnimationLibrary, preloadAnimationLibrary, createPlayerAnimator } from './animation.js'
13
13
  import { initFacialSystem } from './facial-animation.js'
14
14
  import { VRButton } from 'three/addons/webxr/VRButton.js'
15
15
  import { XRControllerModelFactory } from 'three/addons/webxr/XRControllerModelFactory.js'
@@ -713,16 +713,15 @@ function detectVrmVersion(buffer) {
713
713
 
714
714
  function initAssets(playerModelUrl) {
715
715
  loadingMgr.setStage('DOWNLOAD')
716
- const animLibPromise = loadAnimationLibrary('1', null)
716
+ preloadAnimationLibrary()
717
717
  assetsReady = loadingMgr.fetchWithProgress(playerModelUrl).then(async b => {
718
718
  vrmBuffer = b
719
719
  loadingMgr.setStage('PROCESS')
720
- animAssets = await animLibPromise
720
+ animAssets = await loadAnimationLibrary(detectVrmVersion(b), null)
721
721
  assetsLoaded = true
722
722
  checkAllLoaded()
723
723
  }).catch(err => {
724
724
  console.warn('[assets] player model unavailable:', err.message)
725
- animLibPromise.then(r => { animAssets = r }).catch(() => {})
726
725
  assetsLoaded = true
727
726
  checkAllLoaded()
728
727
  })
@@ -978,8 +977,9 @@ function loadEntityModel(entityId, entityState) {
978
977
  fitShadowFrustum()
979
978
  pendingLoads.delete(entityId)
980
979
  if (!environmentLoaded) { environmentLoaded = true; checkAllLoaded() }
980
+ if (firstSnapshotEntityPending.has(entityId)) { firstSnapshotEntityPending.delete(entityId); if (firstSnapshotEntityPending.size === 0) checkAllLoaded() }
981
981
  if (loadingScreenHidden) renderer.compileAsync(scene, camera).catch(() => renderer.compile(scene, camera))
982
- }, (progress) => { if (progress.total > 0) console.log('[gltf]', url, Math.round(progress.loaded / progress.total * 100) + '%') }, (err) => { console.error('[gltf]', url, err); pendingLoads.delete(entityId) })
982
+ }, (progress) => { if (progress.total > 0) console.log('[gltf]', url, Math.round(Math.min(progress.loaded, progress.total) / progress.total * 100) + '%') }, (err) => { console.error('[gltf]', url, err); pendingLoads.delete(entityId); if (firstSnapshotEntityPending.has(entityId)) { firstSnapshotEntityPending.delete(entityId); if (firstSnapshotEntityPending.size === 0) checkAllLoaded() } })
983
983
  }
984
984
 
985
985
  function renderAppUI(state) {
@@ -1027,7 +1027,13 @@ const client = new PhysicsNetworkClient({
1027
1027
  }
1028
1028
  rebuildEntityHierarchy(smoothState.entities)
1029
1029
  latestState = state
1030
- if (!firstSnapshotReceived) { firstSnapshotReceived = true; checkAllLoaded() }
1030
+ if (!firstSnapshotReceived) {
1031
+ firstSnapshotReceived = true
1032
+ for (const e of smoothState.entities) {
1033
+ if (e.model && !entityMeshes.has(e.id)) firstSnapshotEntityPending.add(e.id)
1034
+ }
1035
+ checkAllLoaded()
1036
+ }
1031
1037
  },
1032
1038
  onPlayerJoined: (id) => { if (!playerMeshes.has(id)) createPlayerVRM(id) },
1033
1039
  onPlayerLeft: (id) => removePlayerMesh(id),
@@ -1092,6 +1098,7 @@ let inputLoopId = null
1092
1098
  let loadingScreenHidden = false
1093
1099
  let environmentLoaded = false
1094
1100
  let firstSnapshotReceived = false
1101
+ const firstSnapshotEntityPending = new Set()
1095
1102
  let lastShootState = false
1096
1103
  let lastHealth = 100
1097
1104
 
@@ -1124,6 +1131,7 @@ function checkAllLoaded() {
1124
1131
  if (!assetsLoaded) return
1125
1132
  if (!environmentLoaded) return
1126
1133
  if (!firstSnapshotReceived) return
1134
+ if (firstSnapshotEntityPending.size > 0) return
1127
1135
  loadingMgr.setStage('INIT')
1128
1136
  loadingMgr.complete()
1129
1137
  loadingScreenHidden = true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spoint",
3
- "version": "0.1.43",
3
+ "version": "0.1.45",
4
4
  "description": "Physics and netcode SDK for multiplayer game servers",
5
5
  "type": "module",
6
6
  "main": "src/index.js",