squishjs 0.7.3 → 0.7.51

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/testapp.js DELETED
@@ -1,988 +0,0 @@
1
- const squishMap = {
2
- 'latest': require('squish-latest'),
3
- '0642': require('squish-0642'),
4
- '0633': require('squish-0633'),
5
- '0632': require('squish-0632'),
6
- '0631': require('squish-0631'),
7
- '063': require('squish-063'),
8
- '061': require('squish-061')
9
- };
10
-
11
- let { squish, unsquish, Colors } = squishMap['0633'];
12
-
13
- let bezelInfo;
14
-
15
- Colors = Colors.COLORS;
16
-
17
- const socketWorker = new Worker('socket.js');
18
- const canvas = document.getElementById("game");
19
-
20
- let playingSound;
21
- let currentBuf;
22
-
23
- let rendering = false;
24
-
25
- let aspectRatio;
26
-
27
- let mousePos;
28
- let clientWidth;
29
-
30
- let spectating;
31
-
32
- let hotClient;
33
-
34
- let performanceProfiling;
35
- let performanceData = [];
36
-
37
- const performanceDiv = document.getElementById('performance-data');
38
-
39
- const getClientInfo = () => {
40
- // s/o to Abdessalam Benharira - https://dev.to/itsabdessalam/detect-current-device-type-with-javascript-490j
41
- const userAgent = navigator.userAgent;
42
-
43
- const info = {};
44
-
45
- if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(userAgent)) {
46
- info.deviceType = "tablet";
47
- } else if (/Mobile|iP(hone|od)|Android|BlackBerry|IEMobile|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test(userAgent)) {
48
- info.deviceType = "mobile";
49
- } else if (navigator.maxTouchPoints && navigator.maxTouchPoints > 2) {
50
- info.deviceType = "tablet";
51
- } else {
52
- info.deviceType = "desktop";
53
- }
54
-
55
- const _clientWidth = window.innerWidth;
56
- const _clientHeight = window.innerHeight;
57
-
58
- let aspectRatio = null;
59
-
60
- if (_clientWidth && _clientHeight) {
61
- aspectRatio = _clientWidth / _clientHeight;
62
- }
63
-
64
- info.aspectRatio = aspectRatio;
65
-
66
- return info;
67
- };
68
-
69
- const sendClientInfo = () => {
70
- const clientInfo = getClientInfo();
71
- const initData = {
72
- clientInfo
73
- }
74
-
75
- // init with a specific game if the url contains a game parameter
76
- const gameRegex = new RegExp('\\?game=(\\S*)');
77
- console.log('lookin');
78
- if (window.location.search.match(gameRegex)) {
79
- const gameId = gameRegex.exec(window.location.search)[1];
80
- console.log('using game id ' + gameId);
81
- if (gameId) {
82
- initData.requestedGameId = gameId;
83
- }
84
- }
85
-
86
- socketWorker.postMessage(initData);
87
- };
88
-
89
- socketWorker.onmessage = (socketMessage) => {
90
- if (socketMessage.data.constructor === Object) {
91
- if (socketMessage.data.type === 'SOCKET_CLOSE') {
92
- rendering = false;
93
- }
94
- } else {
95
- currentBuf = new Uint8ClampedArray(socketMessage.data);
96
- if (currentBuf[0] == 2) {
97
- window.playerId = currentBuf[1];
98
- const aspectRatioX = currentBuf[2];
99
- const aspectRatioY = currentBuf[3];
100
- aspectRatio = {x: aspectRatioX, y: aspectRatioY};
101
-
102
- bezelInfo = {x: currentBuf[4], y: currentBuf[5]};
103
-
104
- const squishVersionLength = currentBuf[6];
105
- const squishVersionString = String.fromCharCode.apply(null, currentBuf.slice(7, 7 + currentBuf[6]));
106
- const squishVersion = squishMap[squishVersionString];
107
- squish = squishVersion.squish;
108
- unsquish = squishVersion.unsquish;
109
- Colors = squishVersion.Colors;
110
- initCanvas();
111
- } else if (currentBuf[0] == 1) {
112
- storeAssets(currentBuf);
113
- } else if (currentBuf[0] == 9) {
114
- // for now i know its just aspectRatio
115
- aspectRatio = {x: currentBuf[1], y: currentBuf[2]};
116
- initCanvas();
117
- } else if (currentBuf[0] === 5) {
118
- spectating = false;
119
- let a = String(currentBuf[1]);
120
- let b = String(currentBuf[2]).length > 1 ? currentBuf[2] : "0" + currentBuf[2];
121
- let newPort = a + b;
122
-
123
- socketWorker.postMessage({
124
- socketInfo: {
125
- hostname: window.location.hostname,
126
- playerId: window.playerId || null,
127
- port: Number(newPort),
128
- secure: window.location.host !== 'localhost' && window.isSecureContext
129
- }
130
- });
131
-
132
- } else if (currentBuf[0] === 6) {
133
- spectating = true;
134
- let a = String(currentBuf[1]);
135
- let b = String(currentBuf[2]).length > 1 ? currentBuf[2] : "0" + currentBuf[2];
136
- let newPort = a + b;
137
-
138
- socketWorker.postMessage({
139
- socketInfo: {
140
- hostname: window.location.hostname,
141
- playerId: window.playerId || null,
142
- port: Number(newPort),
143
- secure: window.location.host !== 'localhost' && window.isSecureContext,
144
- spectating
145
- }
146
- });
147
-
148
- } else if (currentBuf[0] === 7) {
149
- initPerformance();
150
- } else if (currentBuf[0] === 8) {
151
- let a = String(currentBuf[1]);
152
- let b = String(currentBuf[2]).length > 1 ? currentBuf[2] : "0" + currentBuf[2];
153
- let newPort = a + b;
154
-
155
- if (!hotClient) {
156
- const hostname = window.location.hostname;
157
- hotClient = new WebSocket(`ws://${hostname}:${newPort}`);
158
- hotClient.onopen = () => {
159
- console.log('hot client opened');
160
- }
161
-
162
- hotClient.onerror = (err) => {
163
- console.log('hot client err');
164
- console.log(err);
165
- }
166
-
167
- hotClient.onmessage = (msg) => {
168
- if (msg.data === 'reload') {
169
- location.reload();
170
- }
171
- }
172
- }
173
- } else if (currentBuf[0] == 3 && !rendering) {
174
- rendering = true;
175
- req();
176
- }
177
- }
178
- };
179
-
180
- const avgGraph = document.createElement('canvas');
181
- const lastNGraph = document.createElement('canvas');
182
-
183
- const avgGraphLabel = document.createElement('h3');
184
- const lastNGraphLabel = document.createElement('h3');
185
-
186
- const initPerformance = () => {
187
- if (!performanceProfiling) {
188
- performanceProfiling = true;
189
-
190
- const div1 = document.createElement('div');
191
- const div2 = document.createElement('div');
192
-
193
- div1.style = 'float: left; margin-right: 50px';
194
- div2.style = 'float: left';
195
-
196
- div1.appendChild(avgGraph);
197
- div2.appendChild(lastNGraph);
198
-
199
- performanceDiv.appendChild(div1);
200
- div1.appendChild(avgGraphLabel);
201
-
202
- performanceDiv.appendChild(div2);
203
- div2.appendChild(lastNGraphLabel);
204
- }
205
- };
206
-
207
- socketWorker.postMessage({
208
- socketInfo: {
209
- hostname: window.location.hostname,
210
- playerId: window.playerId || null,
211
- port: 7000,
212
- secure: window.location.host !== 'localhost' && window.isSecureContext
213
- }
214
- });
215
-
216
- sendClientInfo();
217
-
218
- let gamepad;
219
- let moving;
220
-
221
- window.playerId = null;
222
-
223
- let mouseDown = false;
224
- const keysDown = {};
225
-
226
- let audioCtx, source;
227
-
228
- const gameAssets = {};
229
- const imageCache = {};
230
-
231
- const gameDiv = document.getElementById('homegames-main');
232
- const divColor = Colors.BLACK;
233
- gameDiv.style.background = `rgba(${divColor[0]}, ${divColor[1]}, ${divColor[2]}, ${divColor[3]})`;
234
-
235
- const ctx = canvas.getContext("2d", {alpha: false});
236
-
237
- const initCanvas = () => {
238
- const maxWidth = window.innerWidth;
239
- const maxHeight = window.innerHeight;
240
-
241
- const canFitHeight = (maxWidth * aspectRatio.y / aspectRatio.x) <= maxHeight;
242
-
243
- let canvasHeight, canvasWidth;
244
-
245
- if (canFitHeight) {
246
- const width = window.innerWidth;
247
- canvasWidth = width;
248
- canvasHeight = Math.floor(width * (aspectRatio.y / aspectRatio.x));
249
- } else {
250
- // fit canvas to height
251
- const height = window.innerHeight;
252
- canvasWidth = Math.floor(height * (aspectRatio.x / aspectRatio.y));
253
- canvasHeight = height;
254
- }
255
-
256
- canvas.height = 2 * canvasHeight;
257
- canvas.width = 2 * canvasWidth;
258
- clientWidth = .5 * canvas.width;
259
- clientHeight = .5 * canvas.height;
260
- canvas.style.height = `${clientHeight}px`;
261
- canvas.style.width = `${clientWidth}px`;
262
- };
263
-
264
- const storeAssets = (buf) => {
265
- let i = 0;
266
-
267
- while (buf && i < buf.length) {
268
- const frameType = buf[i];
269
-
270
- if (frameType === 1) {
271
- const assetType = buf[i + 1];
272
- // image
273
- if (assetType === 1) {
274
- const payloadLengthBase32 = String.fromCharCode.apply(null, buf.slice(i + 2, i + 12));
275
- const payloadLength = parseInt(payloadLengthBase32, 36);
276
-
277
- const payloadKeyRaw = buf.slice(i + 12, i + 12 + 32);
278
- const payloadData = buf.slice(i + 12 + 32, i + 12 + payloadLength);
279
- const payloadKey = String.fromCharCode.apply(null, payloadKeyRaw.filter(k => k));
280
- let imgBase64String = "";
281
- for (let i = 0; i < payloadData.length; i++) {
282
- imgBase64String += String.fromCharCode(payloadData[i]);
283
- }
284
- const imgBase64 = btoa(imgBase64String);
285
- gameAssets[payloadKey] = {"type": "image", "data": "data:image/jpeg;base64," + imgBase64};
286
- i += 12 + payloadLength;
287
- } else {
288
- // audio
289
- const payloadLengthBase32 = String.fromCharCode.apply(null, buf.slice(i + 2, i + 12));
290
- const payloadLength = parseInt(payloadLengthBase32, 36);
291
- const payloadKeyRaw = buf.slice(i + 12, i + 12 + 32);
292
- const payloadData = buf.slice(i + 12 + 32, i + 12 + payloadLength);
293
- const payloadKey = String.fromCharCode.apply(null, payloadKeyRaw.filter(k => k));
294
- if (!audioCtx) {
295
- gameAssets[payloadKey] = {"type": "audio", "data": payloadData.buffer, "decoded": false};
296
- } else {
297
- /// audioCtx.decodeAudioData(payloadData.buffer, (buffer) => {
298
- // gameAssets[payloadKey] = {"type": "audio", "data": buffer, "decoded": true};
299
- // });
300
- }
301
-
302
- i += 12 + payloadLength;
303
- }
304
- }
305
- }
306
- }
307
-
308
- let thingIndices = [];
309
-
310
- function renderBuf(buf) {
311
- ctx.clearRect(0, 0, canvas.width, canvas.height);
312
- let i = 0;
313
- thingIndices = [];
314
-
315
- while (buf && i < buf.length) {
316
- const frameType = buf[i];
317
-
318
- const frameSize = buf[i + 1];
319
-
320
- let bufIndex = i + 2;
321
- let thing = unsquish(buf.slice(i, i + frameSize));
322
-
323
- if (!thing.coordinates2d && thing.input && thing.text) {
324
- const maxTextSize = Math.floor(canvas.width);
325
- const fontSize = (thing.text.size / 100) * maxTextSize;
326
- ctx.font = fontSize + "px sans-serif";
327
-
328
- const textInfo = ctx.measureText(thing.text.text);
329
- let textStartX = thing.text.x * canvas.width / 100;
330
-
331
- if (thing.text.align && thing.text.align == 'center') {
332
- textStartX -= textInfo.width / 2;
333
- }
334
-
335
- textStartX = textStartX / canvas.width * 100;
336
- const textHeight = textInfo.actualBoundingBoxDescent - textInfo.actualBoundingBoxAscent;
337
- const textWidthPercent = textInfo.width / canvas.width * 100;
338
- const textHeightPercent = textHeight / canvas.height * 100;
339
-
340
- const clickableChunk = [
341
- !!thing.handleClick,
342
- thing.input && thing.input.type,
343
- thing.id,
344
- [textStartX, thing.text.y, textStartX + textWidthPercent, thing.text.y, textStartX + textWidthPercent, thing.text.y + textHeightPercent, textStartX, thing.text.y + textHeightPercent, textStartX, thing.text.y]
345
- ];
346
- thingIndices.push(clickableChunk);
347
- } else if (thing.coordinates2d !== null && thing.coordinates2d !== undefined) {// && thing.flll !== null) {
348
- const clickableChunk = [
349
- !!thing.handleClick,
350
- thing.input && thing.input.type,
351
- thing.id,
352
- thing.coordinates2d
353
- ];
354
-
355
- thingIndices.push(clickableChunk);
356
-
357
- if (thing.effects && thing.effects.shadow) {
358
- const shadowColor = thing.effects.shadow.color;
359
- ctx.shadowColor = "rgba(" + shadowColor[0] + "," + shadowColor[1] + "," + shadowColor[2] + "," + shadowColor[3] + ")";
360
- if (thing.effects.shadow.blur) {
361
- ctx.shadowBlur = thing.effects.shadow.blur;
362
- }
363
- }
364
-
365
- if (thing.color) {
366
- ctx.globalAlpha = thing.color[3] / 255;
367
- }
368
- if (thing.fill !== null && thing.fill !== undefined) {
369
- ctx.fillStyle = "rgba(" + thing.fill[0] + "," + thing.fill[1] + "," + thing.fill[2] + "," + thing.fill[3] + ")";
370
- }
371
- if (thing.border !== undefined && thing.border !== null) {
372
- ctx.lineWidth = (thing.border / 255) * .1 * canvas.width;
373
- ctx.strokeStyle = "rgba(" + thing.color[0] + "," + thing.color[1] + "," + thing.color[2] + "," + thing.color[3] + ")";
374
- }
375
-
376
- if (thing.coordinates2d !== null && thing.coordinates2d !== undefined) {
377
- ctx.beginPath();
378
-
379
- ctx.moveTo(thing.coordinates2d[0] * canvas.width / 100, thing.coordinates2d[1] * canvas.height / 100);
380
- for (let i = 2; i < thing.coordinates2d.length; i+=2) {
381
- ctx.lineTo(canvas.width / 100 * thing.coordinates2d[i], thing.coordinates2d[i+1] * canvas.height / 100);
382
- }
383
-
384
- if (thing.fill !== undefined && thing.fill !== null) {
385
- ctx.fill();
386
- }
387
-
388
- if (thing.border !== undefined && thing.border !== null) {
389
- ctx.stroke();
390
- }
391
- }
392
- ctx.shadowColor = null;
393
- ctx.shadowBlur = 0;
394
- ctx.lineWidth = 0;
395
- ctx.strokeStyle = null;
396
- }
397
-
398
- if (thing.text) {
399
- ctx.globalAlpha = thing.text.color[3] / 255;
400
- ctx.fillStyle = `rgba(${thing.text.color[0]}, ${thing.text.color[1]}, ${thing.text.color[2]}, ${thing.text.color[3]})`;
401
- const maxTextSize = Math.floor(canvas.width);
402
- const fontSize = (thing.text.size / 100) * maxTextSize;
403
- ctx.font = fontSize + "px sans-serif";
404
- if (thing.text.align) {
405
- ctx.textAlign = thing.text.align;
406
- }
407
- ctx.textBaseline = "top";
408
- ctx.fillText(thing.text.text, thing.text.x * canvas.width/ 100, thing.text.y * canvas.height / 100);
409
- }
410
-
411
- if (thing.asset) {
412
- const assetKey = Object.keys(thing.asset)[0];
413
-
414
- if (gameAssets[assetKey] && gameAssets[assetKey]["type"] === "audio") {
415
- if (!playingSound && audioCtx && gameAssets[assetKey].decoded) {
416
- source = audioCtx.createBufferSource();
417
- source.connect(audioCtx.destination);
418
- source.buffer = gameAssets[assetKey].data;
419
- source.onended = () => {
420
- playingSound = false;
421
- }
422
- source.start(0);
423
- playingSound = true;
424
- } else if (!playingSound && audioCtx) {
425
- console.warn("Cant play audio");
426
- }
427
- } else {
428
- const asset = thing.asset[assetKey];
429
- let image;
430
-
431
- if (imageCache[assetKey] && imageCache[assetKey] !== 'loading') {
432
- image = imageCache[assetKey];
433
- image.width = asset.size.x / 100 * canvas.width;
434
- image.height = asset.size.y / 100 * canvas.height;
435
- if (thing.effects && thing.effects.shadow) {
436
- const shadowColor = thing.effects.shadow.color;
437
- ctx.shadowColor = "rgba(" + shadowColor[0] + "," + shadowColor[1] + "," + shadowColor[2] + "," + shadowColor[3] + ")";
438
- if (thing.effects.shadow.blur) {
439
- ctx.shadowBlur = thing.effects.shadow.blur;
440
- }
441
- }
442
-
443
-
444
- ctx.drawImage(image, (asset.pos.x / 100) * canvas.width,
445
- (asset.pos.y / 100) * canvas.height, image.width, image.height);
446
- } else if (!imageCache[assetKey]) {
447
- image = new Image(asset.size.x / 100 * canvas.width, asset.size.y / 100 * canvas.height);
448
- imageCache[assetKey] = 'loading';
449
- image.onload = () => {
450
- imageCache[assetKey] = image;
451
- if (thing.effects && thing.effects.shadow) {
452
- const shadowColor = thing.effects.shadow.color;
453
- ctx.shadowColor = "rgba(" + shadowColor[0] + "," + shadowColor[1] + "," + shadowColor[2] + "," + shadowColor[3] + ")";
454
- if (thing.effects.shadow.blur) {
455
- ctx.shadowBlur = thing.effects.shadow.blur;
456
- }
457
- }
458
-
459
- ctx.drawImage(image, (asset.pos.x / 100) * canvas.width,
460
- (asset.pos.y / 100) * canvas.height, image.width, image.height);
461
- };
462
-
463
- if (gameAssets[assetKey]) {
464
- image.src = gameAssets[assetKey].data;
465
- }
466
- }
467
- }
468
-
469
- }
470
-
471
- i += frameSize;
472
-
473
- ctx.globalAlpha = 1;
474
- }
475
- }
476
-
477
- let gamepads;
478
-
479
- const getGamepadMappings = (gamepadId) => {
480
- if (gamepadId.indexOf('Xbox 360') >= 0 || gamepadId.indexOf('Xbox One') >= 0) {
481
- const leftStickXIndex = 0;
482
- const leftStickYIndex = 1;
483
-
484
- const rightStickXIndex = 2;
485
- const rightStickYIndex = 3;
486
-
487
- const stickInputThreshold = 0.2;
488
-
489
- const aButtonIndex = 0;
490
- const bButtonIndex = 1;
491
- const xButtonIndex = 2;
492
- const yButtonIndex = 3;
493
-
494
- const stickMappings = {
495
- [leftStickXIndex]: (val) => {
496
- if (Math.abs(val) >= stickInputThreshold) {
497
- if (val < 0) {
498
- keydown('a');
499
- keysDown['a'] = true;
500
- } else {
501
- keydown('d');
502
- keysDown['d'] = true;
503
- }
504
- } else {
505
- keysDown['a'] = false;
506
- keysDown['d'] = false;
507
- }
508
- },
509
- [leftStickYIndex]: (val) => {
510
- if (Math.abs(val) >= stickInputThreshold) {
511
- if (val < 0) {
512
- keydown('w');
513
- keysDown['w'] = true;
514
- } else {
515
- keydown('s');
516
- keysDown['s'] = true;
517
- }
518
- } else {
519
- keysDown['w'] = false;
520
- keysDown['s'] = false;
521
- }
522
- },
523
- [rightStickXIndex]: (val) => {
524
- if (Math.abs(val) >= stickInputThreshold) {
525
- if (val < 0) {
526
- keydown('ArrowLeft');
527
- keysDown['ArrowLeft'] = true;
528
- } else {
529
- keydown('ArrowRight');
530
- keysDown['ArrowRight'] = true;
531
- }
532
- } else {
533
- keysDown['ArrowLeft'] = false;
534
- keysDown['ArrowRight'] = false;
535
- }
536
- },
537
- [rightStickYIndex]: (val) => {
538
- if (Math.abs(val) >= stickInputThreshold) {
539
- if (val < 0) {
540
- keydown('ArrowUp');
541
- keysDown['ArrowUp'] = true;
542
- } else {
543
- keydown('ArrowDown');
544
- keysDown['ArrowDown'] = true;
545
- }
546
- } else {
547
- keysDown['ArrowDown'] = false;
548
- keysDown['ArrowUp'] = false;
549
- }
550
- }
551
- };
552
-
553
- const buttonMappings = {
554
- [aButtonIndex]: {
555
- press: () => {
556
- console.log('a');
557
- },
558
- depress: () => {
559
- console.log(':(');
560
- }
561
- },
562
- [bButtonIndex]: {
563
- press: () => {
564
- console.log('b');
565
- },
566
- depress: () => {
567
- console.log('no b');
568
- }
569
- },
570
- [xButtonIndex]: {
571
- press: () => {
572
- console.log('x');
573
- },
574
- depress: () => {
575
- console.log('no x');
576
- }
577
- },
578
- [yButtonIndex]: {
579
- press: () => {
580
- console.log('y');
581
- },
582
- depress: () => {
583
- console.log('no y');
584
- }
585
-
586
- }
587
- }
588
-
589
- return {
590
- stickMappings,
591
- buttonMappings
592
- }
593
- }
594
- };
595
-
596
- const gamepadsPressed = {};
597
-
598
- const getActiveGamepads = (gamepads) => {
599
- const activeGamepads = new Map();
600
-
601
- for (let gamepadIndex = 0; gamepadIndex < gamepads.length; gamepadIndex++) {
602
- const gamepad = gamepads[gamepadIndex];
603
- activeGamepads.set(gamepadIndex, gamepad);
604
- }
605
-
606
- return activeGamepads;
607
- };
608
-
609
- let clickStopper;
610
-
611
- function req() {
612
- if (!rendering) {
613
- return;
614
- }
615
-
616
- if (performanceProfiling) {
617
- performanceData.push({start: Date.now()});
618
- }
619
-
620
- gamepads = navigator.getGamepads();
621
-
622
- Object.keys(keysDown).filter(k => keysDown[k]).forEach(k => keydown(k));
623
-
624
- const activeGamepads = getActiveGamepads(gamepads);
625
-
626
- if (activeGamepads.length) {
627
- activeGamepads.forEach((gamepadIndex, gamepad) => {
628
- if (!gamepadsPressed.hasOwnProperty(gamepadIndex)) {
629
- gamepadsPressed[gamepadIndex] = {};
630
- }
631
- const inputMappings = getGamepadMappings(gamepad.id);
632
- if (inputMappings) {
633
- for (let stickIndex in inputMappings.stickMappings) {
634
- inputMappings.stickMappings[stickIndex](gamepad.axes[stickIndex]);
635
- }
636
-
637
- for (let buttonIndex in inputMappings.buttonMappings) {
638
- if (!gamepadsPressed[gamepadIndex].hasOwnProperty(buttonIndex)) {
639
- gamepadsPressed[gamepadIndex][buttonIndex] = false;
640
- }
641
- if (gamepad.buttons[buttonIndex].pressed && !gamepadsPressed[gamepadIndex][buttonIndex]) {
642
- gamepadsPressed[gamepadIndex][buttonIndex] = true;
643
- inputMappings.buttonMappings[buttonIndex].press();
644
- } else if (!gamepad.buttons[buttonIndex].pressed && gamepadsPressed[gamepadIndex][buttonIndex]) {
645
- gamepadsPressed[gamepadIndex][buttonIndex] = false;
646
- inputMappings.buttonMappings[buttonIndex].depress();
647
- }
648
- }
649
- }
650
- });
651
- }
652
-
653
- if (mousePos) {
654
- const clickInfo = canClick(mousePos[0], mousePos[1]);//e.clientX, e.clientY);
655
-
656
- if (mouseDown && !clickStopper) {
657
- click(clickInfo);
658
- clickStopper = setTimeout(() => {
659
- clickStopper = null;
660
- }, 30);
661
- }
662
-
663
-
664
- if (clickInfo.isClickable || clickInfo.action) {
665
- canvas.style.cursor = 'pointer';
666
- } else {
667
- canvas.style.cursor = 'initial';
668
- }
669
-
670
- mousePos = null;
671
- }
672
-
673
- currentBuf && currentBuf.length > 1 && currentBuf[0] == 3 && renderBuf(currentBuf);
674
-
675
- if (performanceProfiling) {
676
- const currentRender = performanceData[performanceData.length - 1];
677
- currentRender.end = Date.now();
678
- const renderTime = currentRender.end - currentRender.start;
679
- // performanceDiv.innerHTML = `Last render: ${renderTime}ms`;
680
- if (performanceData.length % 60 === 0) {
681
- updatePerfGraphs();
682
- }
683
- }
684
-
685
- window.requestAnimationFrame(req);
686
- }
687
-
688
- let graphData = [];
689
-
690
- const updatePerfGraphs = () => {
691
- const startFrame = performanceData.length - 60; //performanceData[performanceData.length - 60];
692
- const endFrame = performanceData.length - 1;//performanceData[performanceData.length - 1];
693
- let sum = 0;
694
- for (let i = startFrame; i <= endFrame; i++) {
695
- sum += (performanceData[i].end - performanceData[i].start);
696
- }
697
- const avgRenderTime = sum / 60;
698
- const lastNFrames = performanceData[endFrame].end - performanceData[startFrame].start;
699
-
700
- graphData.push({
701
- avgRenderTime,
702
- lastNFrames
703
- });
704
-
705
- const makeDot = (_canvas, _ctx, x, y) => {
706
- const maxY = _canvas.height;
707
- const maxX = _canvas.width;
708
- const _x = 5 + ((x / 100) * maxX);
709
- const _y = (y / 100) * maxY;
710
- _ctx.fillRect(_x, _y, 5, 5);
711
- }
712
-
713
- const avgGraphCtx = avgGraph.getContext("2d", {alpha: false});
714
- const lastNGraphCtx = lastNGraph.getContext("2d", {alpha: false});
715
-
716
- avgGraphCtx.clearRect(0, 0, avgGraph.width, avgGraph.height);
717
- lastNGraphCtx.clearRect(0, 0, lastNGraph.width, lastNGraph.height);
718
-
719
- avgGraphCtx.fillStyle = 'rgba(226, 114, 91, 255)';
720
- lastNGraphCtx.fillStyle = 'rgba(255, 192, 203, 255)';
721
-
722
- avgGraphCtx.fillRect(0, 0, avgGraph.width, avgGraph.height);
723
- lastNGraphCtx.fillRect(0, 0, lastNGraph.width, lastNGraph.height);
724
-
725
- avgGraphCtx.fillStyle = "rgba(255, 0, 0, 255)";
726
- lastNGraphCtx.fillStyle = "rgba(0, 255, 0, 255)";
727
-
728
- if (graphData.length > 10) {
729
- graphData = graphData.slice(graphData.length - 10, graphData.length);
730
- }
731
-
732
- avgGraphLabel.innerHTML = avgRenderTime.toFixed(2) + ' ms/render';
733
- lastNGraphLabel.innerHTML = Math.floor(1000 / (lastNFrames / 60)) + ' fps';
734
-
735
- for (let i = 0; i < graphData.length; i++) {
736
- const fps = 1000 / (graphData[i].lastNFrames / 60);
737
- makeDot(avgGraph, avgGraphCtx, i * 10, 100 - (10 * (graphData[i].avgRenderTime)));
738
- makeDot(lastNGraph, lastNGraphCtx, i * 10, 100 - (fps));
739
- }
740
- };
741
-
742
- const click = function(clickInfo = {}) {
743
- if (!mousePos) {
744
- return;
745
- }
746
- const x = mousePos[0];
747
- const y = mousePos[1];
748
- const clickX = (x - canvas.offsetLeft) / clientWidth * 100;//) - canvas.offsetLeft;
749
- const clickY = y / clientHeight * 100;
750
-
751
- if (clickInfo.action) {
752
- if (clickInfo.action === 'text') {
753
- // mouseup doesnt fire when you call prompt
754
- mouseDown = false;
755
- const textInput = prompt('Input text');
756
- socketWorker.postMessage(JSON.stringify({
757
- type: 'input',
758
- input: textInput,
759
- nodeId: clickInfo.nodeId
760
- }));
761
- } else if (clickInfo.action === 'file') {
762
- mouseDown = false;
763
- const inputEl = document.getElementById('file-input');
764
- inputEl.click();
765
- inputEl.onchange = (e) => {
766
- if (inputEl.files.length > 0) {
767
- const fileReader = new FileReader();
768
- fileReader.onload = (data) => {
769
- socketWorker.postMessage(JSON.stringify({
770
- type: 'input',
771
- // this is absolutely the wrong way to do this (????)
772
- input: new Uint8Array(fileReader.result),
773
- nodeId: clickInfo.nodeId
774
- }));
775
- };
776
- fileReader.readAsArrayBuffer(inputEl.files[0]);
777
- }
778
- };
779
- }
780
- } else {
781
- if (clickX <= 100 && clickY <= 100) {
782
- const payload = {type: "click", data: {x: clickX, y: clickY}};
783
- socketWorker.postMessage(JSON.stringify(payload));
784
- }
785
- }
786
- };
787
-
788
- const keydown = function(key) {
789
- const payload = {type: "keydown", key: key};
790
- socketWorker.postMessage(JSON.stringify(payload));
791
- };
792
-
793
- const keyup = function(key) {
794
- const payload = {type: "keyup", key: key};
795
- socketWorker.postMessage(JSON.stringify(payload));
796
- };
797
-
798
- const unlock = () => {
799
- if (!audioCtx) {
800
- audioCtx = new (window.AudioContext || window.webkitAudioContext)();
801
- if (audioCtx.state === "suspended") {
802
- audioCtx.resume();
803
- }
804
- for (const key in gameAssets) {
805
- if (gameAssets[key]["type"] === "audio" && !gameAssets[key]["decoded"]) {
806
- audioCtx.decodeAudioData(gameAssets[key].data, (buffer) => {
807
- gameAssets[key].data = buffer;
808
- gameAssets[key].decoded = true;
809
- });
810
- }
811
- }
812
- }
813
- };
814
-
815
- document.addEventListener("touchstart", unlock, false);
816
-
817
- const canClick = (x, y) => {
818
- let isClickable = false;
819
- let action = null;
820
- let nodeId = null;
821
-
822
- if (x < canvas.offsetLeft - window.scrollLeft) {
823
- return false;
824
- }
825
-
826
- const translatedX = x - canvas.offsetLeft - window.scrollX;
827
- const translatedY = y - window.scrollY;
828
-
829
- const xPercentage = 100 * translatedX / clientWidth;
830
- const yPercentage = 100 * translatedY / clientHeight;
831
-
832
- const bezelTop = bezelInfo.y / 2;
833
- const bezelBottom = 100 - (bezelInfo.y / 2);
834
-
835
- const bezelLeft = bezelInfo.x / 2;
836
- const bezelRight = 100 - (bezelInfo.x / 2);
837
-
838
- if ( spectating && (xPercentage > bezelLeft && xPercentage < bezelRight) && (yPercentage > bezelTop && yPercentage < bezelBottom) ) {
839
- return false;
840
- }
841
-
842
- for (const chunkIndex in thingIndices) {
843
- const clickableIndexChunk = thingIndices[chunkIndex];
844
-
845
- let vertices = clickableIndexChunk[3];
846
- if (!vertices || !vertices.length) {
847
- continue;
848
- }
849
- // TODO: fix this hack
850
- if (!vertices[0].length) {
851
- let verticesSwp = new Array(vertices.length / 2);
852
- for (let i = 0; i < vertices.length; i+=2) {
853
- verticesSwp[i/2] = [vertices[i], vertices[i+1]];
854
- }
855
- vertices = verticesSwp;
856
- }
857
- let isInside = false;
858
-
859
- let minX = translateX(vertices[0][0]);
860
- let maxX = translateX(vertices[0][0]);
861
- let minY = translateY(vertices[0][1]);
862
- let maxY = translateY(vertices[0][1]);
863
-
864
- for (let i = 1; i < vertices.length; i++) {
865
- const vert = vertices[i];
866
- minX = Math.min(translateX(vert[0]), minX);
867
- maxX = Math.max(translateX(vert[0]), maxX);
868
- minY = Math.min(translateY(vert[1]), minY);
869
- maxY = Math.max(translateY(vert[1]), maxY);
870
- }
871
-
872
- if (!(x < minX || x > maxX || y < minY || y > maxY)) {
873
- let i = 0;
874
- let j = vertices.length - 1;
875
- for (i, j; i < vertices.length; j=i++) {
876
- if ((translateY(vertices[i][1]) > y) != (translateY(vertices[j][1]) > y) &&
877
- x < (translateX(vertices[j][0]) - translateX(vertices[i][0])) * (y - translateY(vertices[i][1])) / (translateY(vertices[j][1]) - translateY(vertices[i][1])) + translateX(vertices[i][0])) {
878
- isInside = !isInside;
879
- }
880
- }
881
- }
882
-
883
- if (isInside) {
884
- isClickable = clickableIndexChunk[0];
885
- action = clickableIndexChunk[1];
886
- nodeId = clickableIndexChunk[2];
887
- }
888
-
889
-
890
- // const intersects = (
891
- // x >= clickableIndexChunk[3] &&
892
- // x <= clickableIndexChunk[4]
893
- // ) && (
894
- // y >= clickableIndexChunk[5] &&
895
- // y <= clickableIndexChunk[6]) ;
896
- // if (intersects) {
897
- // isClickable = clickableIndexChunk[0];
898
- // action = clickableIndexChunk[1];
899
- // nodeId = clickableIndexChunk[2];
900
- // }
901
- }
902
-
903
- return {
904
- isClickable,
905
- action,
906
- nodeId
907
- }
908
- };
909
-
910
- const translateX = (x) => {
911
- const translated = (x * clientWidth / 100) + canvas.offsetLeft + window.scrollX;
912
- return translated;
913
- };
914
- const translateY = (y) => {
915
- return (y * clientHeight / 100) + canvas.offsetTop + window.scrollY;
916
- };
917
-
918
- window.addEventListener("mousedown", function(e) {
919
- mouseDown = true;
920
- mousePos = [e.clientX, e.clientY];
921
- unlock();
922
- // const clickInfo = canClick(mousePos[0], mousePos[1]);//e.clientX, e.clientY);
923
- // click(clickInfo);//e.clientX + window.scrollX, e.clientY + window.scrollY);
924
- });
925
-
926
- window.addEventListener("mouseup", function(e) {
927
- mouseDown = false;
928
- });
929
-
930
- canvas.addEventListener("mousemove", function(e) {
931
- });
932
-
933
- window.addEventListener("touchstart", function(e) {
934
- e.preventDefault();
935
- mouseDown = true;
936
- mousePos = [e.touches["0"].clientX + window.scrollX, e.touches["0"].clientY + window.scrollY];
937
- // const clickInfo = canClick(mousePos[0], mousePos[1]);//e.clientX, e.clientY);
938
- // click(clickInfo);
939
- });
940
-
941
- canvas.addEventListener("touchmove", function(e) {
942
- e.preventDefault();
943
- mouseDown = true;
944
- mousePos = [e.touches["0"].clientX + window.scrollX, e.touches["0"].clientY + window.scrollY];
945
- });
946
-
947
- window.addEventListener('touchend', () => {
948
- mouseDown = false;
949
- });
950
-
951
- function keyMatters(event) {
952
- // Key code values 36-40 are the arrow keys
953
- return event.key.length == 1 && event.key >= " " && event.key <= "z" || event.keyCode >= 36 && event.keyCode <= 40 || event.key === "Meta" || event.key == "Backspace";
954
- }
955
-
956
- function isMobile() {
957
- return /Android/i.test(navigator.userAgent);
958
- }
959
-
960
- if (isMobile()) {
961
- } else {
962
- document.addEventListener("keydown", function(e) {
963
- if (keyMatters(e) && !keysDown["Meta"]) {
964
- e.preventDefault();
965
- keydown(e.key);
966
- keysDown[e.key] = true;
967
- }
968
- });
969
- document.addEventListener("keyup", function(e) {
970
- if (keyMatters(e)) {
971
- e.preventDefault();
972
- keyup(e.key);
973
- keysDown[e.key] = false;
974
- }
975
- });
976
- }
977
-
978
- window.addEventListener('mousemove', (e) => {
979
- mousePos = [e.clientX + window.scrollX, e.clientY + window.scrollY];
980
- });
981
-
982
- window.addEventListener('resize', () => {
983
- initCanvas(window.gameWidth, window.gameHeight);
984
- currentBuf && currentBuf.length > 1 && currentBuf[0] == 3 && renderBuf(currentBuf);
985
- sendClientInfo();
986
- });
987
-
988
-