spoint 0.1.29 → 0.1.31

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.
Files changed (2) hide show
  1. package/client/app.js +40 -22
  2. package/package.json +1 -1
package/client/app.js CHANGED
@@ -750,6 +750,10 @@ async function createPlayerVRM(id) {
750
750
  if (head) cam.setHeadBone(head)
751
751
  if (cam.getMode() === 'fps' && head) head.scale.set(0, 0, 0)
752
752
  }
753
+ if (!_vrmWarmupDone) {
754
+ _vrmWarmupDone = true
755
+ requestAnimationFrame(() => { renderer.compile(scene, camera); console.log('[shader] vrm warmup compile done') })
756
+ }
753
757
  } catch (e) { console.error('[vrm]', id, e.message) }
754
758
  return group
755
759
  }
@@ -1022,12 +1026,13 @@ const client = new PhysicsNetworkClient({
1022
1026
  const a = evaluateAppModule(d.code)
1023
1027
  if (a?.client) {
1024
1028
  appModules.set(d.app, a.client)
1029
+ _appModuleList = [...appModules.values()]
1025
1030
  if (a.client.setup) try { a.client.setup(engineCtx) } catch (e) { console.error('[app-setup]', d.app, e.message) }
1026
1031
  }
1027
1032
  },
1028
1033
  onAssetUpdate: () => {},
1029
1034
  onAppEvent: (payload) => {
1030
- for (const [, mod] of appModules) { if (mod.onEvent) try { mod.onEvent(payload, engineCtx) } catch (e) { console.error('[app-event]', e.message) } }
1035
+ for (let _i = 0; _i < _appModuleList.length; _i++) { const mod = _appModuleList[_i]; if (mod.onEvent) try { mod.onEvent(payload, engineCtx) } catch (e) { console.error('[app-event]', e.message) } }
1031
1036
  },
1032
1037
  onHotReload: () => { sessionStorage.setItem('cam', JSON.stringify(cam.save())); location.reload() },
1033
1038
  debug: false
@@ -1065,6 +1070,18 @@ let firstSnapshotReceived = false
1065
1070
  let lastShootState = false
1066
1071
  let lastHealth = 100
1067
1072
 
1073
+ let _shaderWarmupDone = false
1074
+ let _vrmWarmupDone = false
1075
+
1076
+ function warmupShaders() {
1077
+ if (_shaderWarmupDone) return
1078
+ _shaderWarmupDone = true
1079
+ const ext = renderer.extensions.get('KHR_parallel_shader_compile')
1080
+ if (ext) console.log('[shader] KHR_parallel_shader_compile active')
1081
+ renderer.compile(scene, camera)
1082
+ console.log('[shader] warmup compile done')
1083
+ }
1084
+
1068
1085
  function checkAllLoaded() {
1069
1086
  if (loadingScreenHidden) return
1070
1087
  if (!assetsLoaded) return
@@ -1072,7 +1089,7 @@ function checkAllLoaded() {
1072
1089
  if (!firstSnapshotReceived) return
1073
1090
  loadingMgr.setStage('INIT')
1074
1091
  loadingMgr.complete()
1075
- loadingScreen.hide().catch(() => {})
1092
+ loadingScreen.hide().then(() => requestAnimationFrame(warmupShaders)).catch(() => requestAnimationFrame(warmupShaders))
1076
1093
  loadingScreenHidden = true
1077
1094
  }
1078
1095
 
@@ -1098,7 +1115,7 @@ function initInputHandler() {
1098
1115
  setTimeout(() => {
1099
1116
  xrBaseReferenceSpace = renderer.xr.getReferenceSpace()
1100
1117
  if (!xrBaseReferenceSpace) return
1101
- const local = client.state?.players?.find(p => p.id === client.playerId)
1118
+ const local = playerStates.get(client.playerId)
1102
1119
  if (local?.position) {
1103
1120
  const headHeight = local.crouch ? 1.1 : 1.6
1104
1121
  const pos = { x: -local.position[0], y: -(local.position[1] + headHeight), z: -local.position[2] }
@@ -1227,7 +1244,7 @@ function startInputLoop() {
1227
1244
  inputHandler.pulse('right', 0.5, 100)
1228
1245
  }
1229
1246
  lastShootState = input.shoot
1230
- const local = client.state?.players?.find(p => p.id === client.playerId)
1247
+ const local = playerStates.get(client.playerId)
1231
1248
  if (local) {
1232
1249
  if (local.health < lastHealth) {
1233
1250
  inputHandler.pulse('left', 0.8, 200)
@@ -1235,7 +1252,7 @@ function startInputLoop() {
1235
1252
  }
1236
1253
  lastHealth = local.health
1237
1254
  }
1238
- for (const [, mod] of appModules) { if (mod.onInput) try { mod.onInput(input, engineCtx) } catch (e) { console.error('[app-input]', e.message) } }
1255
+ for (let _i = 0; _i < _appModuleList.length; _i++) { const mod = _appModuleList[_i]; if (mod.onInput) try { mod.onInput(input, engineCtx) } catch (e) { console.error('[app-input]', e.message) } }
1239
1256
  client.sendInput(input)
1240
1257
  }, 1000 / 60)
1241
1258
  }
@@ -1248,8 +1265,8 @@ document.addEventListener('pointerlockchange', () => {
1248
1265
  else document.removeEventListener('mousemove', cam.onMouseMove)
1249
1266
  })
1250
1267
  renderer.domElement.addEventListener('wheel', cam.onWheel, { passive: false })
1251
- renderer.domElement.addEventListener('mousedown', (e) => { for (const [, mod] of appModules) { if (mod.onMouseDown) try { mod.onMouseDown(e, engineCtx) } catch (ex) {} } })
1252
- renderer.domElement.addEventListener('mouseup', (e) => { for (const [, mod] of appModules) { if (mod.onMouseUp) try { mod.onMouseUp(e, engineCtx) } catch (ex) {} } })
1268
+ renderer.domElement.addEventListener('mousedown', (e) => { for (let _i = 0; _i < _appModuleList.length; _i++) { const mod = _appModuleList[_i]; if (mod.onMouseDown) try { mod.onMouseDown(e, engineCtx) } catch (ex) {} } })
1269
+ renderer.domElement.addEventListener('mouseup', (e) => { for (let _i = 0; _i < _appModuleList.length; _i++) { const mod = _appModuleList[_i]; if (mod.onMouseUp) try { mod.onMouseUp(e, engineCtx) } catch (ex) {} } })
1253
1270
  renderer.domElement.addEventListener('contextmenu', (e) => e.preventDefault())
1254
1271
  window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight) })
1255
1272
 
@@ -1290,7 +1307,7 @@ function loadQueuedModels() {
1290
1307
  try {
1291
1308
  const buffer = e.target.result
1292
1309
  gltfLoader.parse(buffer, '', (gltf) => {
1293
- const local = client.state?.players?.find(p => p.id === client.playerId)
1310
+ const local = playerStates.get(client.playerId)
1294
1311
  if (!local) return
1295
1312
  const sy = Math.sin(cam.yaw), cy = Math.cos(cam.yaw)
1296
1313
  const spawnDist = 1.0
@@ -1361,6 +1378,7 @@ document.addEventListener('drop', (e) => {
1361
1378
  })
1362
1379
 
1363
1380
  let smoothDt = 1 / 60
1381
+ let _appModuleList = []
1364
1382
  function animate(timestamp) {
1365
1383
  const now = timestamp || performance.now()
1366
1384
  const rawDt = Math.min((now - lastFrameTime) / 1000, 0.1)
@@ -1370,22 +1388,22 @@ function animate(timestamp) {
1370
1388
  fpsFrames++
1371
1389
  if (now - fpsLast >= 1000) { fpsDisplay = fpsFrames; fpsFrames = 0; fpsLast = now }
1372
1390
  const lerpFactor = 1.0 - Math.exp(-16.0 * frameDt)
1373
- for (const [id, target] of playerTargets) {
1391
+ playerTargets.forEach((target, id) => {
1374
1392
  const mesh = playerMeshes.get(id)
1375
- if (!mesh) continue
1393
+ if (!mesh) return
1376
1394
  const ps = playerStates.get(id)
1377
1395
  const vx = ps?.velocity?.[0] || 0, vy = ps?.velocity?.[1] || 0, vz = ps?.velocity?.[2] || 0
1378
1396
  const goalX = target.x + vx * frameDt, goalY = target.y + vy * frameDt, goalZ = target.z + vz * frameDt
1379
1397
  mesh.position.x += (goalX - mesh.position.x) * lerpFactor
1380
1398
  mesh.position.y += (goalY - mesh.position.y) * lerpFactor
1381
1399
  mesh.position.z += (goalZ - mesh.position.z) * lerpFactor
1382
- }
1383
- for (const [id, animator] of playerAnimators) {
1400
+ })
1401
+ playerAnimators.forEach((animator, id) => {
1384
1402
  const ps = playerStates.get(id)
1385
- if (!ps) continue
1403
+ if (!ps) return
1386
1404
  animator.update(frameDt, ps.velocity, ps.onGround, ps.health, ps._aiming || false, ps.crouch || 0)
1387
1405
  const mesh = playerMeshes.get(id)
1388
- if (!mesh) continue
1406
+ if (!mesh) return
1389
1407
  const vx = ps.velocity?.[0] || 0, vz = ps.velocity?.[2] || 0
1390
1408
  if (vx * vx + vz * vz > 0.25) mesh.userData.lastYaw = Math.atan2(vx, vz)
1391
1409
  if (mesh.userData.lastYaw !== undefined) {
@@ -1403,16 +1421,16 @@ function animate(timestamp) {
1403
1421
  }
1404
1422
  if (features?._headBone) features._headBone.rotation.x = -(ps.lookPitch || 0) * 0.6
1405
1423
  }
1406
- }
1407
- for (const [eid, mesh] of entityMeshes) {
1424
+ })
1425
+ entityMeshes.forEach((mesh) => {
1408
1426
  if (mesh.userData.spin) mesh.rotation.y += mesh.userData.spin * frameDt
1409
1427
  if (mesh.userData.hover) {
1410
1428
  mesh.userData.hoverTime = (mesh.userData.hoverTime || 0) + frameDt
1411
1429
  const child = mesh.children[0]
1412
1430
  if (child) child.position.y = Math.sin(mesh.userData.hoverTime * 2) * mesh.userData.hover
1413
1431
  }
1414
- }
1415
- for (const [, mod] of appModules) { if (mod.onFrame) try { mod.onFrame(frameDt, engineCtx) } catch (e) {} }
1432
+ })
1433
+ for (let _i = 0; _i < _appModuleList.length; _i++) { const mod = _appModuleList[_i]; if (mod.onFrame) try { mod.onFrame(frameDt, engineCtx) } catch (e) {} }
1416
1434
  if (engineCtx.facial) engineCtx.facial.update(frameDt)
1417
1435
  uiTimer += frameDt
1418
1436
  if (latestState && uiTimer >= 0.25) { uiTimer = 0; renderAppUI(latestState) }
@@ -1442,15 +1460,15 @@ function animate(timestamp) {
1442
1460
  const speed = Math.sqrt(local.velocity[0] ** 2 + local.velocity[2] ** 2)
1443
1461
  isMoving = speed > 0.5
1444
1462
  }
1445
- updateVignette(frameDt, isMoving)
1463
+ updateVignette(frameDt, isMoving)
1446
1464
 
1447
1465
  if (arEnabled) {
1448
1466
  const xrFrame = renderer.xr.getFrame()
1449
1467
  if (xrFrame) {
1450
1468
  arControls.update(xrFrame, camera, scene)
1451
- const local = client.state?.players?.find(p => p.id === client.playerId)
1452
- if (local?.position && !arControls.anchorPlaced) {
1453
- arControls.setInitialFPSPosition(local.position, cam.yaw)
1469
+ const arLocal = playerStates.get(client.playerId)
1470
+ if (arLocal?.position && !arControls.anchorPlaced) {
1471
+ arControls.setInitialFPSPosition(arLocal.position, cam.yaw)
1454
1472
  }
1455
1473
  }
1456
1474
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spoint",
3
- "version": "0.1.29",
3
+ "version": "0.1.31",
4
4
  "description": "Physics and netcode SDK for multiplayer game servers",
5
5
  "type": "module",
6
6
  "main": "src/index.js",