hytopia 0.1.72 → 0.1.73
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/docs/server.eventrouter.emit.md +20 -4
- package/docs/server.eventrouter.md +43 -1
- package/docs/server.eventrouter.on.md +1 -1
- package/docs/server.eventrouter.once.md +69 -0
- package/docs/server.eventrouter.prependon.md +69 -0
- package/docs/server.eventrouter.prependonce.md +69 -0
- package/docs/server.md +0 -11
- package/examples/hole-in-wall-game/assets/map.json +3 -2
- package/examples/hole-in-wall-game/assets/ui/index.html +3 -4
- package/examples/hole-in-wall-game/index.ts +122 -258
- package/examples/hole-in-wall-game/package.json +2 -2
- package/examples/hole-in-wall-game/wall-shapes.ts +145 -0
- package/package.json +1 -1
- package/server.api.json +253 -96
- package/server.d.ts +33 -23
- package/server.js +80 -80
- package/docs/server.event_2.md +0 -76
- package/docs/server.event_2.payload.md +0 -13
- package/docs/server.event_2.type.md +0 -13
- package/examples/hole-in-wall-game/hole-in-the-wall-4.zip +0 -0
@@ -11,179 +11,46 @@ import {
|
|
11
11
|
PlayerEntity,
|
12
12
|
SceneUI,
|
13
13
|
World,
|
14
|
+
CollisionGroup,
|
14
15
|
} from 'hytopia';
|
15
16
|
|
17
|
+
import GAME_WALL_SHAPES from './wall-shapes';
|
18
|
+
|
16
19
|
import worldMap from './assets/map.json';
|
17
20
|
|
21
|
+
// Game constants
|
18
22
|
enum GameWallDirection {
|
19
23
|
NORTH = 'NORTH',
|
20
24
|
SOUTH = 'SOUTH',
|
21
|
-
WEST = 'WEST',
|
25
|
+
WEST = 'WEST',
|
22
26
|
EAST = 'EAST',
|
23
27
|
}
|
24
28
|
|
25
|
-
const
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
}
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
[
|
45
|
-
[
|
46
|
-
|
47
|
-
|
48
|
-
|
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 };
|
29
|
+
const GAME_CONFIG = {
|
30
|
+
LEVEL_DURATION: 10,
|
31
|
+
START_DELAY: 30,
|
32
|
+
WALL_COLLISION_GROUP: CollisionGroup.GROUP_1,
|
33
|
+
WALL_DESPAWN_DISTANCE: 18,
|
34
|
+
POSITIONS: {
|
35
|
+
START: { x: 1, y: 22, z: 1 },
|
36
|
+
JOIN_NPC: { x: 1, y: 35, z: -7 },
|
37
|
+
PLAYER_SPAWN: { x: 1, y: 35, z: 2 },
|
38
|
+
WALLS: {
|
39
|
+
[GameWallDirection.NORTH]: { x: 1, y: 20, z: -10 },
|
40
|
+
[GameWallDirection.SOUTH]: { x: 1, y: 20, z: 12 },
|
41
|
+
[GameWallDirection.WEST]: { x: -10, y: 20, z: 1 },
|
42
|
+
[GameWallDirection.EAST]: { x: 12, y: 20, z: 1 },
|
43
|
+
}
|
44
|
+
},
|
45
|
+
WALL_VELOCITIES: {
|
46
|
+
[GameWallDirection.NORTH]: { x: 0, y: 0, z: 1 },
|
47
|
+
[GameWallDirection.SOUTH]: { x: 0, y: 0, z: -1 },
|
48
|
+
[GameWallDirection.WEST]: { x: 1, y: 0, z: 0 },
|
49
|
+
[GameWallDirection.EAST]: { x: -1, y: 0, z: 0 },
|
50
|
+
}
|
51
|
+
};
|
52
|
+
|
53
|
+
// Game state
|
187
54
|
const QUEUED_PLAYER_ENTITIES = new Set<PlayerEntity>();
|
188
55
|
const GAME_PLAYER_ENTITIES = new Set<PlayerEntity>();
|
189
56
|
|
@@ -194,13 +61,14 @@ let gameInterval: NodeJS.Timer;
|
|
194
61
|
let gameStartTime: number | null = null;
|
195
62
|
let gameUiState: object = {};
|
196
63
|
|
197
|
-
|
64
|
+
// Audio
|
65
|
+
const gameActiveAudio = new Audio({
|
198
66
|
uri: 'audio/music.mp3',
|
199
67
|
loop: true,
|
200
68
|
volume: 0.2,
|
201
69
|
});
|
202
70
|
|
203
|
-
|
71
|
+
const gameInactiveAudio = new Audio({
|
204
72
|
uri: 'audio/music/overworld.mp3',
|
205
73
|
loop: true,
|
206
74
|
volume: 0.2,
|
@@ -212,7 +80,6 @@ startServer(world => {
|
|
212
80
|
world.onPlayerLeave = player => onPlayerLeave(world, player);
|
213
81
|
|
214
82
|
spawnJoinNpc(world);
|
215
|
-
|
216
83
|
gameInactiveAudio.play(world);
|
217
84
|
});
|
218
85
|
|
@@ -224,27 +91,33 @@ function onPlayerJoin(world: World, player: Player) {
|
|
224
91
|
player,
|
225
92
|
name: 'Player',
|
226
93
|
modelUri: 'models/player.gltf',
|
227
|
-
modelLoopedAnimations: [
|
94
|
+
modelLoopedAnimations: ['idle'],
|
228
95
|
modelScale: 0.5,
|
229
96
|
});
|
230
97
|
|
231
|
-
playerEntity.spawn(world,
|
98
|
+
playerEntity.spawn(world, GAME_CONFIG.POSITIONS.PLAYER_SPAWN);
|
232
99
|
|
100
|
+
playerEntity.setCollisionGroupsForSolidColliders({
|
101
|
+
belongsTo: [CollisionGroup.ENTITY, CollisionGroup.PLAYER],
|
102
|
+
collidesWith: [CollisionGroup.BLOCK, CollisionGroup.ENTITY_SENSOR, GAME_CONFIG.WALL_COLLISION_GROUP],
|
103
|
+
});
|
104
|
+
|
105
|
+
playerEntity.setCollisionGroupsForSensorColliders({
|
106
|
+
belongsTo: [CollisionGroup.ENTITY_SENSOR],
|
107
|
+
collidesWith: [CollisionGroup.BLOCK, GAME_CONFIG.WALL_COLLISION_GROUP],
|
108
|
+
});
|
109
|
+
|
233
110
|
playerEntity.onTick = () => {
|
234
111
|
if (playerEntity.position.y < 5) {
|
235
112
|
killPlayer(playerEntity);
|
236
113
|
}
|
237
114
|
}
|
238
|
-
|
239
115
|
}
|
240
116
|
|
241
117
|
function onPlayerLeave(world: World, player: Player) {
|
242
118
|
world.entityManager.getAllPlayerEntities(player).forEach(entity => {
|
243
|
-
// remove from game state
|
244
119
|
removePlayerFromQueue(entity);
|
245
120
|
killPlayer(entity);
|
246
|
-
|
247
|
-
// despawn player entity
|
248
121
|
entity.despawn();
|
249
122
|
});
|
250
123
|
}
|
@@ -253,7 +126,7 @@ function spawnJoinNpc(world: World) {
|
|
253
126
|
const joinNpc = new Entity({
|
254
127
|
name: 'Join NPC',
|
255
128
|
modelUri: 'models/mindflayer.gltf',
|
256
|
-
modelLoopedAnimations: [
|
129
|
+
modelLoopedAnimations: ['idle'],
|
257
130
|
modelScale: 0.4,
|
258
131
|
rigidBodyOptions: {
|
259
132
|
rotation: { x: 0, y: 1, z: 0, w: 0 },
|
@@ -274,9 +147,9 @@ function spawnJoinNpc(world: World) {
|
|
274
147
|
}
|
275
148
|
],
|
276
149
|
},
|
277
|
-
});
|
150
|
+
});
|
278
151
|
|
279
|
-
joinNpc.spawn(world,
|
152
|
+
joinNpc.spawn(world, GAME_CONFIG.POSITIONS.JOIN_NPC);
|
280
153
|
|
281
154
|
const sceneUi = new SceneUI({
|
282
155
|
templateId: 'join-npc-ui',
|
@@ -289,6 +162,7 @@ function spawnJoinNpc(world: World) {
|
|
289
162
|
|
290
163
|
function addPlayerEntityToQueue(world: World, playerEntity: PlayerEntity) {
|
291
164
|
if (QUEUED_PLAYER_ENTITIES.has(playerEntity)) return;
|
165
|
+
|
292
166
|
QUEUED_PLAYER_ENTITIES.add(playerEntity);
|
293
167
|
world.chatManager.sendPlayerMessage(playerEntity.player, 'You have joined the next game queue!', '00FF00');
|
294
168
|
uiUpdate({ queueCount: QUEUED_PLAYER_ENTITIES.size });
|
@@ -313,23 +187,23 @@ function queueGame(world: World) {
|
|
313
187
|
uiUpdate({
|
314
188
|
gameState,
|
315
189
|
gameCountdownStartTime,
|
316
|
-
countdown:
|
190
|
+
countdown: GAME_CONFIG.START_DELAY,
|
317
191
|
});
|
318
192
|
|
319
193
|
setTimeout(() => {
|
320
194
|
QUEUED_PLAYER_ENTITIES.forEach(playerEntity => {
|
321
|
-
playerEntity.setPosition(
|
195
|
+
playerEntity.setPosition(GAME_CONFIG.POSITIONS.START);
|
322
196
|
GAME_PLAYER_ENTITIES.add(playerEntity);
|
323
197
|
|
324
198
|
world.sceneUIManager.getAllEntityAttachedSceneUIs(playerEntity).forEach(sceneUi => {
|
325
|
-
sceneUi.unload();
|
199
|
+
sceneUi.unload();
|
326
200
|
});
|
327
201
|
});
|
328
202
|
|
329
203
|
QUEUED_PLAYER_ENTITIES.clear();
|
330
204
|
uiUpdate({ queueCount: 0 });
|
331
205
|
startGame(world);
|
332
|
-
},
|
206
|
+
}, GAME_CONFIG.START_DELAY * 1000);
|
333
207
|
}
|
334
208
|
|
335
209
|
function startGame(world: World) {
|
@@ -343,32 +217,27 @@ function startGame(world: World) {
|
|
343
217
|
if (!gameStartTime) return clearTimeout(gameInterval);
|
344
218
|
|
345
219
|
const elapsedTime = Date.now() - gameStartTime;
|
346
|
-
const level = Math.floor(elapsedTime / (
|
220
|
+
const level = Math.floor(elapsedTime / (GAME_CONFIG.LEVEL_DURATION * 1000)) + 1;
|
347
221
|
|
348
|
-
|
349
|
-
const
|
350
|
-
const spawnInterval = Math.max(2000, 10000 - (level * 1000)); // Decrease from 10s by 1s per level, min 2s
|
222
|
+
const speedModifier = 1 + (level * 0.15);
|
223
|
+
const spawnInterval = Math.max(2000, 10000 - (level * 1000));
|
351
224
|
|
352
|
-
// Generate wall from random direction
|
353
225
|
const directions = Object.values(GameWallDirection);
|
354
226
|
const randomDirection = directions[Math.floor(Math.random() * directions.length)];
|
355
227
|
|
356
228
|
generateWall(world, randomDirection, speedModifier);
|
357
229
|
|
358
|
-
// Dynamically adjust interval
|
359
230
|
clearTimeout(gameInterval);
|
360
231
|
gameInterval = setTimeout(gameLoop, spawnInterval);
|
361
232
|
|
362
|
-
// Update level
|
363
233
|
if (level > gameLevel) {
|
364
234
|
gameLevel = level;
|
365
235
|
uiUpdate({ gameLevel });
|
366
236
|
}
|
367
237
|
}
|
368
238
|
|
369
|
-
gameLoop();
|
239
|
+
gameLoop();
|
370
240
|
|
371
|
-
// Update UI
|
372
241
|
uiUpdate({
|
373
242
|
gameState: 'inProgress',
|
374
243
|
gameStartTime,
|
@@ -383,7 +252,7 @@ function endGame() {
|
|
383
252
|
|
384
253
|
const winner = Array.from(GAME_PLAYER_ENTITIES)[0];
|
385
254
|
if (winner) {
|
386
|
-
winner.setPosition(
|
255
|
+
winner.setPosition(GAME_CONFIG.POSITIONS.PLAYER_SPAWN);
|
387
256
|
winner.world!.chatManager.sendBroadcastMessage(`${winner.player.username} wins!`, '00FF00');
|
388
257
|
}
|
389
258
|
|
@@ -398,17 +267,13 @@ function endGame() {
|
|
398
267
|
function killPlayer(playerEntity: PlayerEntity) {
|
399
268
|
if (!GAME_PLAYER_ENTITIES.has(playerEntity)) return;
|
400
269
|
|
401
|
-
|
402
|
-
playerEntity.setPosition(PLAYER_SPAWN_POSITION);
|
403
|
-
|
404
|
-
// remove from game player list
|
270
|
+
playerEntity.setPosition(GAME_CONFIG.POSITIONS.PLAYER_SPAWN);
|
405
271
|
GAME_PLAYER_ENTITIES.delete(playerEntity);
|
406
272
|
|
407
|
-
if (GAME_PLAYER_ENTITIES.size
|
273
|
+
if (GAME_PLAYER_ENTITIES.size <= 1) {
|
408
274
|
endGame();
|
409
275
|
}
|
410
276
|
|
411
|
-
// update remaining players for the ui
|
412
277
|
uiUpdate({
|
413
278
|
playersRemaining: Array.from(GAME_PLAYER_ENTITIES).map(playerEntity => playerEntity.player.username),
|
414
279
|
});
|
@@ -416,11 +281,7 @@ function killPlayer(playerEntity: PlayerEntity) {
|
|
416
281
|
|
417
282
|
function removePlayerFromQueue(playerEntity: PlayerEntity) {
|
418
283
|
if (!QUEUED_PLAYER_ENTITIES.has(playerEntity)) return;
|
419
|
-
|
420
|
-
// remove from queue
|
421
284
|
QUEUED_PLAYER_ENTITIES.delete(playerEntity);
|
422
|
-
|
423
|
-
// update ui
|
424
285
|
uiUpdate({ queueCount: QUEUED_PLAYER_ENTITIES.size });
|
425
286
|
}
|
426
287
|
|
@@ -428,69 +289,73 @@ function generateWall(world: World, direction: GameWallDirection, speedModifier:
|
|
428
289
|
const selectedShape = GAME_WALL_SHAPES[Math.floor(Math.random() * GAME_WALL_SHAPES.length)];
|
429
290
|
const isNorthSouth = direction === GameWallDirection.NORTH || direction === GameWallDirection.SOUTH;
|
430
291
|
|
431
|
-
// Iterate through the shape array to create wall segments
|
432
292
|
for (let y = 0; y < selectedShape.length; y++) {
|
433
293
|
for (let x = 0; x < selectedShape[y].length; x++) {
|
434
|
-
if (selectedShape[y][x] ===
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
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
|
-
}
|
294
|
+
if (selectedShape[y][x] === 0) continue;
|
295
|
+
|
296
|
+
const xOffset = (x - selectedShape[y].length / 2) * 1 + 0.5;
|
297
|
+
const yOffset = (selectedShape.length - y - 1) * 1 + 0.5;
|
298
|
+
|
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',
|
303
|
+
blockHalfExtents: {
|
304
|
+
x: isNorthSouth ? 0.5 : 0.5,
|
305
|
+
y: 0.5,
|
306
|
+
z: isNorthSouth ? 0.5 : 0.5
|
307
|
+
},
|
308
|
+
rigidBodyOptions: {
|
309
|
+
type: RigidBodyType.KINEMATIC_VELOCITY,
|
472
310
|
}
|
311
|
+
});
|
312
|
+
|
313
|
+
const spawnPosition = { ...GAME_CONFIG.POSITIONS.WALLS[direction] };
|
314
|
+
|
315
|
+
if (isNorthSouth) {
|
316
|
+
spawnPosition.x += xOffset;
|
317
|
+
spawnPosition.y += yOffset;
|
318
|
+
if (selectedShape[y][x] === 2) {
|
319
|
+
spawnPosition.z += direction === GameWallDirection.NORTH ? 1 : -1;
|
320
|
+
} else if (selectedShape[y][x] === 3) {
|
321
|
+
spawnPosition.z += direction === GameWallDirection.NORTH ? 2 : -2;
|
322
|
+
}
|
323
|
+
} else {
|
324
|
+
spawnPosition.z += xOffset;
|
325
|
+
spawnPosition.y += yOffset;
|
326
|
+
if (selectedShape[y][x] === 2) {
|
327
|
+
spawnPosition.x += direction === GameWallDirection.WEST ? 1 : -1;
|
328
|
+
} else if (selectedShape[y][x] === 3) {
|
329
|
+
spawnPosition.x += direction === GameWallDirection.WEST ? 2 : -2;
|
330
|
+
}
|
331
|
+
}
|
473
332
|
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
333
|
+
wallSegment.spawn(world, spawnPosition);
|
334
|
+
|
335
|
+
wallSegment.setCollisionGroupsForSolidColliders({
|
336
|
+
belongsTo: [GAME_CONFIG.WALL_COLLISION_GROUP],
|
337
|
+
collidesWith: [CollisionGroup.PLAYER, CollisionGroup.ENTITY_SENSOR],
|
338
|
+
});
|
339
|
+
|
340
|
+
wallSegment.setLinearVelocity({
|
341
|
+
x: GAME_CONFIG.WALL_VELOCITIES[direction].x * speedModifier,
|
342
|
+
y: GAME_CONFIG.WALL_VELOCITIES[direction].y * speedModifier,
|
343
|
+
z: GAME_CONFIG.WALL_VELOCITIES[direction].z * speedModifier,
|
344
|
+
});
|
345
|
+
|
346
|
+
wallSegment.onTick = () => {
|
347
|
+
if (!wallSegment.isSpawned) return;
|
348
|
+
const position = wallSegment.position;
|
349
|
+
|
350
|
+
if (Math.abs(position.x - spawnPosition.x) > GAME_CONFIG.WALL_DESPAWN_DISTANCE ||
|
351
|
+
Math.abs(position.z - spawnPosition.z) > GAME_CONFIG.WALL_DESPAWN_DISTANCE) {
|
352
|
+
wallSegment.setLinearVelocity({ x: 0, y: -32, z: 0 });
|
353
|
+
|
354
|
+
setTimeout(() => {
|
355
|
+
if (wallSegment.isSpawned) {
|
491
356
|
wallSegment.despawn();
|
492
|
-
}
|
493
|
-
}
|
357
|
+
}
|
358
|
+
}, 1000);
|
494
359
|
}
|
495
360
|
}
|
496
361
|
}
|
@@ -499,7 +364,6 @@ function generateWall(world: World, direction: GameWallDirection, speedModifier:
|
|
499
364
|
|
500
365
|
function uiUpdate(data: object) {
|
501
366
|
gameUiState = { ...gameUiState, ...data };
|
502
|
-
|
503
367
|
GameServer.instance.playerManager.getConnectedPlayers().forEach(player => {
|
504
368
|
player.ui.sendData(data);
|
505
369
|
});
|
@@ -0,0 +1,145 @@
|
|
1
|
+
const GAME_WALL_SHAPES = [
|
2
|
+
// lol shape
|
3
|
+
[
|
4
|
+
[0, 1, 0, 1, 1, 1, 0, 1],
|
5
|
+
[0, 1, 0, 1, 0, 1, 0, 1],
|
6
|
+
[0, 1, 0, 1, 1, 1, 0, 1],
|
7
|
+
],
|
8
|
+
// stairs
|
9
|
+
[
|
10
|
+
[0, 0, 0, 0, 0, 0, 0, 1],
|
11
|
+
[0, 0, 0, 0, 0, 1, 1, 1],
|
12
|
+
[0, 0, 0, 1, 1, 1, 1, 1],
|
13
|
+
[0, 1, 1, 1, 1, 1, 1, 1],
|
14
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
15
|
+
],
|
16
|
+
// horizontal bar
|
17
|
+
[
|
18
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
19
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
20
|
+
],
|
21
|
+
// vertical bars
|
22
|
+
[
|
23
|
+
[1, 0, 1, 0, 1, 0, 1, 0],
|
24
|
+
[1, 0, 1, 0, 1, 0, 1, 0],
|
25
|
+
[1, 0, 1, 0, 1, 0, 1, 0],
|
26
|
+
[1, 0, 1, 0, 1, 0, 1, 0],
|
27
|
+
],
|
28
|
+
// lattice
|
29
|
+
[
|
30
|
+
[1, 0, 1, 0, 1, 0, 1, 0],
|
31
|
+
[0, 1, 0, 1, 0, 1, 0, 1],
|
32
|
+
[1, 0, 1, 0, 1, 0, 1, 0],
|
33
|
+
[0, 1, 0, 1, 0, 1, 0, 1],
|
34
|
+
[1, 0, 1, 0, 1, 0, 1, 0],
|
35
|
+
[0, 0, 0, 1, 0, 1, 0, 0],
|
36
|
+
[1, 0, 1, 0, 1, 0, 1, 0],
|
37
|
+
],
|
38
|
+
// platforming hole
|
39
|
+
[
|
40
|
+
[1, 1, 1, 0, 0, 1, 1, 1],
|
41
|
+
[1, 1, 1, 0, 0, 1, 1, 1],
|
42
|
+
[1, 1, 1, 2, 2, 1, 1, 1],
|
43
|
+
[1, 1, 2, 1, 1, 2, 1, 1],
|
44
|
+
[1, 2, 1, 1, 1, 1, 2, 1],
|
45
|
+
[2, 1, 1, 1, 1, 1, 1, 2],
|
46
|
+
],
|
47
|
+
// 3d stairs
|
48
|
+
[
|
49
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
50
|
+
[2, 1, 2, 1, 1, 2, 1, 2],
|
51
|
+
[2, 3, 2, 3, 3, 2, 3, 2],
|
52
|
+
[3, 3, 3, 3, 3, 3, 3, 3],
|
53
|
+
],
|
54
|
+
// 3d lattice
|
55
|
+
[
|
56
|
+
[0, 2, 0, 2, 0, 2, 0, 2],
|
57
|
+
[1, 0, 1, 0, 1, 0, 1, 0],
|
58
|
+
[0, 2, 0, 2, 0, 2, 0, 2],
|
59
|
+
[1, 0, 2, 0, 2, 0, 1, 0],
|
60
|
+
[1, 0, 1, 0, 1, 0, 1, 0],
|
61
|
+
[0, 2, 0, 2, 0, 2, 0, 2],
|
62
|
+
[1, 0, 3, 0, 3, 0, 1, 0],
|
63
|
+
],
|
64
|
+
// full wall
|
65
|
+
[
|
66
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
67
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
68
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
69
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
70
|
+
],
|
71
|
+
// zig zag challenge
|
72
|
+
[
|
73
|
+
[1, 1, 1, 0, 0, 0, 0, 0],
|
74
|
+
[0, 0, 1, 1, 1, 0, 0, 0],
|
75
|
+
[0, 0, 0, 0, 1, 1, 1, 0],
|
76
|
+
[0, 0, 0, 0, 0, 0, 1, 1],
|
77
|
+
],
|
78
|
+
// triple jump
|
79
|
+
[
|
80
|
+
[0, 0, 1, 0, 0, 1, 0, 0],
|
81
|
+
[0, 0, 1, 0, 0, 1, 0, 0],
|
82
|
+
[1, 1, 1, 0, 0, 1, 1, 1],
|
83
|
+
],
|
84
|
+
// layered tunnel
|
85
|
+
[
|
86
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
87
|
+
[1, 0, 0, 2, 2, 0, 0, 1],
|
88
|
+
[1, 0, 0, 3, 3, 0, 0, 1],
|
89
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
90
|
+
],
|
91
|
+
// diagonal dash
|
92
|
+
[
|
93
|
+
[1, 1, 0, 0, 0, 0, 0, 0],
|
94
|
+
[0, 1, 1, 0, 0, 0, 0, 0],
|
95
|
+
[0, 0, 1, 1, 0, 0, 0, 0],
|
96
|
+
[0, 0, 0, 1, 1, 0, 0, 0],
|
97
|
+
[0, 0, 0, 0, 1, 1, 0, 0],
|
98
|
+
],
|
99
|
+
// wave rider
|
100
|
+
[
|
101
|
+
[1, 0, 0, 0, 0, 0, 0, 1],
|
102
|
+
[1, 1, 0, 0, 0, 0, 1, 1],
|
103
|
+
[0, 1, 1, 0, 0, 1, 1, 0],
|
104
|
+
[0, 0, 1, 1, 1, 1, 0, 0],
|
105
|
+
],
|
106
|
+
// forward momentum
|
107
|
+
[
|
108
|
+
[1, 1, 2, 2, 3, 3, 3, 3],
|
109
|
+
[1, 1, 2, 2, 3, 3, 3, 3],
|
110
|
+
[1, 1, 2, 2, 3, 3, 3, 3],
|
111
|
+
],
|
112
|
+
// spiral staircase
|
113
|
+
[
|
114
|
+
[1, 1, 1, 1, 2, 2, 3, 3],
|
115
|
+
[3, 3, 1, 1, 1, 2, 2, 2],
|
116
|
+
[2, 3, 3, 1, 1, 1, 1, 2],
|
117
|
+
[2, 2, 2, 3, 3, 1, 1, 1],
|
118
|
+
],
|
119
|
+
// hopscotch
|
120
|
+
[
|
121
|
+
[0, 1, 0, 1, 0, 1, 0, 1],
|
122
|
+
[0, 2, 0, 2, 0, 2, 0, 2],
|
123
|
+
[1, 0, 1, 0, 1, 0, 1, 0],
|
124
|
+
[2, 0, 2, 0, 2, 0, 2, 0],
|
125
|
+
],
|
126
|
+
// snake path
|
127
|
+
[
|
128
|
+
[1, 1, 1, 1, 0, 0, 0, 0],
|
129
|
+
[0, 0, 0, 1, 0, 0, 0, 0],
|
130
|
+
[0, 0, 0, 2, 0, 0, 0, 0],
|
131
|
+
[0, 0, 0, 3, 3, 3, 3, 3],
|
132
|
+
],
|
133
|
+
// diamond gate
|
134
|
+
[
|
135
|
+
[1, 1, 1, 0, 0, 1, 1, 1],
|
136
|
+
[1, 1, 0, 0, 0, 0, 1, 1],
|
137
|
+
[1, 0, 2, 0, 0, 2, 0, 1],
|
138
|
+
[0, 0, 0, 3, 3, 0, 0, 0],
|
139
|
+
[1, 0, 2, 0, 0, 2, 0, 1],
|
140
|
+
[1, 1, 0, 0, 0, 0, 1, 1],
|
141
|
+
[1, 1, 1, 0, 0, 1, 1, 1],
|
142
|
+
],
|
143
|
+
];
|
144
|
+
|
145
|
+
export default GAME_WALL_SHAPES;
|