hytopia 0.1.96 → 0.1.98

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 (71) hide show
  1. package/docs/server.md +66 -0
  2. package/docs/server.pathfindabortcallback.md +13 -0
  3. package/docs/server.pathfindcompletecallback.md +13 -0
  4. package/docs/server.pathfindingentitycontroller.debug.md +13 -0
  5. package/docs/server.pathfindingentitycontroller.maxfall.md +13 -0
  6. package/docs/server.pathfindingentitycontroller.maxjump.md +13 -0
  7. package/docs/server.pathfindingentitycontroller.maxopensetiterations.md +13 -0
  8. package/docs/server.pathfindingentitycontroller.md +287 -0
  9. package/docs/server.pathfindingentitycontroller.pathfind.md +87 -0
  10. package/docs/server.pathfindingentitycontroller.speed.md +13 -0
  11. package/docs/server.pathfindingentitycontroller.target.md +13 -0
  12. package/docs/server.pathfindingentitycontroller.verticalpenalty.md +13 -0
  13. package/docs/server.pathfindingentitycontroller.waypointnextindex.md +13 -0
  14. package/docs/server.pathfindingentitycontroller.waypoints.md +13 -0
  15. package/docs/server.pathfindingentitycontroller.waypointtimeoutms.md +13 -0
  16. package/docs/server.pathfindingoptions.md +26 -0
  17. package/docs/server.playerentitycontroller.autocancelmouseleftclick.md +13 -0
  18. package/docs/server.playerentitycontroller.md +19 -0
  19. package/docs/server.playerentitycontrolleroptions.autocancelmouseleftclick.md +13 -0
  20. package/docs/server.playerentitycontrolleroptions.md +19 -0
  21. package/docs/server.simpleentitycontroller.jump.md +53 -0
  22. package/docs/server.simpleentitycontroller.md +14 -0
  23. package/docs/server.waypointmovecompletecallback.md +15 -0
  24. package/docs/server.waypointmoveskippedcallback.md +15 -0
  25. package/examples/ai-agents/.env.example +2 -0
  26. package/examples/ai-agents/README.md +17 -0
  27. package/examples/ai-agents/bun.lockb +0 -0
  28. package/examples/ai-agents/package.json +2 -2
  29. package/examples/big-world/bun.lockb +0 -0
  30. package/examples/big-world/package.json +2 -2
  31. package/examples/block-entity/bun.lockb +0 -0
  32. package/examples/block-entity/package.json +2 -2
  33. package/examples/child-entity/bun.lockb +0 -0
  34. package/examples/child-entity/package-lock.json +30 -0
  35. package/examples/child-entity/package.json +2 -2
  36. package/examples/custom-ui/bun.lockb +0 -0
  37. package/examples/custom-ui/package.json +2 -2
  38. package/examples/entity-controller/bun.lockb +0 -0
  39. package/examples/entity-spawn/bun.lockb +0 -0
  40. package/examples/entity-spawn/package.json +1 -1
  41. package/examples/hole-in-wall-game/bun.lockb +0 -0
  42. package/examples/hole-in-wall-game/package.json +2 -2
  43. package/examples/lighting/bun.lockb +0 -0
  44. package/examples/lighting/package.json +3 -2
  45. package/examples/pathfinding/README.md +3 -0
  46. package/examples/pathfinding/assets/map.json +25828 -0
  47. package/examples/pathfinding/bun.lockb +0 -0
  48. package/examples/pathfinding/index.ts +113 -0
  49. package/examples/pathfinding/package.json +16 -0
  50. package/examples/payload-game/bun.lockb +0 -0
  51. package/examples/payload-game/package.json +3 -2
  52. package/examples/wall-dodge-game/bun.lockb +0 -0
  53. package/examples/wall-dodge-game/package-lock.json +30 -0
  54. package/examples/wall-dodge-game/package.json +2 -2
  55. package/examples/zombies-fps/assets/audio/sfx/pistol-shoot-1.mp3 +0 -0
  56. package/examples/zombies-fps/assets/audio/sfx/pistol-shoot-2.mp3 +0 -0
  57. package/examples/zombies-fps/assets/audio/sfx/pistol-shoot.mp3 +0 -0
  58. package/examples/zombies-fps/assets/maps/terrain.json +0 -12
  59. package/examples/zombies-fps/assets/ui/index.html +35 -0
  60. package/examples/zombies-fps/bun.lockb +0 -0
  61. package/examples/zombies-fps/classes/GamePlayerEntity.ts +49 -16
  62. package/examples/zombies-fps/classes/GunEntity.ts +66 -0
  63. package/examples/zombies-fps/classes/guns/BulletEntity.ts +0 -0
  64. package/examples/zombies-fps/classes/guns/PistolEntity.ts +49 -0
  65. package/examples/zombies-fps/index.ts +5 -1
  66. package/examples/zombies-fps/package.json +2 -2
  67. package/package.json +1 -1
  68. package/server.api.json +713 -0
  69. package/server.d.ts +136 -0
  70. package/server.js +87 -87
  71. package/examples/zombies-fps/classes/WeaponEntity.ts +0 -32
Binary file
@@ -0,0 +1,113 @@
1
+ import {
2
+ startServer,
3
+ Entity,
4
+ PathfindingEntityController,
5
+ PlayerEntity,
6
+ Quaternion,
7
+ RigidBodyType,
8
+ ColliderShape,
9
+ } from 'hytopia';
10
+
11
+ import worldMap from './assets/map.json';
12
+
13
+ startServer(world => {
14
+ world.loadMap(worldMap);
15
+
16
+ // Spawn our zombie that will pathfind around the map
17
+ const zombie = new Entity({
18
+ controller: new PathfindingEntityController(),
19
+ name: 'Zombie',
20
+ modelUri: 'models/npcs/zombie.gltf',
21
+ modelLoopedAnimations: [ 'walk' ],
22
+ modelScale: 0.5,
23
+ rigidBodyOptions: {
24
+ enabledRotations: { x: false, y: true, z: false },
25
+ ccdEnabled: true,
26
+ },
27
+ });
28
+
29
+ // Spawn somewhere in front of the player
30
+ zombie.spawn(world, { x: 4, y: 3, z: -6 }, Quaternion.fromEuler(0, 180, 0)); // rotate 180 degrees around Y, facing the player spawn point.
31
+
32
+ // Enter /pathfind to make the zombie pathfind to the player
33
+ let pathfindMarkers: Entity[] = [];
34
+ world.chatManager.registerCommand('/pathfind', (player, args) => {
35
+ // Get the entity of the palyer that entered the command
36
+ const playerEntities = world.entityManager.getPlayerEntitiesByPlayer(player);
37
+ const playerEntity = playerEntities[0];
38
+ const playerPosition = playerEntity.position;
39
+
40
+ // Remove all existing pathfind markers, which we use in the example just to visualize the path taken.
41
+ pathfindMarkers.forEach(marker => marker.despawn());
42
+ pathfindMarkers = [];
43
+
44
+ // Pathfind the zombie to the player
45
+ const pathfindingController = zombie.controller as PathfindingEntityController;
46
+
47
+ // .pathfind() is synchronous and returns immediately soon as a path is found or not, but before the entity has reached the target.
48
+ const succeeded = pathfindingController.pathfind(playerPosition, 3, { // all possible options for example
49
+ debug: true, // Setting true will console log pathfinding result info
50
+ maxFall: 10, // The maximum fall distance (in blocks) the entity can fall when considering a path.
51
+ maxJump: 1, // The maximum height (in blocks) the entity will jump when considering a path, the controller will apply the jumps automatically while pathfinding.
52
+ maxOpenSetIterations: 100, // A performance optimization value. A lower value will make pathfinding faster but may fail for longer paths, a higher value can make pathfinding take longer but will work better for longer paths.
53
+ verticalPenalty: -1, // A behavior control. The more negative the value, the more the entity will prefer taking a route that requires jumping and falling, even going out of its way to do so. A more positive value will prefer avoiding jumps and falls unless absolutely necessary.
54
+ pathfindAbortCallback: () => { // Invoked when maxOpenSetIterations is reached and pathfinding aborts.
55
+ console.log('Pathfinding aborted');
56
+ },
57
+ pathfindCompleteCallback: () => { // Invoked when the entity associated with the PathfindingEntityController finishes pathfinding and is now at the target coordinate.
58
+ console.log('Pathfinding complete');
59
+ },
60
+ waypointMoveCompleteCallback: () => { // Invoked when the entity associated with the PathfindingEntityController finishes moving to a calculate waypoint of its current path.
61
+ console.log('Waypoint reached');
62
+ },
63
+ waypointMoveSkippedCallback: () => { // Invoked when the entity associated with the PathfindingEntityController skips a waypoint because it exceeded the waypointTimeoutMs.
64
+ console.log('Waypoint skipped');
65
+ },
66
+ waypointTimeoutMs: 2000, // The timeout in milliseconds for a waypoint to be considered reached. Defaults to 2000ms divided by the speed of the entity.
67
+ });
68
+
69
+ // .pathfind() will return true if the algorithm found a path and began traversing it.
70
+ console.log(`Path found successfully?: ${succeeded}`);
71
+
72
+ // Spawn visual markers for the path
73
+ pathfindingController.waypoints.forEach(waypoint => {
74
+ const pathfindMarker = new Entity({
75
+ modelUri: 'models/items/cookie.gltf',
76
+ rigidBodyOptions: {
77
+ type: RigidBodyType.FIXED,
78
+ colliders: [
79
+ {
80
+ shape: ColliderShape.BLOCK,
81
+ halfExtents: { x: 0.5, y: 0.5, z: 0.5 },
82
+ isSensor: true,
83
+ },
84
+ ],
85
+ },
86
+ });
87
+
88
+ pathfindMarker.spawn(world, { x: waypoint.x, y: waypoint.y + 0.25, z: waypoint.z });
89
+
90
+ pathfindMarkers.push(pathfindMarker);
91
+ });
92
+ });
93
+
94
+ // Spawn a player entity when a player joins the game.
95
+ world.onPlayerJoin = player => {
96
+ const playerEntity = new PlayerEntity({
97
+ player,
98
+ name: 'Player',
99
+ modelUri: 'models/players/player.gltf',
100
+ modelLoopedAnimations: [ 'idle' ],
101
+ modelScale: 0.5,
102
+ });
103
+
104
+ world.chatManager.sendPlayerMessage(player, 'To make the zombie pathfind to you, enter: /pathfind', '00FF00');
105
+
106
+ playerEntity.spawn(world, { x: 4, y: 3, z: 1 });
107
+ };
108
+
109
+ // Despawn all player entities when a player leaves the game.
110
+ world.onPlayerLeave = player => {
111
+ world.entityManager.getPlayerEntitiesByPlayer(player).forEach(entity => entity.despawn());
112
+ };
113
+ });
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "pathfinding",
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": "latest",
14
+ "hytopia": "latest"
15
+ }
16
+ }
Binary file
@@ -10,7 +10,8 @@
10
10
  "author": "",
11
11
  "license": "ISC",
12
12
  "dependencies": {
13
- "@hytopia.com/assets": "^0.2.5",
14
- "hytopia": "^0.1.86"
13
+ "@hytopia.com/assets": "latest",
14
+ "hytopia": "latest"
15
+
15
16
  }
16
17
  }
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "payload-game",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "payload-game",
9
+ "version": "1.0.0",
10
+ "license": "ISC",
11
+ "dependencies": {
12
+ "@hytopia.com/assets": "latest",
13
+ "hytopia": "latest"
14
+ }
15
+ },
16
+ "node_modules/@hytopia.com/assets": {
17
+ "version": "0.1.7",
18
+ "resolved": "https://registry.npmjs.org/@hytopia.com/assets/-/assets-0.1.7.tgz",
19
+ "integrity": "sha512-gC113cIIVKp97cDX3u9n3ats8qS1kuaKPStQXOf1wNxuRs36yBvHM8NJWArfzzk8SG3ilfSZtc7qMYHod2ngcg=="
20
+ },
21
+ "node_modules/hytopia": {
22
+ "version": "0.1.81",
23
+ "resolved": "https://registry.npmjs.org/hytopia/-/hytopia-0.1.81.tgz",
24
+ "integrity": "sha512-F7oKIt/3iPwWdrbgycyZ/t7+SrgOOmS4CvmDFiQYDsk+6cILIadBkq/H4M/YpxL3iqqvZVHFDv13tybM+zolZw==",
25
+ "bin": {
26
+ "hytopia": "bin/scripts.js"
27
+ }
28
+ }
29
+ }
30
+ }
@@ -10,7 +10,7 @@
10
10
  "author": "",
11
11
  "license": "ISC",
12
12
  "dependencies": {
13
- "@hytopia.com/assets": "^0.2.5",
14
- "hytopia": "^0.1.86"
13
+ "@hytopia.com/assets": "latest",
14
+ "hytopia": "latest"
15
15
  }
16
16
  }
@@ -126,12 +126,6 @@
126
126
  "textureUri": "blocks/iron-ore.png",
127
127
  "isCustom": false
128
128
  },
129
- {
130
- "id": 22,
131
- "name": "lava",
132
- "textureUri": "blocks/lava.png",
133
- "isCustom": false
134
- },
135
129
  {
136
130
  "id": 23,
137
131
  "name": "log",
@@ -246,12 +240,6 @@
246
240
  "textureUri": "blocks/voidsoil.png",
247
241
  "isCustom": false
248
242
  },
249
- {
250
- "id": 42,
251
- "name": "water-flow",
252
- "textureUri": "blocks/water-flow.png",
253
- "isCustom": false
254
- },
255
243
  {
256
244
  "id": 43,
257
245
  "name": "water-still",
@@ -0,0 +1,35 @@
1
+ <style>
2
+ .crosshair {
3
+ position: fixed;
4
+ top: 50%;
5
+ left: 50%;
6
+ transform: translate(-50%, -50%);
7
+ width: 20px;
8
+ height: 20px;
9
+ pointer-events: none;
10
+ opacity: 0.7;
11
+ }
12
+
13
+ .crosshair::before,
14
+ .crosshair::after {
15
+ content: '';
16
+ position: absolute;
17
+ background-color: rgba(255, 255, 255, 0.8);
18
+ }
19
+
20
+ .crosshair::before {
21
+ width: 2px;
22
+ height: 100%;
23
+ left: 50%;
24
+ transform: translateX(-50%);
25
+ }
26
+
27
+ .crosshair::after {
28
+ width: 100%;
29
+ height: 2px;
30
+ top: 50%;
31
+ transform: translateY(-50%);
32
+ }
33
+ </style>
34
+
35
+ <div class="crosshair"></div>
Binary file
@@ -1,54 +1,87 @@
1
1
  import {
2
+ CollisionGroup,
2
3
  Player,
4
+ PlayerCameraOrientation,
3
5
  PlayerEntity,
4
6
  PlayerCameraMode,
7
+ PlayerInput,
5
8
  Vector3Like,
6
9
  QuaternionLike,
7
10
  World,
8
11
  Quaternion,
12
+ PlayerEntityController,
9
13
  } from 'hytopia';
10
14
 
11
- import WeaponEntity from './WeaponEntity';
15
+ import PistolEntity from './guns/PistolEntity';
16
+ import type GunEntity from './guns/GunEntity';
12
17
 
13
18
  const BASE_HEALTH = 100;
19
+ const BASE_MONEY = 10;
14
20
 
15
21
  export default class GamePlayerEntity extends PlayerEntity {
16
22
  public health: number;
17
23
  public maxHealth: number;
24
+ public money: number;
25
+ private _gun: GunEntity | null = null;
26
+
27
+ // Player entities always assign a PlayerController to the entity, so we can safely create a convenience getter
28
+ public get playerController(): PlayerEntityController {
29
+ return this.controller as PlayerEntityController;
30
+ }
18
31
 
19
32
  public constructor(player: Player) {
20
33
  super({
21
34
  player,
22
35
  name: 'Player',
23
36
  modelUri: 'models/players/soldier-player.gltf',
24
- modelLoopedAnimations: [ 'idle_gun_right', 'shoot_gun_right' ],
25
37
  modelScale: 0.5,
26
38
  });
39
+
40
+
41
+ // Prevent mouse left click from being cancelled, required
42
+ // for auto-fire and semi-auto fire mechanics, etc.
43
+ this.playerController.autoCancelMouseLeftClick = false;
44
+
45
+ // Setup player animations
46
+ this.playerController.idleLoopedAnimations = [ 'idle_gun_right', 'idle_lower' ];
47
+ this.playerController.interactOneshotAnimations = [];
48
+ this.playerController.walkLoopedAnimations = [ 'idle_gun_right', 'walk_lower' ];
49
+ this.playerController.runLoopedAnimations = [ 'idle_gun_right', 'run_lower' ];
50
+ this.playerController.onTickWithPlayerInput = this._onTickWithPlayerInput;
51
+
52
+ // Setup UI
53
+ this.player.ui.load('ui/index.html');
27
54
 
28
- // this.player.camera.setMode(PlayerCameraMode.FIRST_PERSON);
29
- // this.player.camera.setModelHiddenNodes([ 'head' ]);
30
- // this.player.camera.setOffset({ x: 0, y: 0.4, z: 0 });
31
- // this.player.camera.setForwardOffset(0.4);
55
+ // Setup first person camera
56
+ this.player.camera.setMode(PlayerCameraMode.FIRST_PERSON);
57
+ this.player.camera.setModelHiddenNodes([ 'head', 'neck' ]);
58
+ this.player.camera.setOffset({ x: 0, y: 0.5, z: 0 });
59
+ this.player.camera.setForwardOffset(0.2);
32
60
 
61
+ // Set base stats
33
62
  this.health = BASE_HEALTH;
34
63
  this.maxHealth = BASE_HEALTH;
64
+ this.money = BASE_MONEY;
35
65
  }
36
66
 
37
67
  public override spawn(world: World, position: Vector3Like, rotation?: QuaternionLike): void {
38
68
  super.spawn(world, position, rotation);
39
69
 
40
- const weapon = new WeaponEntity({
41
- name: 'Pistol',
42
- modelUri: 'models/items/pistol.glb',
43
- modelScale: 1.3,
44
- damage: 10,
45
- ammo: 10,
46
- maxAmmo: 10,
47
- parent: this,
48
- parentNodeName: 'hand_right_anchor',
70
+ // Prevent players from colliding, setup appropriate collision groups for invisible walls, etc.
71
+ this.setCollisionGroupsForSolidColliders({
72
+ belongsTo: [ CollisionGroup.PLAYER ],
73
+ collidesWith: [ CollisionGroup.BLOCK, CollisionGroup.ENTITY, CollisionGroup.ENTITY_SENSOR ],
49
74
  });
50
75
 
51
- weapon.spawn(world, { x: 0, y: 0, z: 0 }, Quaternion.fromEuler(-90, 0, 0));
76
+ // Give player a pistol.
77
+ this._gun = new PistolEntity({ parent: this });
78
+ this._gun.spawn(world, { x: 0, y: 0, z: -0.2 }, Quaternion.fromEuler(-90, 0, 0));
79
+ }
80
+
81
+ private _onTickWithPlayerInput = (entity: PlayerEntity, input: PlayerInput, cameraOrientation: PlayerCameraOrientation, deltaTimeMs: number) => {
82
+ if (input.ml && this._gun) {
83
+ this._gun.shoot();
84
+ }
52
85
  }
53
86
  }
54
87
 
@@ -0,0 +1,66 @@
1
+ import {
2
+ Entity,
3
+ EntityOptions,
4
+ } from 'hytopia';
5
+
6
+ export type GunHand = 'left' | 'right' | 'both';
7
+
8
+ export interface GunEntityOptions extends EntityOptions {
9
+ ammo: number; // The amount of ammo in the clip.
10
+ damage: number; // The damage of the gun.
11
+ fireRate: number; // Bullets shot per second.
12
+ reloadTime: number; // Seconds to reload.
13
+ hand: GunHand; // The hand the weapon is held in.
14
+ maxAmmo: number; // The amount of ammo the clip can hold.
15
+ }
16
+
17
+ export default class GunEntity extends Entity {
18
+ public ammo: number;
19
+ public damage: number;
20
+ public fireRate: number;
21
+ public hand: GunHand;
22
+ public maxAmmo: number;
23
+ public reloadTime: number;
24
+ private _lastFireTime: number = 0;
25
+
26
+ public constructor(options: GunEntityOptions) {
27
+ super({
28
+ ...options,
29
+ parent: options.parent,
30
+ parentNodeName: options.parent ? GunEntity._getParentNodeName(options.hand) : undefined,
31
+ });
32
+
33
+ this.fireRate = options.fireRate;
34
+ this.damage = options.damage;
35
+ this.ammo = options.ammo;
36
+ this.hand = options.hand;
37
+ this.maxAmmo = options.maxAmmo;
38
+ this.reloadTime = options.reloadTime;
39
+ }
40
+
41
+ // simple convenience helper for handling ammo and fire rate in shoot() overrides.
42
+ public processShoot(): boolean {
43
+ const now = performance.now();
44
+
45
+ if (this._lastFireTime && now - this._lastFireTime < 1000 / this.fireRate) {
46
+ return false;
47
+ }
48
+
49
+ if (this.ammo <= 0) {
50
+ //return false;
51
+ }
52
+
53
+ this.ammo--;
54
+ this._lastFireTime = now;
55
+
56
+ return true;
57
+ }
58
+
59
+ // override to create specific gun shoot logic
60
+ public shoot() {}
61
+
62
+ // convenience helper for getting the node name of the hand the gun is held in.
63
+ private static _getParentNodeName(hand: GunHand): string {
64
+ return hand === 'left' ? 'hand_left_anchor' : 'hand_right_anchor';
65
+ }
66
+ }
@@ -0,0 +1,49 @@
1
+ import {
2
+ Audio,
3
+ PlayerEntity,
4
+ } from 'hytopia';
5
+
6
+ import GunEntity from '../GunEntity';
7
+ import type { GunEntityOptions } from '../GunEntity';
8
+
9
+ export default class PistolEntity extends GunEntity {
10
+ public constructor(options: Partial<GunEntityOptions>) {
11
+ super({
12
+ ammo: options.ammo ?? 10,
13
+ damage: options.damage ?? 3,
14
+ fireRate: options.fireRate ?? 5,
15
+ hand: options.hand ?? 'right',
16
+ maxAmmo: options.maxAmmo ?? 10,
17
+ modelUri: 'models/items/pistol.glb',
18
+ modelScale: 1.3,
19
+ parent: options.parent,
20
+ reloadTime: options.reloadTime ?? 1,
21
+ });
22
+ }
23
+
24
+ public override shoot() {
25
+ if (!this.parent || !this.processShoot()) {
26
+ return;
27
+ }
28
+
29
+ const parentPlayerEntity = this.parent as PlayerEntity;
30
+
31
+ if (!parentPlayerEntity.world) {
32
+ return;
33
+ }
34
+
35
+ // cancel the input, pistols require click to shoot
36
+ parentPlayerEntity.player.input.ml = false;
37
+
38
+ // play shoot animation
39
+ parentPlayerEntity.startModelOneshotAnimations([ 'shoot_gun_right' ]);
40
+
41
+ (new Audio({
42
+ position: parentPlayerEntity.position,
43
+ referenceDistance: 20,
44
+ uri: 'audio/sfx/pistol-shoot-1.mp3',
45
+ volume: 1,
46
+ })).play(parentPlayerEntity.world, true);
47
+ }
48
+ }
49
+
@@ -1,4 +1,4 @@
1
- import { startServer, Collider, ColliderShape } from 'hytopia';
1
+ import { startServer, Collider, ColliderShape, CollisionGroup } from 'hytopia';
2
2
  import GamePlayerEntity from './classes/GamePlayerEntity';
3
3
  import PurchaseBarrierEntity from './classes/PurchaseBarrierEntity';
4
4
  import { INVISIBLE_WALLS, PURCHASE_BARRIERS } from './gameConfig';
@@ -19,6 +19,10 @@ startServer(world => {
19
19
  shape: ColliderShape.BLOCK,
20
20
  halfExtents: wall.halfExtents,
21
21
  relativePosition: wall.position, // since this is not attached to a rigid body, relative position is realtive to the world global coordinate space.
22
+ collisionGroups: {
23
+ belongsTo: [ CollisionGroup.BLOCK ],
24
+ collidesWith: [ CollisionGroup.PLAYER ],
25
+ },
22
26
  });
23
27
 
24
28
  wallCollider.addToSimulation(world.simulation);
@@ -10,7 +10,7 @@
10
10
  "author": "",
11
11
  "license": "ISC",
12
12
  "dependencies": {
13
- "@hytopia.com/assets": "^0.2.5",
14
- "hytopia": "^0.1.93"
13
+ "@hytopia.com/assets": "latest",
14
+ "hytopia": "latest"
15
15
  }
16
16
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hytopia",
3
- "version": "0.1.96",
3
+ "version": "0.1.98",
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": {