spoint 0.1.492 → 0.1.493

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 CHANGED
@@ -165,6 +165,16 @@ npm run bots
165
165
 
166
166
  Env vars: `BOT_COUNT`, `BOT_DURATION`, `BOT_HZ`, `BOT_URL`
167
167
 
168
+ ## Documentation
169
+
170
+ - **Getting Started**: `docs/getting-started.md` — Full tutorial, world/app creation, API reference
171
+ - **Quick Reference**: `docs/quick-reference.md` — Cheatsheet for config, physics, client, network messages
172
+ - **Architecture**: `docs/architecture-decisions.md`
173
+ - **Rendering**: `docs/rendering.md`
174
+ - **Editor**: `docs/editor-composing.md`
175
+ - **Publishing**: `docs/publish.md`
176
+ - **Anticheat**: `docs/anticheat.md`
177
+
168
178
  ## License
169
179
 
170
180
  MIT
@@ -0,0 +1,267 @@
1
+ export default {
2
+ server: {
3
+ setup(ctx) {
4
+ const roomSize = 30
5
+ const wallHeight = 8
6
+ const wallThickness = 0.5
7
+
8
+ // Floor
9
+ ctx.physics.addColliderFromConfig({
10
+ type: 'box',
11
+ size: [roomSize / 2, wallThickness / 2, roomSize / 2],
12
+ position: [0, -wallThickness / 2, 0],
13
+ mass: 0,
14
+ dynamic: false
15
+ })
16
+
17
+ // Ceiling
18
+ ctx.physics.addColliderFromConfig({
19
+ type: 'box',
20
+ size: [roomSize / 2, wallThickness / 2, roomSize / 2],
21
+ position: [0, wallHeight + wallThickness / 2, 0],
22
+ mass: 0,
23
+ dynamic: false
24
+ })
25
+
26
+ // Walls - back (negative Z)
27
+ ctx.physics.addColliderFromConfig({
28
+ type: 'box',
29
+ size: [roomSize / 2, wallHeight / 2, wallThickness / 2],
30
+ position: [0, wallHeight / 2, -roomSize / 2],
31
+ mass: 0,
32
+ dynamic: false
33
+ })
34
+
35
+ // Walls - front (positive Z)
36
+ ctx.physics.addColliderFromConfig({
37
+ type: 'box',
38
+ size: [roomSize / 2, wallHeight / 2, wallThickness / 2],
39
+ position: [0, wallHeight / 2, roomSize / 2],
40
+ mass: 0,
41
+ dynamic: false
42
+ })
43
+
44
+ // Walls - left (negative X)
45
+ ctx.physics.addColliderFromConfig({
46
+ type: 'box',
47
+ size: [wallThickness / 2, wallHeight / 2, roomSize / 2],
48
+ position: [-roomSize / 2, wallHeight / 2, 0],
49
+ mass: 0,
50
+ dynamic: false
51
+ })
52
+
53
+ // Walls - right (positive X)
54
+ ctx.physics.addColliderFromConfig({
55
+ type: 'box',
56
+ size: [wallThickness / 2, wallHeight / 2, roomSize / 2],
57
+ position: [roomSize / 2, wallHeight / 2, 0],
58
+ mass: 0,
59
+ dynamic: false
60
+ })
61
+
62
+ // Store room dimensions for client rendering
63
+ ctx.state.roomSize = roomSize
64
+ ctx.state.wallHeight = wallHeight
65
+ ctx.state.wallThickness = wallThickness
66
+ ctx.state.gridSize = 2
67
+ }
68
+ },
69
+ client: {
70
+ setup(engine) {
71
+ // Create the white room with grid lines
72
+ this.createConstructRoom(engine)
73
+ },
74
+ render(ctx) {
75
+ return {
76
+ position: [0, 0, 0],
77
+ rotation: [0, 0, 0, 1],
78
+ custom: {
79
+ // Empty - we create the room in setup
80
+ }
81
+ }
82
+ },
83
+ createConstructRoom(engine) {
84
+ const { THREE, scene } = engine
85
+ const roomSize = 30
86
+ const wallHeight = 8
87
+ const wallThickness = 0.5
88
+ const gridSize = 2
89
+
90
+ // White material with slight emissive glow
91
+ const whiteMaterial = new THREE.MeshStandardMaterial({
92
+ color: 0xffffff,
93
+ roughness: 0.1,
94
+ metalness: 0,
95
+ emissive: 0x222222,
96
+ emissiveIntensity: 0.3,
97
+ side: THREE.DoubleSide
98
+ })
99
+
100
+ // Grid line material - subtle gray
101
+ const gridMaterial = new THREE.MeshStandardMaterial({
102
+ color: 0x888888,
103
+ roughness: 0.3,
104
+ metalness: 0,
105
+ emissive: 0x111111,
106
+ emissiveIntensity: 0.1,
107
+ side: THREE.DoubleSide,
108
+ transparent: true,
109
+ opacity: 0.4
110
+ })
111
+
112
+ // Bright grid line material for main axes
113
+ const axisMaterial = new THREE.MeshStandardMaterial({
114
+ color: 0xcccccc,
115
+ roughness: 0.2,
116
+ metalness: 0,
117
+ emissive: 0x333333,
118
+ emissiveIntensity: 0.2,
119
+ side: THREE.DoubleSide
120
+ })
121
+
122
+ // Floor
123
+ const floorGeo = new THREE.BoxGeometry(roomSize, wallThickness, roomSize)
124
+ const floor = new THREE.Mesh(floorGeo, whiteMaterial)
125
+ floor.position.set(0, -wallThickness / 2, 0)
126
+ floor.receiveShadow = true
127
+ scene.add(floor)
128
+
129
+ // Ceiling
130
+ const ceilGeo = new THREE.BoxGeometry(roomSize, wallThickness, roomSize)
131
+ const ceil = new THREE.Mesh(ceilGeo, whiteMaterial)
132
+ ceil.position.set(0, wallHeight + wallThickness / 2, 0)
133
+ scene.add(ceil)
134
+
135
+ // Walls
136
+ const wallGeo = new THREE.BoxGeometry(roomSize, wallHeight, wallThickness)
137
+ const sideWallGeo = new THREE.BoxGeometry(wallThickness, wallHeight, roomSize)
138
+
139
+ // Back wall (negative Z)
140
+ const backWall = new THREE.Mesh(wallGeo, whiteMaterial)
141
+ backWall.position.set(0, wallHeight / 2, -roomSize / 2)
142
+ backWall.receiveShadow = true
143
+ scene.add(backWall)
144
+
145
+ // Front wall (positive Z)
146
+ const frontWall = new THREE.Mesh(wallGeo, whiteMaterial)
147
+ frontWall.position.set(0, wallHeight / 2, roomSize / 2)
148
+ frontWall.receiveShadow = true
149
+ scene.add(frontWall)
150
+
151
+ // Left wall (negative X)
152
+ const leftWall = new THREE.Mesh(sideWallGeo, whiteMaterial)
153
+ leftWall.position.set(-roomSize / 2, wallHeight / 2, 0)
154
+ leftWall.receiveShadow = true
155
+ scene.add(leftWall)
156
+
157
+ // Right wall (positive X)
158
+ const rightWall = new THREE.Mesh(sideWallGeo, whiteMaterial)
159
+ rightWall.position.set(roomSize / 2, wallHeight / 2, 0)
160
+ rightWall.receiveShadow = true
161
+ scene.add(rightWall)
162
+
163
+ // Grid lines on floor
164
+ const lineThickness = 0.05
165
+ const lineGeo = new THREE.BoxGeometry(roomSize, lineThickness, lineThickness)
166
+ const crossLineGeo = new THREE.BoxGeometry(lineThickness, lineThickness, roomSize)
167
+
168
+ // Floor grid
169
+ for (let i = -roomSize / 2; i <= roomSize / 2; i += gridSize) {
170
+ // X-axis lines
171
+ const lineX = new THREE.Mesh(lineGeo, i === 0 ? axisMaterial : gridMaterial)
172
+ lineX.position.set(0, lineThickness / 2, i)
173
+ scene.add(lineX)
174
+
175
+ // Z-axis lines
176
+ const lineZ = new THREE.Mesh(crossLineGeo, i === 0 ? axisMaterial : gridMaterial)
177
+ lineZ.position.set(i, lineThickness / 2, 0)
178
+ scene.add(lineZ)
179
+ }
180
+
181
+ // Wall grids - back wall
182
+ const wallLineGeoH = new THREE.BoxGeometry(roomSize, lineThickness, lineThickness)
183
+ const wallLineGeoV = new THREE.BoxGeometry(lineThickness, wallHeight, lineThickness)
184
+
185
+ for (let i = -roomSize / 2; i <= roomSize / 2; i += gridSize) {
186
+ // Horizontal lines
187
+ const hLine = new THREE.Mesh(wallLineGeoH, i === 0 ? axisMaterial : gridMaterial)
188
+ hLine.position.set(0, -wallHeight / 2 + i + wallHeight / 2, -roomSize / 2 + wallThickness / 2 + lineThickness)
189
+ scene.add(hLine)
190
+
191
+ // Vertical lines
192
+ const vLine = new THREE.Mesh(wallLineGeoV, i === 0 ? axisMaterial : gridMaterial)
193
+ vLine.position.set(-roomSize / 2 + i, 0, -roomSize / 2 + wallThickness / 2 + lineThickness)
194
+ scene.add(vLine)
195
+ }
196
+
197
+ // Front wall grid
198
+ for (let i = -roomSize / 2; i <= roomSize / 2; i += gridSize) {
199
+ const hLine = new THREE.Mesh(wallLineGeoH, i === 0 ? axisMaterial : gridMaterial)
200
+ hLine.position.set(0, -wallHeight / 2 + i + wallHeight / 2, roomSize / 2 - wallThickness / 2 - lineThickness)
201
+ scene.add(hLine)
202
+
203
+ const vLine = new THREE.Mesh(wallLineGeoV, i === 0 ? axisMaterial : gridMaterial)
204
+ vLine.position.set(-roomSize / 2 + i, 0, roomSize / 2 - wallThickness / 2 - lineThickness)
205
+ scene.add(vLine)
206
+ }
207
+
208
+ // Left wall grid
209
+ const sideWallLineGeoH = new THREE.BoxGeometry(lineThickness, lineThickness, roomSize)
210
+ const sideWallLineGeoV = new THREE.BoxGeometry(lineThickness, wallHeight, lineThickness)
211
+
212
+ for (let i = -roomSize / 2; i <= roomSize / 2; i += gridSize) {
213
+ const hLine = new THREE.Mesh(sideWallLineGeoH, i === 0 ? axisMaterial : gridMaterial)
214
+ hLine.position.set(-roomSize / 2 + wallThickness / 2 + lineThickness, -wallHeight / 2 + i + wallHeight / 2, 0)
215
+ scene.add(hLine)
216
+
217
+ const vLine = new THREE.Mesh(sideWallLineGeoV, i === 0 ? axisMaterial : gridMaterial)
218
+ vLine.position.set(-roomSize / 2 + wallThickness / 2 + lineThickness, 0, -roomSize / 2 + i)
219
+ scene.add(vLine)
220
+ }
221
+
222
+ // Right wall grid
223
+ for (let i = -roomSize / 2; i <= roomSize / 2; i += gridSize) {
224
+ const hLine = new THREE.Mesh(sideWallLineGeoH, i === 0 ? axisMaterial : gridMaterial)
225
+ hLine.position.set(roomSize / 2 - wallThickness / 2 - lineThickness, -wallHeight / 2 + i + wallHeight / 2, 0)
226
+ scene.add(hLine)
227
+
228
+ const vLine = new THREE.Mesh(sideWallLineGeoV, i === 0 ? axisMaterial : gridMaterial)
229
+ vLine.position.set(roomSize / 2 - wallThickness / 2 - lineThickness, 0, -roomSize / 2 + i)
230
+ scene.add(vLine)
231
+ }
232
+
233
+ // Ceiling grid
234
+ for (let i = -roomSize / 2; i <= roomSize / 2; i += gridSize) {
235
+ const lineX = new THREE.Mesh(lineGeo, i === 0 ? axisMaterial : gridMaterial)
236
+ lineX.position.set(0, wallHeight + wallThickness - lineThickness / 2, i)
237
+ scene.add(lineX)
238
+
239
+ const lineZ = new THREE.Mesh(crossLineGeo, i === 0 ? axisMaterial : gridMaterial)
240
+ lineZ.position.set(i, wallHeight + wallThickness - lineThickness / 2, 0)
241
+ scene.add(lineZ)
242
+ }
243
+
244
+ // Add subtle point lights for that construct glow
245
+ const centerLight = new THREE.PointLight(0xffffff, 2, 50)
246
+ centerLight.position.set(0, wallHeight / 2, 0)
247
+ scene.add(centerLight)
248
+
249
+ // Corner accent lights
250
+ const cornerPositions = [
251
+ [-roomSize / 2 + 2, wallHeight - 2, -roomSize / 2 + 2],
252
+ [roomSize / 2 - 2, wallHeight - 2, -roomSize / 2 + 2],
253
+ [-roomSize / 2 + 2, wallHeight - 2, roomSize / 2 - 2],
254
+ [roomSize / 2 - 2, wallHeight - 2, roomSize / 2 - 2]
255
+ ]
256
+
257
+ cornerPositions.forEach(pos => {
258
+ const light = new THREE.PointLight(0xffffff, 0.5, 15)
259
+ light.position.set(...pos)
260
+ scene.add(light)
261
+ })
262
+
263
+ // Store reference for cleanup if needed
264
+ this.constructRoom = { floor, ceil, backWall, frontWall, leftWall, rightWall }
265
+ }
266
+ }
267
+ }
@@ -0,0 +1,96 @@
1
+ const MATRIX_CONSTRUCT = {
2
+ enabled: false,
3
+ anchorDir: [0, 1, 0],
4
+ radius: 1000,
5
+ reliefScale: 0,
6
+ maxLevel: 0,
7
+ offsetY: 0,
8
+ center: [0, 0],
9
+ physics: { extent: 1, resolution: 1 },
10
+ seed: 0,
11
+ timeOfDay: { serverAuthoritative: true, dayLengthSec: 600, startFraction: 0.5 },
12
+ weather: { serverAuthoritative: true, type: 'clear', intensity: 0, particleCount: 0 },
13
+ vegetation: { enabled: false }
14
+ }
15
+
16
+ export default {
17
+ port: 3001,
18
+ tickRate: 64,
19
+ entityTickRate: 15,
20
+ gravity: [0, -9.81, 0],
21
+ relevanceRadius: 100,
22
+ physicsRadius: 50,
23
+ physicsBodyBudget: 128,
24
+ movement: {
25
+ maxSpeed: 7.0,
26
+ sprintSpeed: 12.0,
27
+ groundAccel: 300.0,
28
+ airAccel: 30.0,
29
+ airMaxSpeed: 0.15,
30
+ airSpeedCap: 16.0,
31
+ friction: 5.0,
32
+ stopSpeed: 1.0,
33
+ jumpImpulse: 5.5,
34
+ collisionRestitution: 0.2,
35
+ collisionDamping: 0.25
36
+ },
37
+ player: {
38
+ health: 100,
39
+ capsuleRadius: 0.28,
40
+ capsuleHalfHeight: 0.63,
41
+ crouchHalfHeight: 0.315,
42
+ mass: 120,
43
+ modelScale: 1.323,
44
+ feetOffset: 0.212
45
+ },
46
+ scene: {
47
+ skyColor: 0xffffff,
48
+ fogColor: 0xffffff,
49
+ fogNear: 500,
50
+ fogFar: 1000,
51
+ ambientColor: 0xffffff,
52
+ ambientIntensity: 0.8,
53
+ sunColor: 0xffffff,
54
+ sunIntensity: 0.5,
55
+ sunPosition: [0, 100, 0],
56
+ fillColor: 0xffffff,
57
+ fillIntensity: 0.5,
58
+ fillPosition: [0, 50, 0],
59
+ shadowMapSize: 1024,
60
+ shadowBias: 0.001,
61
+ shadowNormalBias: 0.1
62
+ },
63
+ camera: {
64
+ fov: 70,
65
+ shoulderOffset: 0.35,
66
+ shoulderOffsets: [0, 0.55, 0.35, 0.1, 0.0],
67
+ headHeight: 1.85,
68
+ zoomStages: [0, 2, 4, 8, 18],
69
+ defaultZoomIndex: 2,
70
+ followSpeed: 12.0,
71
+ snapSpeed: 30.0,
72
+ mouseSensitivity: 0.002,
73
+ pitchRange: [-1.4, 1.4]
74
+ },
75
+ animation: {
76
+ mixerTimeScale: 1.3,
77
+ walkTimeScale: 2.4,
78
+ jogTimeScale: 1.9,
79
+ sprintTimeScale: 1.0,
80
+ fadeTime: 0.15
81
+ },
82
+ trustedApps: ['matrix-construct-room', 'tps-game'],
83
+ placeableApps: [],
84
+ terrain: MATRIX_CONSTRUCT,
85
+ entities: [
86
+ { id: 'terrain', app: 'terrain', config: MATRIX_CONSTRUCT },
87
+ { id: 'matrix-room', app: 'matrix-construct-room', position: [0, 0, 0] },
88
+ { id: 'tps-game', position: [0, 0, 0], app: 'tps-game' }
89
+ ],
90
+ spawnPoint: [0, 2, 0],
91
+ playerModel: './apps/tps-game/cleetus.vrm',
92
+ iceServers: [
93
+ { urls: 'stun:stun.l.google.com:19302' },
94
+ { urls: 'turn:openrelay.metered.ca:443?transport=tcp', username: 'openrelayproject', credential: 'openrelayproject' }
95
+ ]
96
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spoint",
3
- "version": "0.1.492",
3
+ "version": "0.1.493",
4
4
  "description": "Physics and netcode SDK for multiplayer game servers",
5
5
  "type": "module",
6
6
  "workspaces": [