hytopia 0.1.71 → 0.1.72

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,506 @@
1
+ import {
2
+ Audio,
3
+ BlockType,
4
+ Collider,
5
+ ColliderShape,
6
+ Entity,
7
+ GameServer,
8
+ RigidBodyType,
9
+ startServer,
10
+ Player,
11
+ PlayerEntity,
12
+ SceneUI,
13
+ World,
14
+ } from 'hytopia';
15
+
16
+ import worldMap from './assets/map.json';
17
+
18
+ enum GameWallDirection {
19
+ NORTH = 'NORTH',
20
+ SOUTH = 'SOUTH',
21
+ WEST = 'WEST',
22
+ EAST = 'EAST',
23
+ }
24
+
25
+ const GAME_LEVEL_DURATION_SECONDS = 10;
26
+ const GAME_START_POSITION = { x: 1, y: 25, z: 1 };
27
+ const GAME_START_DELAY_SECONDS = 3;
28
+ const GAME_WALL_DESPAWN_DISTANCE = 18;
29
+ const GAME_WALL_SPAWN_POSITIONS = {
30
+ [GameWallDirection.NORTH]: { x: 1, y: 20, z: -10 }, // North (x width)
31
+ [GameWallDirection.SOUTH]: { x: 1, y: 20, z: 12 }, // South (x width)
32
+ [GameWallDirection.WEST]: { x: -10, y: 20, z: 1 }, // West (z width)
33
+ [GameWallDirection.EAST]: { x: 12, y: 20, z: 1 }, // East (z width)
34
+ }
35
+ const GAME_WALL_VELOCITY_DIRECTIONS = {
36
+ [GameWallDirection.NORTH]: { x: 0, y: 0, z: 1 },
37
+ [GameWallDirection.SOUTH]: { x: 0, y: 0, z: -1 },
38
+ [GameWallDirection.WEST]: { x: 1, y: 0, z: 0 },
39
+ [GameWallDirection.EAST]: { x: -1, y: 0, z: 0 },
40
+ }
41
+ const GAME_WALL_SHAPES = [
42
+ // lol shape
43
+ [
44
+ [0, 1, 0, 1, 1, 1, 0, 1],
45
+ [0, 1, 0, 1, 0, 1, 0, 1],
46
+ [0, 1, 0, 1, 1, 1, 0, 1],
47
+ ],
48
+ // stairs
49
+ [
50
+ [0, 0, 0, 0, 0, 0, 0, 1],
51
+ [0, 0, 0, 0, 0, 1, 1, 1],
52
+ [0, 0, 0, 1, 1, 1, 1, 1],
53
+ [0, 1, 1, 1, 1, 1, 1, 1],
54
+ [1, 1, 1, 1, 1, 1, 1, 1],
55
+ ],
56
+ // horizontal bar
57
+ [
58
+ [1, 1, 1, 1, 1, 1, 1, 1],
59
+ [1, 1, 1, 1, 1, 1, 1, 1],
60
+ ],
61
+ // vertical bars
62
+ [
63
+ [1, 0, 1, 0, 1, 0, 1, 0],
64
+ [1, 0, 1, 0, 1, 0, 1, 0],
65
+ [1, 0, 1, 0, 1, 0, 1, 0],
66
+ [1, 0, 1, 0, 1, 0, 1, 0],
67
+ ],
68
+ // lattice
69
+ [
70
+ [1, 0, 1, 0, 1, 0, 1, 0],
71
+ [0, 1, 0, 1, 0, 1, 0, 1],
72
+ [1, 0, 1, 0, 1, 0, 1, 0],
73
+ [0, 1, 0, 1, 0, 1, 0, 1],
74
+ [1, 0, 1, 0, 1, 0, 1, 0],
75
+ [0, 0, 0, 1, 0, 1, 0, 0],
76
+ [1, 0, 1, 0, 1, 0, 1, 0],
77
+ ],
78
+ // platforming hole
79
+ [
80
+ [1, 1, 1, 0, 0, 1, 1, 1],
81
+ [1, 1, 1, 0, 0, 1, 1, 1],
82
+ [1, 1, 1, 2, 2, 1, 1, 1],
83
+ [1, 1, 2, 1, 1, 2, 1, 1],
84
+ [1, 2, 1, 1, 1, 1, 2, 1],
85
+ [2, 1, 1, 1, 1, 1, 1, 2],
86
+ ],
87
+ // 3d stairs
88
+ [
89
+ [1, 1, 1, 1, 1, 1, 1, 1],
90
+ [2, 1, 2, 1, 1, 2, 1, 2],
91
+ [2, 3, 2, 3, 3, 2, 3, 2],
92
+ [3, 3, 3, 3, 3, 3, 3, 3],
93
+ ],
94
+ // 3d lattice
95
+ [
96
+ [0, 2, 0, 2, 0, 2, 0, 2],
97
+ [1, 0, 1, 0, 1, 0, 1, 0],
98
+ [0, 2, 0, 2, 0, 2, 0, 2],
99
+ [1, 0, 2, 0, 2, 0, 1, 0],
100
+ [1, 0, 1, 0, 1, 0, 1, 0],
101
+ [0, 2, 0, 2, 0, 2, 0, 2],
102
+ [1, 0, 3, 0, 3, 0, 1, 0],
103
+ ],
104
+ // full wall
105
+ [
106
+ [1, 1, 1, 1, 1, 1, 1, 1],
107
+ [1, 1, 1, 1, 1, 1, 1, 1],
108
+ [1, 1, 1, 1, 1, 1, 1, 1],
109
+ [1, 1, 1, 1, 1, 1, 1, 1],
110
+ ],
111
+ // zig zag challenge
112
+ [
113
+ [1, 1, 1, 0, 0, 0, 0, 0],
114
+ [0, 0, 1, 1, 1, 0, 0, 0],
115
+ [0, 0, 0, 0, 1, 1, 1, 0],
116
+ [0, 0, 0, 0, 0, 0, 1, 1],
117
+ ],
118
+ // triple jump
119
+ [
120
+ [0, 0, 1, 0, 0, 1, 0, 0],
121
+ [0, 0, 1, 0, 0, 1, 0, 0],
122
+ [1, 1, 1, 0, 0, 1, 1, 1],
123
+ ],
124
+ // layered tunnel
125
+ [
126
+ [1, 1, 1, 1, 1, 1, 1, 1],
127
+ [1, 0, 0, 2, 2, 0, 0, 1],
128
+ [1, 0, 0, 3, 3, 0, 0, 1],
129
+ [1, 1, 1, 1, 1, 1, 1, 1],
130
+ ],
131
+ // diagonal dash
132
+ [
133
+ [1, 1, 0, 0, 0, 0, 0, 0],
134
+ [0, 1, 1, 0, 0, 0, 0, 0],
135
+ [0, 0, 1, 1, 0, 0, 0, 0],
136
+ [0, 0, 0, 1, 1, 0, 0, 0],
137
+ [0, 0, 0, 0, 1, 1, 0, 0],
138
+ ],
139
+ // wave rider
140
+ [
141
+ [1, 0, 0, 0, 0, 0, 0, 1],
142
+ [1, 1, 0, 0, 0, 0, 1, 1],
143
+ [0, 1, 1, 0, 0, 1, 1, 0],
144
+ [0, 0, 1, 1, 1, 1, 0, 0],
145
+ ],
146
+ // forward momentum
147
+ [
148
+ [1, 1, 2, 2, 3, 3, 3, 3],
149
+ [1, 1, 2, 2, 3, 3, 3, 3],
150
+ [1, 1, 2, 2, 3, 3, 3, 3],
151
+ ],
152
+ // spiral staircase
153
+ [
154
+ [1, 1, 1, 1, 2, 2, 3, 3],
155
+ [3, 3, 1, 1, 1, 2, 2, 2],
156
+ [2, 3, 3, 1, 1, 1, 1, 2],
157
+ [2, 2, 2, 3, 3, 1, 1, 1],
158
+ ],
159
+ // hopscotch
160
+ [
161
+ [0, 1, 0, 1, 0, 1, 0, 1],
162
+ [0, 2, 0, 2, 0, 2, 0, 2],
163
+ [1, 0, 1, 0, 1, 0, 1, 0],
164
+ [2, 0, 2, 0, 2, 0, 2, 0],
165
+ ],
166
+ // snake path
167
+ [
168
+ [1, 1, 1, 1, 0, 0, 0, 0],
169
+ [0, 0, 0, 1, 0, 0, 0, 0],
170
+ [0, 0, 0, 2, 0, 0, 0, 0],
171
+ [0, 0, 0, 3, 3, 3, 3, 3],
172
+ ],
173
+ // diamond gate
174
+ [
175
+ [1, 1, 1, 0, 0, 1, 1, 1],
176
+ [1, 1, 0, 0, 0, 0, 1, 1],
177
+ [1, 0, 2, 0, 0, 2, 0, 1],
178
+ [0, 0, 0, 3, 3, 0, 0, 0],
179
+ [1, 0, 2, 0, 0, 2, 0, 1],
180
+ [1, 1, 0, 0, 0, 0, 1, 1],
181
+ [1, 1, 1, 0, 0, 1, 1, 1],
182
+ ],
183
+ ];
184
+
185
+ const JOIN_NPC_SPAWN_POSITION = { x: 1, y: 35, z: -7 };
186
+ const PLAYER_SPAWN_POSITION = { x: 1, y: 35, z: 2 };
187
+ const QUEUED_PLAYER_ENTITIES = new Set<PlayerEntity>();
188
+ const GAME_PLAYER_ENTITIES = new Set<PlayerEntity>();
189
+
190
+ let gameLevel = 1;
191
+ let gameState: 'awaitingPlayers' | 'starting' | 'inProgress' = 'awaitingPlayers';
192
+ let gameCountdownStartTime: number | null = null;
193
+ let gameInterval: NodeJS.Timer;
194
+ let gameStartTime: number | null = null;
195
+ let gameUiState: object = {};
196
+
197
+ let gameActiveAudio = new Audio({
198
+ uri: 'audio/music.mp3',
199
+ loop: true,
200
+ volume: 0.2,
201
+ });
202
+
203
+ let gameInactiveAudio = new Audio({
204
+ uri: 'audio/music/overworld.mp3',
205
+ loop: true,
206
+ volume: 0.2,
207
+ });
208
+
209
+ startServer(world => {
210
+ world.loadMap(worldMap);
211
+ world.onPlayerJoin = player => onPlayerJoin(world, player);
212
+ world.onPlayerLeave = player => onPlayerLeave(world, player);
213
+
214
+ spawnJoinNpc(world);
215
+
216
+ gameInactiveAudio.play(world);
217
+ });
218
+
219
+ function onPlayerJoin(world: World, player: Player) {
220
+ player.ui.load('ui/index.html');
221
+ player.ui.sendData(gameUiState);
222
+
223
+ const playerEntity = new PlayerEntity({
224
+ player,
225
+ name: 'Player',
226
+ modelUri: 'models/player.gltf',
227
+ modelLoopedAnimations: [ 'idle' ],
228
+ modelScale: 0.5,
229
+ });
230
+
231
+ playerEntity.spawn(world, PLAYER_SPAWN_POSITION);
232
+
233
+ playerEntity.onTick = () => {
234
+ if (playerEntity.position.y < 5) {
235
+ killPlayer(playerEntity);
236
+ }
237
+ }
238
+
239
+ }
240
+
241
+ function onPlayerLeave(world: World, player: Player) {
242
+ world.entityManager.getAllPlayerEntities(player).forEach(entity => {
243
+ // remove from game state
244
+ removePlayerFromQueue(entity);
245
+ killPlayer(entity);
246
+
247
+ // despawn player entity
248
+ entity.despawn();
249
+ });
250
+ }
251
+
252
+ function spawnJoinNpc(world: World) {
253
+ const joinNpc = new Entity({
254
+ name: 'Join NPC',
255
+ modelUri: 'models/mindflayer.gltf',
256
+ modelLoopedAnimations: [ 'idle' ],
257
+ modelScale: 0.4,
258
+ rigidBodyOptions: {
259
+ rotation: { x: 0, y: 1, z: 0, w: 0 },
260
+ enabledPositions: { x: false, y: true, z: false },
261
+ enabledRotations: { x: false, y: true, z: false },
262
+ colliders: [
263
+ Collider.optionsFromModelUri('models/mindflayer.gltf', 0.4),
264
+ {
265
+ shape: ColliderShape.CYLINDER,
266
+ radius: 2,
267
+ halfHeight: 2,
268
+ isSensor: true,
269
+ onCollision: (other: BlockType | Entity, started: boolean) => {
270
+ if (other instanceof PlayerEntity && started) {
271
+ addPlayerEntityToQueue(world, other);
272
+ }
273
+ }
274
+ }
275
+ ],
276
+ },
277
+ });
278
+
279
+ joinNpc.spawn(world, JOIN_NPC_SPAWN_POSITION);
280
+
281
+ const sceneUi = new SceneUI({
282
+ templateId: 'join-npc-ui',
283
+ attachedToEntity: joinNpc,
284
+ offset: { x: 0, y: 2.5, z: 0 },
285
+ });
286
+
287
+ sceneUi.load(world);
288
+ }
289
+
290
+ function addPlayerEntityToQueue(world: World, playerEntity: PlayerEntity) {
291
+ if (QUEUED_PLAYER_ENTITIES.has(playerEntity)) return;
292
+ QUEUED_PLAYER_ENTITIES.add(playerEntity);
293
+ world.chatManager.sendPlayerMessage(playerEntity.player, 'You have joined the next game queue!', '00FF00');
294
+ uiUpdate({ queueCount: QUEUED_PLAYER_ENTITIES.size });
295
+
296
+ if (gameState === 'awaitingPlayers' && QUEUED_PLAYER_ENTITIES.size > 1) {
297
+ queueGame(world);
298
+ }
299
+
300
+ const queuedSceneUi = new SceneUI({
301
+ templateId: 'player-queued',
302
+ attachedToEntity: playerEntity,
303
+ offset: { x: 0, y: 1, z: 0 },
304
+ });
305
+
306
+ queuedSceneUi.load(world);
307
+ }
308
+
309
+ function queueGame(world: World) {
310
+ gameState = 'starting';
311
+ gameCountdownStartTime = Date.now();
312
+
313
+ uiUpdate({
314
+ gameState,
315
+ gameCountdownStartTime,
316
+ countdown: GAME_START_DELAY_SECONDS,
317
+ });
318
+
319
+ setTimeout(() => {
320
+ QUEUED_PLAYER_ENTITIES.forEach(playerEntity => {
321
+ playerEntity.setPosition(GAME_START_POSITION);
322
+ GAME_PLAYER_ENTITIES.add(playerEntity);
323
+
324
+ world.sceneUIManager.getAllEntityAttachedSceneUIs(playerEntity).forEach(sceneUi => {
325
+ sceneUi.unload(); // unload the queued ui
326
+ });
327
+ });
328
+
329
+ QUEUED_PLAYER_ENTITIES.clear();
330
+ uiUpdate({ queueCount: 0 });
331
+ startGame(world);
332
+ }, GAME_START_DELAY_SECONDS * 1000);
333
+ }
334
+
335
+ function startGame(world: World) {
336
+ gameState = 'inProgress';
337
+ gameStartTime = Date.now();
338
+
339
+ gameInactiveAudio.pause();
340
+ gameActiveAudio.play(world, true);
341
+
342
+ const gameLoop = () => {
343
+ if (!gameStartTime) return clearTimeout(gameInterval);
344
+
345
+ const elapsedTime = Date.now() - gameStartTime;
346
+ const level = Math.floor(elapsedTime / (GAME_LEVEL_DURATION_SECONDS * 1000)) + 1;
347
+
348
+ // Calculate difficulty parameters based on level
349
+ const speedModifier = 1 + (level * 0.15); // 15% faster per level
350
+ const spawnInterval = Math.max(2000, 10000 - (level * 1000)); // Decrease from 10s by 1s per level, min 2s
351
+
352
+ // Generate wall from random direction
353
+ const directions = Object.values(GameWallDirection);
354
+ const randomDirection = directions[Math.floor(Math.random() * directions.length)];
355
+
356
+ generateWall(world, randomDirection, speedModifier);
357
+
358
+ // Dynamically adjust interval
359
+ clearTimeout(gameInterval);
360
+ gameInterval = setTimeout(gameLoop, spawnInterval);
361
+
362
+ // Update level
363
+ if (level > gameLevel) {
364
+ gameLevel = level;
365
+ uiUpdate({ gameLevel });
366
+ }
367
+ }
368
+
369
+ gameLoop(); // invoke to start
370
+
371
+ // Update UI
372
+ uiUpdate({
373
+ gameState: 'inProgress',
374
+ gameStartTime,
375
+ playersRemaining: Array.from(GAME_PLAYER_ENTITIES).map(playerEntity => playerEntity.player.username),
376
+ });
377
+ }
378
+
379
+ function endGame() {
380
+ clearTimeout(gameInterval);
381
+ gameState = 'awaitingPlayers';
382
+ gameLevel = 1;
383
+
384
+ const winner = Array.from(GAME_PLAYER_ENTITIES)[0];
385
+ if (winner) {
386
+ winner.setPosition(PLAYER_SPAWN_POSITION);
387
+ winner.world!.chatManager.sendBroadcastMessage(`${winner.player.username} wins!`, '00FF00');
388
+ }
389
+
390
+ GAME_PLAYER_ENTITIES.clear();
391
+
392
+ gameActiveAudio.pause();
393
+ gameInactiveAudio.play(gameInactiveAudio.world!, true);
394
+
395
+ uiUpdate({ gameState: 'awaitingPlayers', gameLevel: 1 });
396
+ }
397
+
398
+ function killPlayer(playerEntity: PlayerEntity) {
399
+ if (!GAME_PLAYER_ENTITIES.has(playerEntity)) return;
400
+
401
+ // return to spawn position
402
+ playerEntity.setPosition(PLAYER_SPAWN_POSITION);
403
+
404
+ // remove from game player list
405
+ GAME_PLAYER_ENTITIES.delete(playerEntity);
406
+
407
+ if (GAME_PLAYER_ENTITIES.size < 1) {
408
+ endGame();
409
+ }
410
+
411
+ // update remaining players for the ui
412
+ uiUpdate({
413
+ playersRemaining: Array.from(GAME_PLAYER_ENTITIES).map(playerEntity => playerEntity.player.username),
414
+ });
415
+ }
416
+
417
+ function removePlayerFromQueue(playerEntity: PlayerEntity) {
418
+ if (!QUEUED_PLAYER_ENTITIES.has(playerEntity)) return;
419
+
420
+ // remove from queue
421
+ QUEUED_PLAYER_ENTITIES.delete(playerEntity);
422
+
423
+ // update ui
424
+ uiUpdate({ queueCount: QUEUED_PLAYER_ENTITIES.size });
425
+ }
426
+
427
+ function generateWall(world: World, direction: GameWallDirection, speedModifier: number = 1) {
428
+ const selectedShape = GAME_WALL_SHAPES[Math.floor(Math.random() * GAME_WALL_SHAPES.length)];
429
+ const isNorthSouth = direction === GameWallDirection.NORTH || direction === GameWallDirection.SOUTH;
430
+
431
+ // Iterate through the shape array to create wall segments
432
+ for (let y = 0; y < selectedShape.length; y++) {
433
+ for (let x = 0; x < selectedShape[y].length; x++) {
434
+ if (selectedShape[y][x] === 1 || selectedShape[y][x] === 2 || selectedShape[y][x] === 3) {
435
+ // Calculate position offset from center
436
+ const xOffset = (x - selectedShape[y].length / 2) * 1 + 0.5; // 1 block width
437
+ const yOffset = (selectedShape.length - y - 1) * 1 + 0.5; // 1 block height
438
+
439
+ const wallSegment = new Entity({
440
+ blockTextureUri: selectedShape[y][x] === 2 ? 'textures/dirt.png' :
441
+ selectedShape[y][x] === 3 ? 'textures/sand.png' :
442
+ 'textures/oak_leaves.png',
443
+ blockHalfExtents: {
444
+ x: isNorthSouth ? 0.5 : 0.5,
445
+ y: 0.5,
446
+ z: isNorthSouth ? 0.5 : 0.5
447
+ },
448
+ rigidBodyOptions: {
449
+ type: RigidBodyType.KINEMATIC_VELOCITY,
450
+ }
451
+ });
452
+
453
+ const spawnPosition = { ...GAME_WALL_SPAWN_POSITIONS[direction] };
454
+
455
+ // Adjust position based on direction
456
+ if (isNorthSouth) {
457
+ spawnPosition.x += xOffset;
458
+ spawnPosition.y += yOffset;
459
+ if (selectedShape[y][x] === 2) {
460
+ spawnPosition.z += direction === GameWallDirection.NORTH ? 1 : -1;
461
+ } else if (selectedShape[y][x] === 3) {
462
+ spawnPosition.z += direction === GameWallDirection.NORTH ? 2 : -2;
463
+ }
464
+ } else {
465
+ spawnPosition.z += xOffset;
466
+ spawnPosition.y += yOffset;
467
+ if (selectedShape[y][x] === 2) {
468
+ spawnPosition.x += direction === GameWallDirection.WEST ? 1 : -1;
469
+ } else if (selectedShape[y][x] === 3) {
470
+ spawnPosition.x += direction === GameWallDirection.WEST ? 2 : -2;
471
+ }
472
+ }
473
+
474
+ wallSegment.spawn(world, spawnPosition);
475
+
476
+ // Set velocity based on direction
477
+ wallSegment.setLinearVelocity({
478
+ x: GAME_WALL_VELOCITY_DIRECTIONS[direction].x * speedModifier,
479
+ y: GAME_WALL_VELOCITY_DIRECTIONS[direction].y * speedModifier,
480
+ z: GAME_WALL_VELOCITY_DIRECTIONS[direction].z * speedModifier,
481
+ });
482
+
483
+ wallSegment.onTick = () => {
484
+ if (!wallSegment.isSpawned) return;
485
+ const position = wallSegment.position;
486
+
487
+ if (Math.abs(position.x - spawnPosition.x) > GAME_WALL_DESPAWN_DISTANCE || Math.abs(position.z - spawnPosition.z) > GAME_WALL_DESPAWN_DISTANCE) {
488
+ wallSegment.setLinearVelocity({ x: 0, y: -32, z: 0 }); // drop it out of the world to trigger decollision
489
+
490
+ setTimeout(() => {
491
+ wallSegment.despawn();
492
+ }, 1000);
493
+ }
494
+ }
495
+ }
496
+ }
497
+ }
498
+ }
499
+
500
+ function uiUpdate(data: object) {
501
+ gameUiState = { ...gameUiState, ...data };
502
+
503
+ GameServer.instance.playerManager.getConnectedPlayers().forEach(player => {
504
+ player.ui.sendData(data);
505
+ });
506
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "hole-in-wall-game",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": [],
10
+ "author": "",
11
+ "license": "ISC",
12
+ "dependencies": {
13
+ "@hytopia.com/assets": "^0.1.6",
14
+ "hytopia": "latest"
15
+ }
16
+ }
@@ -0,0 +1,6 @@
1
+ # wall-dodge-game
2
+
3
+ A game where players compete to survive the longest while dodging walls.
4
+
5
+ Includes a number of features such as leaderboards, countdown systems,
6
+ and more.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hytopia",
3
- "version": "0.1.71",
3
+ "version": "0.1.72",
4
4
  "description": "The HYTOPIA SDK makes it easy for developers to create massively multiplayer games using JavaScript or TypeScript.",
5
5
  "main": "server.js",
6
6
  "bin": {
package/server.api.json CHANGED
@@ -25438,6 +25438,55 @@
25438
25438
  "isAbstract": false,
25439
25439
  "name": "setCcdEnabled"
25440
25440
  },
25441
+ {
25442
+ "kind": "Method",
25443
+ "canonicalReference": "server!RigidBody#setCollisionGroupsForSensorColliders:member(1)",
25444
+ "docComment": "/**\n * Sets the collision groups for sensor colliders of the rigid body.\n *\n * @param collisionGroups - The collision groups for sensor colliders of the rigid body.\n */\n",
25445
+ "excerptTokens": [
25446
+ {
25447
+ "kind": "Content",
25448
+ "text": "setCollisionGroupsForSensorColliders(collisionGroups: "
25449
+ },
25450
+ {
25451
+ "kind": "Reference",
25452
+ "text": "CollisionGroups",
25453
+ "canonicalReference": "server!CollisionGroups:type"
25454
+ },
25455
+ {
25456
+ "kind": "Content",
25457
+ "text": "): "
25458
+ },
25459
+ {
25460
+ "kind": "Content",
25461
+ "text": "void"
25462
+ },
25463
+ {
25464
+ "kind": "Content",
25465
+ "text": ";"
25466
+ }
25467
+ ],
25468
+ "isStatic": false,
25469
+ "returnTypeTokenRange": {
25470
+ "startIndex": 3,
25471
+ "endIndex": 4
25472
+ },
25473
+ "releaseTag": "Public",
25474
+ "isProtected": false,
25475
+ "overloadIndex": 1,
25476
+ "parameters": [
25477
+ {
25478
+ "parameterName": "collisionGroups",
25479
+ "parameterTypeTokenRange": {
25480
+ "startIndex": 1,
25481
+ "endIndex": 2
25482
+ },
25483
+ "isOptional": false
25484
+ }
25485
+ ],
25486
+ "isOptional": false,
25487
+ "isAbstract": false,
25488
+ "name": "setCollisionGroupsForSensorColliders"
25489
+ },
25441
25490
  {
25442
25491
  "kind": "Method",
25443
25492
  "canonicalReference": "server!RigidBody#setCollisionGroupsForSolidColliders:member(1)",
package/server.d.ts CHANGED
@@ -3136,6 +3136,11 @@ export declare class RigidBody {
3136
3136
  * @param collisionGroups - The collision groups for solid colliders of the rigid body.
3137
3137
  */
3138
3138
  setCollisionGroupsForSolidColliders(collisionGroups: CollisionGroups): void;
3139
+ /**
3140
+ * Sets the collision groups for sensor colliders of the rigid body.
3141
+ * @param collisionGroups - The collision groups for sensor colliders of the rigid body.
3142
+ */
3143
+ setCollisionGroupsForSensorColliders(collisionGroups: CollisionGroups): void;
3139
3144
  /**
3140
3145
  * Sets the type of the rigid body.
3141
3146
  * @param type - The type of the rigid body.