hytopia 0.1.99 → 0.2.1

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.
@@ -103,6 +103,27 @@ The unique HYTOPIA UUID for the player.
103
103
  The current [PlayerInput](./server.playerinput.md) of the player.
104
104
 
105
105
 
106
+ </td></tr>
107
+ <tr><td>
108
+
109
+ [profilePictureUrl](./server.player.profilepictureurl.md)
110
+
111
+
112
+ </td><td>
113
+
114
+ `readonly`
115
+
116
+
117
+ </td><td>
118
+
119
+ string \| undefined
120
+
121
+
122
+ </td><td>
123
+
124
+ The profile picture URL for the player.
125
+
126
+
106
127
  </td></tr>
107
128
  <tr><td>
108
129
 
@@ -0,0 +1,13 @@
1
+ <!-- Do not edit this file. It is automatically generated by API Documenter. -->
2
+
3
+ [Home](./index.md) &gt; [server](./server.md) &gt; [Player](./server.player.md) &gt; [profilePictureUrl](./server.player.profilepictureurl.md)
4
+
5
+ ## Player.profilePictureUrl property
6
+
7
+ The profile picture URL for the player.
8
+
9
+ **Signature:**
10
+
11
+ ```typescript
12
+ readonly profilePictureUrl: string | undefined;
13
+ ```
@@ -63,7 +63,7 @@ let gameUiState: object = {};
63
63
 
64
64
  // Audio
65
65
  const gameActiveAudio = new Audio({
66
- uri: 'audio/music/hytopia-main.mp3',
66
+ uri: 'audio/music.mp3',
67
67
  loop: true,
68
68
  volume: 0.2,
69
69
  });
@@ -297,9 +297,9 @@ function generateWall(world: World, direction: GameWallDirection, speedModifier:
297
297
  const yOffset = (selectedShape.length - y - 1) * 1 + 0.5;
298
298
 
299
299
  const wallSegment = new Entity({
300
- blockTextureUri: selectedShape[y][x] === 2 ? 'textures/dirt.png' :
301
- selectedShape[y][x] === 3 ? 'textures/sand.png' :
302
- 'textures/oak_leaves.png',
300
+ blockTextureUri: selectedShape[y][x] === 2 ? 'blocks/dirt.png' :
301
+ selectedShape[y][x] === 3 ? 'blocks/sand.png' :
302
+ 'blocks/oak-leaves.png',
303
303
  blockHalfExtents: {
304
304
  x: isNorthSouth ? 0.5 : 0.5,
305
305
  y: 0.5,
@@ -1,4 +1,5 @@
1
1
  import {
2
+ Audio,
2
3
  CollisionGroup,
3
4
  ColliderShape,
4
5
  BlockType,
@@ -55,6 +56,12 @@ startServer(world => {
55
56
 
56
57
  setupJoinNPC(world);
57
58
  startBlockSpawner(world);
59
+
60
+ (new Audio({
61
+ uri: 'audio/bgm.mp3',
62
+ loop: true,
63
+ volume: 0.05,
64
+ })).play(world);
58
65
  });
59
66
 
60
67
  /**
@@ -0,0 +1,5 @@
1
+ # zombies-fps
2
+
3
+ A game inspired by the Call of Duty Zombies game mode. This is a basic, but mostly full featured game where players fight
4
+ off waves of zombies, can unlock rooms and weapons through crates, revive each other, and more. It implements the basics of a
5
+ complete gun system that uses raycasts as well.
@@ -73,6 +73,7 @@
73
73
  <!-- UI Scripts-->
74
74
  <script>
75
75
  const CDN_ASSETS_URL = '{{CDN_ASSETS_URL}}';
76
+ let timerInterval;
76
77
 
77
78
  hytopia.registerSceneUITemplate('downed-player', (id, onState) => {
78
79
  const template = document.getElementById('downed-player-template');
@@ -158,10 +159,15 @@
158
159
  document.querySelector('.game-info').style.display = 'block';
159
160
  document.querySelector('.game-info .timer').textContent = 'Time: 00:00';
160
161
  document.querySelector('.game-info .wave').textContent = 'Wave: 1';
162
+
163
+ // Clear previous timer
164
+ if (timerInterval) {
165
+ clearInterval(timerInterval);
166
+ }
161
167
 
162
168
  // Start game timer
163
169
  const startTime = Date.now();
164
- setInterval(() => {
170
+ timerInterval = setInterval(() => {
165
171
  const elapsedSeconds = Math.floor((Date.now() - startTime) / 1000);
166
172
  const minutes = Math.floor(elapsedSeconds / 60).toString().padStart(2, '0');
167
173
  const seconds = (elapsedSeconds % 60).toString().padStart(2, '0');
@@ -42,7 +42,7 @@ export default class EnemyEntity extends Entity {
42
42
  private _targetEntity: Entity | undefined;
43
43
 
44
44
  public constructor(options: EnemyEntityOptions) {
45
- super(options);
45
+ super({ ...options, tag: 'enemy' });
46
46
  this.damage = options.damage;
47
47
  this.health = options.health;
48
48
  this.jumpHeight = options.jumpHeight ?? 1;
@@ -84,7 +84,7 @@ export default class EnemyEntity extends Entity {
84
84
  }
85
85
  }
86
86
 
87
- public takeDamage(damage: number, fromPlayer: GamePlayerEntity) {
87
+ public takeDamage(damage: number, fromPlayer?: GamePlayerEntity) {
88
88
  if (!this.world) {
89
89
  return;
90
90
  }
@@ -96,7 +96,9 @@ export default class EnemyEntity extends Entity {
96
96
  }
97
97
 
98
98
  // Give reward based on damage as % of health
99
- fromPlayer.addMoney((this.damage / this.maxHealth) * this.reward);
99
+ if (fromPlayer) {
100
+ fromPlayer.addMoney((this.damage / this.maxHealth) * this.reward);
101
+ }
100
102
 
101
103
  if (this.health <= 0 && this.isSpawned) {
102
104
  // Enemy is dead, give half reward & despawn
@@ -1,16 +1,18 @@
1
1
  import { Audio, Collider, ColliderShape, CollisionGroup, GameServer } from 'hytopia';
2
+ import GamePlayerEntity from './GamePlayerEntity';
2
3
  import PurchaseBarrierEntity from './PurchaseBarrierEntity';
3
4
  import { INVISIBLE_WALLS, INVISIBLE_WALL_COLLISION_GROUP, PURCHASE_BARRIERS, ENEMY_SPAWN_POINTS, WEAPON_CRATES } from '../gameConfig';
4
- import type { World, Vector3Like } from 'hytopia';
5
-
6
- // temp
7
- import ZombieEntity from './enemies/ZombieEntity';
8
5
  import RipperEntity from './enemies/RipperEntity';
6
+ import ZombieEntity from './enemies/ZombieEntity';
9
7
  import WeaponCrateEntity from './WeaponCrateEntity';
8
+ import type { World, Vector3Like } from 'hytopia';
9
+ import type EnemyEntity from './EnemyEntity';
10
+ import type { Player } from 'hytopia';
10
11
 
11
12
  const GAME_WAVE_INTERVAL_MS = 30 * 1000; // 30 seconds between waves
12
13
  const SLOWEST_SPAWN_INTERVAL_MS = 4000; // Starting spawn rate
13
14
  const FASTEST_SPAWN_INTERVAL_MS = 750; // Fastest spawn rate
15
+ const GAME_START_COUNTDOWN_S = 45; // 45 seconds delay before game starts
14
16
  const WAVE_SPAWN_INTERVAL_REDUCTION_MS = 300; // Spawn rate reduction per wave
15
17
  const WAVE_DELAY_MS = 10000; // 10s between waves
16
18
 
@@ -24,7 +26,9 @@ export default class GameManager {
24
26
  public world: World | undefined;
25
27
 
26
28
  private _enemySpawnTimeout: NodeJS.Timeout | undefined;
27
- private _startTime: number | undefined;
29
+ private _endGameTimeout: NodeJS.Timeout | undefined;
30
+ private _startCountdown: number = GAME_START_COUNTDOWN_S;
31
+ private _startInterval: NodeJS.Timeout | undefined;
28
32
  private _waveTimeout: NodeJS.Timeout | undefined;
29
33
  private _waveStartAudio: Audio;
30
34
 
@@ -40,6 +44,28 @@ export default class GameManager {
40
44
  this.unlockedIds.add(id);
41
45
  }
42
46
 
47
+ public checkEndGame() {
48
+ clearTimeout(this._endGameTimeout);
49
+
50
+ this._endGameTimeout = setTimeout(() => {
51
+ if (!this.world) return;
52
+
53
+ let allPlayersDowned = true;
54
+
55
+ this.world.entityManager.getAllPlayerEntities().forEach(playerEntity => {
56
+ const gamePlayerEntity = playerEntity as GamePlayerEntity;
57
+
58
+ if (!gamePlayerEntity.downed) {
59
+ allPlayersDowned = false;
60
+ }
61
+ });
62
+
63
+ if (allPlayersDowned) {
64
+ this.endGame();
65
+ }
66
+ }, 1000);
67
+ }
68
+
43
69
  public setupGame(world: World) {
44
70
  this.world = world;
45
71
 
@@ -58,17 +84,8 @@ export default class GameManager {
58
84
  wallCollider.addToSimulation(world.simulation);
59
85
  });
60
86
 
61
- // Setup purchase barriers
62
- PURCHASE_BARRIERS.forEach(barrier => {
63
- const purchaseBarrier = new PurchaseBarrierEntity({
64
- name: barrier.name,
65
- removalPrice: barrier.removalPrice,
66
- unlockIds: barrier.unlockIds,
67
- width: barrier.width,
68
- });
69
-
70
- purchaseBarrier.spawn(world, barrier.position, barrier.rotation);
71
- });
87
+ // Spawn initial purchase barriers
88
+ this.spawnPurchaseBarriers();
72
89
 
73
90
  // Setup weapon crates
74
91
  WEAPON_CRATES.forEach(crate => {
@@ -88,14 +105,31 @@ export default class GameManager {
88
105
  volume: 0.4,
89
106
  })).play(world);
90
107
 
91
- world.chatManager.registerCommand('/start', () => this.startGame());
108
+ this.startCountdown();
109
+ }
110
+
111
+ public startCountdown() {
112
+ clearInterval(this._startInterval);
113
+ this._startCountdown = GAME_START_COUNTDOWN_S;
114
+ this._startInterval = setInterval(() => {
115
+ if (!this.world || !this.world.entityManager.getAllPlayerEntities().length) return;
116
+
117
+ this._startCountdown--;
118
+
119
+ if (this._startCountdown <= 0) {
120
+ this.startGame();
121
+ this.world.chatManager.sendBroadcastMessage('Game starting!', 'FF0000');
122
+ } else {
123
+ this.world.chatManager.sendBroadcastMessage(`${this._startCountdown} seconds until the game starts...`, 'FF0000');
124
+ }
125
+ }, 1000);
92
126
  }
93
127
 
94
128
  public startGame() {
95
129
  if (!this.world || this.isStarted) return; // type guard
96
130
 
97
131
  this.isStarted = true;
98
- this._startTime = Date.now();
132
+ clearInterval(this._startInterval);
99
133
 
100
134
  GameServer.instance.playerManager.getConnectedPlayersByWorld(this.world).forEach(player => {
101
135
  player.ui.sendData({ type: 'start' });
@@ -105,6 +139,64 @@ export default class GameManager {
105
139
  this._waveLoop();
106
140
  }
107
141
 
142
+ public endGame() {
143
+ if (!this.world) return;
144
+
145
+ this.world.chatManager.sendBroadcastMessage(`Game Over! Your team made it to wave ${this.waveNumber}!`, '00FF00');
146
+
147
+ clearTimeout(this._enemySpawnTimeout);
148
+ clearTimeout(this._waveTimeout);
149
+
150
+ this.isStarted = false;
151
+ this.unlockedIds = new Set([ 'start' ]);
152
+ this.waveNumber = 0;
153
+ this.waveDelay = 0;
154
+
155
+ this.world.entityManager.getEntitiesByTag('enemy').forEach(entity => {
156
+ const enemy = entity as EnemyEntity;
157
+ enemy.takeDamage(enemy.health); // triggers any UI updates when killed via takedamage
158
+ });
159
+
160
+ this.world.entityManager.getAllPlayerEntities().forEach(playerEntity => {
161
+ const player = playerEntity.player;
162
+ playerEntity.despawn();
163
+ });
164
+
165
+ GameServer.instance.playerManager.getConnectedPlayers().forEach(player => {
166
+ this.spawnPlayerEntity(player);
167
+ });
168
+
169
+ this.spawnPurchaseBarriers();
170
+ this.startCountdown();
171
+ }
172
+
173
+ public spawnPlayerEntity(player: Player) {
174
+ if (!this.world) return;
175
+
176
+ const playerEntity = new GamePlayerEntity(player);
177
+ playerEntity.spawn(this.world, { x: 2, y: 10, z: 19 });
178
+ player.camera.setAttachedToEntity(playerEntity);
179
+ }
180
+
181
+ public spawnPurchaseBarriers() {
182
+ if (!this.world) return;
183
+
184
+ this.world.entityManager.getEntitiesByTag('purchase-barrier').forEach(entity => {
185
+ entity.despawn();
186
+ });
187
+
188
+ PURCHASE_BARRIERS.forEach(barrier => {
189
+ const purchaseBarrier = new PurchaseBarrierEntity({
190
+ name: barrier.name,
191
+ removalPrice: barrier.removalPrice,
192
+ unlockIds: barrier.unlockIds,
193
+ width: barrier.width,
194
+ });
195
+
196
+ purchaseBarrier.spawn(this.world!, barrier.position, barrier.rotation);
197
+ });
198
+ }
199
+
108
200
  private _spawnLoop() {
109
201
  if (!this.world) return; // type guard
110
202
 
@@ -21,8 +21,8 @@ import PistolEntity from './guns/PistolEntity';
21
21
 
22
22
  import InteractableEntity from './InteractableEntity';
23
23
  import type GunEntity from './GunEntity';
24
- import type { GunEntityOptions } from './GunEntity';
25
24
  import { INVISIBLE_WALL_COLLISION_GROUP } from '../gameConfig';
25
+ import GameManager from './GameManager';
26
26
 
27
27
  const BASE_HEALTH = 100;
28
28
  const REVIVE_REQUIRED_HEALTH = 50;
@@ -137,6 +137,10 @@ export default class GamePlayerEntity extends PlayerEntity {
137
137
 
138
138
  // Start auto heal ticker
139
139
  this._autoHealTicker();
140
+
141
+ // Reset any prior UI from respawn
142
+ this._updatePlayerUIHealth();
143
+ this._updatePlayerUIMoney();
140
144
  }
141
145
 
142
146
  public addMoney(amount: number) {
@@ -263,10 +267,16 @@ export default class GamePlayerEntity extends PlayerEntity {
263
267
  this.playerController.walkVelocity = downed ? 1 : 4;
264
268
  this.playerController.jumpVelocity = downed ? 0 : 10;
265
269
 
270
+ if (!downed && this._gun) {
271
+ this._gun.setParentAnimations();
272
+ }
273
+
266
274
  if (downed) {
267
275
  this._downedSceneUI.setState({ progress: 0 })
268
276
  this._downedSceneUI.load(this.world);
269
277
  this.world.chatManager.sendPlayerMessage(this.player, 'You are downed! A teammate can still revive you!', 'FF0000');
278
+
279
+ GameManager.instance.checkEndGame();
270
280
  } else {
271
281
  this._downedSceneUI.unload();
272
282
  this.world.chatManager.sendPlayerMessage(this.player, 'You are back up! Thank your team & fight the horde!', '00FF00');
@@ -81,7 +81,7 @@ export default abstract class GunEntity extends Entity {
81
81
  });
82
82
 
83
83
  if (options.parent) {
84
- this._updateParentAnimations();
84
+ this.setParentAnimations();
85
85
  }
86
86
  }
87
87
 
@@ -168,6 +168,18 @@ export default abstract class GunEntity extends Entity {
168
168
  }, this.reloadTimeMs);
169
169
  }
170
170
 
171
+ public setParentAnimations() {
172
+ if (!this.parent || !this.parent.world) {
173
+ return;
174
+ }
175
+
176
+ const playerEntityController = this.parent.controller as PlayerEntityController;
177
+
178
+ playerEntityController.idleLoopedAnimations = [ this.idleAnimation, 'idle_lower' ];
179
+ playerEntityController.walkLoopedAnimations = [ this.idleAnimation, 'walk_lower' ];
180
+ playerEntityController.runLoopedAnimations = [ this.idleAnimation, 'run_lower' ];
181
+ }
182
+
171
183
  // override to create specific gun shoot logic
172
184
  public shoot() {
173
185
  if (!this.parent || !this.parent.world) {
@@ -221,18 +233,6 @@ export default abstract class GunEntity extends Entity {
221
233
  }
222
234
  }
223
235
 
224
- private _updateParentAnimations() {
225
- if (!this.parent || !this.parent.world) {
226
- return;
227
- }
228
-
229
- const playerEntityController = this.parent.controller as PlayerEntityController;
230
-
231
- playerEntityController.idleLoopedAnimations = [ this.idleAnimation, 'idle_lower' ];
232
- playerEntityController.walkLoopedAnimations = [ this.idleAnimation, 'walk_lower' ];
233
- playerEntityController.runLoopedAnimations = [ this.idleAnimation, 'run_lower' ];
234
- }
235
-
236
236
  private _updatePlayerUIAmmo() {
237
237
  if (!this.parent || !this.parent.world) {
238
238
  return;
@@ -40,6 +40,7 @@ export default class PurchaseBarrierEntity extends InteractableEntity {
40
40
  rigidBodyOptions: {
41
41
  type: RigidBodyType.FIXED,
42
42
  },
43
+ tag: 'purchase-barrier',
43
44
  });
44
45
 
45
46
  this.removalPrice = options.removalPrice;
@@ -1,5 +1,4 @@
1
1
  import { startServer } from 'hytopia';
2
- import GamePlayerEntity from './classes/GamePlayerEntity';
3
2
  import worldMap from './assets/maps/terrain.json';
4
3
 
5
4
  import GameManager from './classes/GameManager';
@@ -8,8 +7,6 @@ startServer(world => {
8
7
  // Load map.
9
8
  world.loadMap(worldMap);
10
9
 
11
- //world.simulation.enableDebugRaycasting(true);
12
-
13
10
  // Setup lighting
14
11
  world.setAmbientLightIntensity(0.0001);
15
12
  world.setAmbientLightColor({ r: 255, g: 192, b: 192 });
@@ -21,12 +18,10 @@ startServer(world => {
21
18
  // Spawn a player entity when a player joins the game.
22
19
  world.onPlayerJoin = player => {
23
20
  if (GameManager.instance.isStarted) {
24
- return world.chatManager.sendPlayerMessage(player, 'This round has already started, please wait for the next round. You can fly around as a spectator.', 'FF0000');
21
+ return world.chatManager.sendPlayerMessage(player, 'This round has already started, you will automatically join when the next round starts. While you wait, you can fly around as a spectator by using W, A, S, D.', 'FF0000');
25
22
  }
26
23
 
27
- const playerEntity = new GamePlayerEntity(player);
28
-
29
- playerEntity.spawn(world, { x: 2, y: 10, z: 19 });
24
+ GameManager.instance.spawnPlayerEntity(player);
30
25
  };
31
26
 
32
27
  // Despawn all player entities when a player leaves the game.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hytopia",
3
- "version": "0.1.99",
3
+ "version": "0.2.1",
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "metadata": {
3
3
  "toolPackage": "@microsoft/api-extractor",
4
- "toolVersion": "7.47.11",
4
+ "toolVersion": "7.50.0",
5
5
  "schemaVersion": 1011,
6
6
  "oldestForwardsCompatibleVersion": 1001,
7
7
  "tsdocConfig": {
@@ -7115,7 +7115,7 @@
7115
7115
  {
7116
7116
  "kind": "Reference",
7117
7117
  "text": "RAPIER.Collider",
7118
- "canonicalReference": "@dimforge/rapier3d-compat!Collider:class"
7118
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!Collider:class"
7119
7119
  },
7120
7120
  {
7121
7121
  "kind": "Content",
@@ -9391,7 +9391,7 @@
9391
9391
  {
9392
9392
  "kind": "Reference",
9393
9393
  "text": "RAPIER.Vector",
9394
- "canonicalReference": "@dimforge/rapier3d-compat!Vector:interface"
9394
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!Vector:interface"
9395
9395
  },
9396
9396
  {
9397
9397
  "kind": "Content",
@@ -9400,7 +9400,7 @@
9400
9400
  {
9401
9401
  "kind": "Reference",
9402
9402
  "text": "RAPIER.Vector",
9403
- "canonicalReference": "@dimforge/rapier3d-compat!Vector:interface"
9403
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!Vector:interface"
9404
9404
  },
9405
9405
  {
9406
9406
  "kind": "Content",
@@ -18286,6 +18286,36 @@
18286
18286
  "isAbstract": false,
18287
18287
  "name": "leaveWorld"
18288
18288
  },
18289
+ {
18290
+ "kind": "Property",
18291
+ "canonicalReference": "server!Player#profilePictureUrl:member",
18292
+ "docComment": "/**\n * The profile picture URL for the player.\n */\n",
18293
+ "excerptTokens": [
18294
+ {
18295
+ "kind": "Content",
18296
+ "text": "readonly profilePictureUrl: "
18297
+ },
18298
+ {
18299
+ "kind": "Content",
18300
+ "text": "string | undefined"
18301
+ },
18302
+ {
18303
+ "kind": "Content",
18304
+ "text": ";"
18305
+ }
18306
+ ],
18307
+ "isReadonly": true,
18308
+ "isOptional": false,
18309
+ "releaseTag": "Public",
18310
+ "name": "profilePictureUrl",
18311
+ "propertyTypeTokenRange": {
18312
+ "startIndex": 1,
18313
+ "endIndex": 2
18314
+ },
18315
+ "isStatic": false,
18316
+ "isProtected": false,
18317
+ "isAbstract": false
18318
+ },
18289
18319
  {
18290
18320
  "kind": "Property",
18291
18321
  "canonicalReference": "server!Player#ui:member",
@@ -24793,7 +24823,7 @@
24793
24823
  {
24794
24824
  "kind": "Reference",
24795
24825
  "text": "RAPIER.InteractionGroups",
24796
- "canonicalReference": "@dimforge/rapier3d-compat!InteractionGroups:type"
24826
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!InteractionGroups:type"
24797
24827
  },
24798
24828
  {
24799
24829
  "kind": "Content",
@@ -24877,7 +24907,7 @@
24877
24907
  {
24878
24908
  "kind": "Reference",
24879
24909
  "text": "RAPIER.QueryFilterFlags",
24880
- "canonicalReference": "@dimforge/rapier3d-compat!QueryFilterFlags:enum"
24910
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!QueryFilterFlags:enum"
24881
24911
  },
24882
24912
  {
24883
24913
  "kind": "Content",
@@ -24886,7 +24916,7 @@
24886
24916
  {
24887
24917
  "kind": "Reference",
24888
24918
  "text": "RAPIER.Collider",
24889
- "canonicalReference": "@dimforge/rapier3d-compat!Collider:class"
24919
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!Collider:class"
24890
24920
  },
24891
24921
  {
24892
24922
  "kind": "Content",
@@ -24895,7 +24925,7 @@
24895
24925
  {
24896
24926
  "kind": "Reference",
24897
24927
  "text": "RAPIER.RigidBody",
24898
- "canonicalReference": "@dimforge/rapier3d-compat!RigidBody:class"
24928
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!RigidBody:class"
24899
24929
  },
24900
24930
  {
24901
24931
  "kind": "Content",
@@ -24904,7 +24934,7 @@
24904
24934
  {
24905
24935
  "kind": "Reference",
24906
24936
  "text": "RAPIER.Collider",
24907
- "canonicalReference": "@dimforge/rapier3d-compat!Collider:class"
24937
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!Collider:class"
24908
24938
  },
24909
24939
  {
24910
24940
  "kind": "Content",
@@ -26795,7 +26825,7 @@
26795
26825
  {
26796
26826
  "kind": "Reference",
26797
26827
  "text": "RAPIER.RigidBody",
26798
- "canonicalReference": "@dimforge/rapier3d-compat!RigidBody:class"
26828
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!RigidBody:class"
26799
26829
  },
26800
26830
  {
26801
26831
  "kind": "Content",
@@ -30436,7 +30466,7 @@
30436
30466
  {
30437
30467
  "kind": "Reference",
30438
30468
  "text": "RAPIER.ColliderHandle",
30439
- "canonicalReference": "@dimforge/rapier3d-compat!ColliderHandle:type"
30469
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!ColliderHandle:type"
30440
30470
  },
30441
30471
  {
30442
30472
  "kind": "Content",
@@ -30445,7 +30475,7 @@
30445
30475
  {
30446
30476
  "kind": "Reference",
30447
30477
  "text": "RAPIER.ColliderHandle",
30448
- "canonicalReference": "@dimforge/rapier3d-compat!ColliderHandle:type"
30478
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!ColliderHandle:type"
30449
30479
  },
30450
30480
  {
30451
30481
  "kind": "Content",
@@ -30507,7 +30537,7 @@
30507
30537
  {
30508
30538
  "kind": "Reference",
30509
30539
  "text": "RAPIER.Vector3",
30510
- "canonicalReference": "@dimforge/rapier3d-compat!Vector3:class"
30540
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!Vector3:class"
30511
30541
  },
30512
30542
  {
30513
30543
  "kind": "Content",
@@ -30598,7 +30628,7 @@
30598
30628
  {
30599
30629
  "kind": "Reference",
30600
30630
  "text": "RAPIER.Vector3",
30601
- "canonicalReference": "@dimforge/rapier3d-compat!Vector3:class"
30631
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!Vector3:class"
30602
30632
  },
30603
30633
  {
30604
30634
  "kind": "Content",
@@ -30607,7 +30637,7 @@
30607
30637
  {
30608
30638
  "kind": "Reference",
30609
30639
  "text": "RAPIER.Vector3",
30610
- "canonicalReference": "@dimforge/rapier3d-compat!Vector3:class"
30640
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!Vector3:class"
30611
30641
  },
30612
30642
  {
30613
30643
  "kind": "Content",
@@ -30702,7 +30732,7 @@
30702
30732
  {
30703
30733
  "kind": "Reference",
30704
30734
  "text": "RAPIER.Vector3",
30705
- "canonicalReference": "@dimforge/rapier3d-compat!Vector3:class"
30735
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!Vector3:class"
30706
30736
  },
30707
30737
  {
30708
30738
  "kind": "Content",
@@ -30815,7 +30845,7 @@
30815
30845
  {
30816
30846
  "kind": "Reference",
30817
30847
  "text": "RapierSdpMatrix3",
30818
- "canonicalReference": "@dimforge/rapier3d-compat!SdpMatrix3:class"
30848
+ "canonicalReference": "@dimforge/rapier3d-compat-simd!SdpMatrix3:class"
30819
30849
  },
30820
30850
  {
30821
30851
  "kind": "Content",
package/server.d.ts CHANGED
@@ -1,13 +1,12 @@
1
- /// <reference types="node" />
2
-
3
1
  import type { AnyPacket } from '@hytopia.com/server-protocol';
4
2
  import http from 'http';
5
3
  import type { IncomingMessage } from 'http';
6
4
  import type { InputSchema } from '@hytopia.com/server-protocol';
7
5
  import type { IPacket } from '@hytopia.com/server-protocol';
6
+ import type { LobbyMembershipDto } from '@hytopia.com/creative-lib/dist/impl/getSession';
8
7
  import protocol from '@hytopia.com/server-protocol';
9
- import RAPIER from '@dimforge/rapier3d-compat';
10
- import { SdpMatrix3 } from '@dimforge/rapier3d-compat';
8
+ import RAPIER from '@dimforge/rapier3d-compat-simd';
9
+ import { SdpMatrix3 } from '@dimforge/rapier3d-compat-simd';
11
10
  import type { Socket as Socket_2 } from 'net';
12
11
  import { WebSocket as WebSocket_2 } from 'ws';
13
12
 
@@ -2343,6 +2342,8 @@ export declare class Player {
2343
2342
  readonly id: string;
2344
2343
  /** The unique HYTOPIA username for the player. */
2345
2344
  readonly username: string;
2345
+ /** The profile picture URL for the player. */
2346
+ readonly profilePictureUrl: string | undefined;
2346
2347
  /** The camera for the player. */
2347
2348
  readonly camera: PlayerCamera;
2348
2349