@hytopia.com/examples 1.0.49 → 1.0.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.
Binary file
@@ -33,8 +33,36 @@
33
33
  <!-- Leaderboard -->
34
34
  <div class="leaderboard">
35
35
  <div class="leaderboard-title">Deathmatch</div>
36
- <div class="leaderboard-timer">0:00</div>
37
- <div class="leaderboard-players-count">Players: 0</div>
36
+ <div class="leaderboard-info-row">
37
+ <div class="leaderboard-timer">
38
+ <img src="{{CDN_ASSETS_URL}}/icons/clock.png" alt="Timer" class="leaderboard-info-icon">
39
+ <span class="leaderboard-timer-value">0:00</span>
40
+ </div>
41
+ <div class="leaderboard-players-count">
42
+ <img src="{{CDN_ASSETS_URL}}/icons/player.png" alt="Players" class="leaderboard-info-icon">
43
+ <span class="leaderboard-player-count-value">0</span>
44
+ </div>
45
+ </div>
46
+ <div class="leaderboard-mobile-summary">
47
+ <div class="leaderboard-summary-entry summary-top">
48
+ <div class="summary-label-with-icon">
49
+ <img src="{{CDN_ASSETS_URL}}/icons/crown-gold.png" class="summary-crown" alt="Top player">
50
+ <span class="summary-name summary-top-name">—</span>
51
+ </div>
52
+ <span class="summary-kills summary-top-kills">0</span>
53
+ </div>
54
+ <div class="leaderboard-summary-entry summary-second">
55
+ <div class="summary-label-with-icon">
56
+ <img src="{{CDN_ASSETS_URL}}/icons/crown-silver.png" class="summary-crown" alt="Second player">
57
+ <span class="summary-name summary-second-name">—</span>
58
+ </div>
59
+ <span class="summary-kills summary-second-kills">0</span>
60
+ </div>
61
+ <div class="leaderboard-summary-entry summary-self">
62
+ <span class="summary-name summary-self-name">You</span>
63
+ <span class="summary-kills summary-self-kills">0</span>
64
+ </div>
65
+ </div>
38
66
  <div class="leaderboard-header">
39
67
  <div class="header-name">Player</div>
40
68
  <div class="header-kills">Kills</div>
@@ -62,15 +90,17 @@
62
90
  <div class="exp-text">Unranked</div>
63
91
  </div>
64
92
 
65
- <div class="shield-bar">
66
- <div class="shield-bar-fill"></div>
67
- <img src="{{CDN_ASSETS_URL}}/icons/shield.png" alt="Shield Icon" class="shield-icon">
68
- <div class="shield-text">0</div>
69
- </div>
70
- <div class="health-bar">
71
- <div class="health-bar-fill"></div>
72
- <img src="{{CDN_ASSETS_URL}}/icons/heart.png" alt="Health Icon" class="health-icon">
73
- <div class="health-text">100</div>
93
+ <div class="health-shield-row">
94
+ <div class="health-bar">
95
+ <div class="health-bar-fill"></div>
96
+ <img src="{{CDN_ASSETS_URL}}/icons/heart.png" alt="Health Icon" class="health-icon">
97
+ <div class="health-text">100</div>
98
+ </div>
99
+ <div class="shield-bar">
100
+ <div class="shield-bar-fill"></div>
101
+ <img src="{{CDN_ASSETS_URL}}/icons/shield.png" alt="Shield Icon" class="shield-icon">
102
+ <div class="shield-text">0</div>
103
+ </div>
74
104
  </div>
75
105
  </div>
76
106
  </div>
@@ -176,6 +206,13 @@
176
206
  let gameEndTime = 0;
177
207
  let timerInterval;
178
208
  let isLoadExpUpdate = true; // Flag to track the first EXP update
209
+ let localPlayerUsername = '';
210
+ const summaryTopNameEl = document.querySelector('.summary-top-name');
211
+ const summaryTopKillsEl = document.querySelector('.summary-top-kills');
212
+ const summarySecondNameEl = document.querySelector('.summary-second-name');
213
+ const summarySecondKillsEl = document.querySelector('.summary-second-kills');
214
+ const summarySelfNameEl = document.querySelector('.summary-self-name');
215
+ const summarySelfKillsEl = document.querySelector('.summary-self-kills');
179
216
 
180
217
  function updateLeaderboard() {
181
218
  const leaderboardPlayers = document.querySelector('.leaderboard-players');
@@ -239,6 +276,35 @@
239
276
 
240
277
  leaderboardPlayers.appendChild(playerElement);
241
278
  });
279
+
280
+ updateLeaderboardSummary();
281
+ }
282
+
283
+ function updateLeaderboardSummary() {
284
+ if (
285
+ !document.body.classList.contains('mobile') ||
286
+ !summaryTopNameEl ||
287
+ !summaryTopKillsEl ||
288
+ !summarySecondNameEl ||
289
+ !summarySecondKillsEl ||
290
+ !summarySelfNameEl ||
291
+ !summarySelfKillsEl
292
+ ) {
293
+ return;
294
+ }
295
+
296
+ const entries = Object.entries(leaderboardKillCounts).sort((a, b) => b[1] - a[1]);
297
+ const [topName = '—', topKills = 0] = entries[0] ?? [];
298
+ const [secondName = '—', secondKills = 0] = entries[1] ?? [];
299
+ const yourName = localPlayerUsername || 'You';
300
+ const yourKills = localPlayerUsername ? (leaderboardKillCounts[localPlayerUsername] ?? 0) : 0;
301
+
302
+ summaryTopNameEl.textContent = topName || '—';
303
+ summaryTopKillsEl.textContent = `${topKills || 0} Kills`;
304
+ summarySecondNameEl.textContent = secondName || '—';
305
+ summarySecondKillsEl.textContent = `${secondKills || 0} Kills`;
306
+ summarySelfNameEl.textContent = yourName;
307
+ summarySelfKillsEl.textContent = `${yourKills || 0} Kills`;
242
308
  }
243
309
 
244
310
  function updateTimer() {
@@ -250,8 +316,10 @@
250
316
  const seconds = Math.floor((timeRemaining % 60000) / 1000);
251
317
  const formattedTime = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
252
318
 
253
- const timerElement = document.querySelector('.leaderboard-timer');
254
- timerElement.textContent = formattedTime;
319
+ const timerValue = document.querySelector('.leaderboard-timer-value');
320
+ if (timerValue) {
321
+ timerValue.textContent = formattedTime;
322
+ }
255
323
 
256
324
  // Stop the timer when it reaches zero
257
325
  if (timeRemaining <= 0) {
@@ -549,21 +617,29 @@
549
617
  }
550
618
 
551
619
  if (type === 'leaderboard-sync') {
552
- const { killCounts } = data;
620
+ const { killCounts, localPlayer } = data;
553
621
  leaderboardKillCounts = killCounts;
622
+ if (localPlayer) {
623
+ localPlayerUsername = localPlayer;
624
+ }
554
625
  updateLeaderboard();
555
626
  }
556
627
 
557
628
  if (type === 'leaderboard-update') {
558
- const { username, killCount } = data;
629
+ const { username, killCount, localPlayer } = data;
559
630
  leaderboardKillCounts[username] = killCount;
631
+ if (localPlayer) {
632
+ localPlayerUsername = localPlayer;
633
+ }
560
634
  updateLeaderboard();
561
635
  }
562
636
 
563
637
  if (type === 'players-count') {
564
638
  const { count } = data;
565
- const playersCount = document.querySelector('.leaderboard-players-count');
566
- playersCount.textContent = `Players: ${count}`;
639
+ const playersCount = document.querySelector('.leaderboard-player-count-value');
640
+ if (playersCount) {
641
+ playersCount.textContent = count;
642
+ }
567
643
  }
568
644
 
569
645
  if (type === 'materials') {
@@ -1141,6 +1217,7 @@
1141
1217
  border-radius: 3px;
1142
1218
  box-shadow: 0 0 10px rgba(230, 190, 40, 0.3);
1143
1219
  position: relative; /* Needed for absolute positioning of children */
1220
+ text-align: center;
1144
1221
  }
1145
1222
 
1146
1223
  .exp-bar-fill {
@@ -1358,6 +1435,7 @@
1358
1435
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
1359
1436
  border: 2px solid rgba(255, 255, 255, 0.2);
1360
1437
  z-index: 100;
1438
+ pointer-events: none;
1361
1439
  }
1362
1440
 
1363
1441
  .leaderboard-title {
@@ -1372,17 +1450,36 @@
1372
1450
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
1373
1451
  }
1374
1452
 
1375
- .leaderboard-timer {
1376
- text-align: center;
1377
- font-size: 16px;
1378
- font-weight: bold;
1453
+ .leaderboard-info-row {
1454
+ display: flex;
1455
+ justify-content: space-between;
1456
+ gap: 8px;
1379
1457
  margin-bottom: 10px;
1380
- padding: 3px;
1458
+ }
1459
+
1460
+ .leaderboard-info-row .leaderboard-timer,
1461
+ .leaderboard-info-row .leaderboard-players-count {
1462
+ flex: 1;
1463
+ display: flex;
1464
+ align-items: center;
1465
+ justify-content: center;
1466
+ gap: 6px;
1381
1467
  background: rgba(255, 255, 255, 0.1);
1382
1468
  border-radius: 3px;
1469
+ padding: 3px 6px;
1470
+ height: 20px;
1471
+ font-size: 15px;
1472
+ font-weight: bold;
1383
1473
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
1384
1474
  }
1385
1475
 
1476
+ .leaderboard-info-icon {
1477
+ width: 14px;
1478
+ height: 14px;
1479
+ object-fit: contain;
1480
+ display: block;
1481
+ }
1482
+
1386
1483
  .leaderboard-header {
1387
1484
  display: flex;
1388
1485
  justify-content: space-between;
@@ -1450,50 +1547,107 @@
1450
1547
  display: none;
1451
1548
  }
1452
1549
 
1550
+ .leaderboard-mobile-summary {
1551
+ display: none;
1552
+ gap: 4px;
1553
+ }
1554
+
1555
+ .leaderboard-summary-entry {
1556
+ display: flex;
1557
+ justify-content: space-between;
1558
+ align-items: center;
1559
+ padding: 4px 8px;
1560
+ background: rgba(255, 255, 255, 0.1);
1561
+ border-radius: 4px;
1562
+ font-weight: 600;
1563
+ font-size: 10px;
1564
+ }
1565
+
1566
+ .summary-label-with-icon {
1567
+ display: flex;
1568
+ align-items: center;
1569
+ gap: 6px;
1570
+ }
1571
+
1572
+ .summary-crown {
1573
+ width: 12px;
1574
+ height: 12px;
1575
+ }
1576
+
1577
+ .leaderboard-summary-entry .summary-name {
1578
+ letter-spacing: 0.4px;
1579
+ text-transform: uppercase;
1580
+ font-size: 10px;
1581
+ }
1582
+
1583
+ .leaderboard-summary-entry .summary-kills {
1584
+ font-size: 11px;
1585
+ }
1586
+
1453
1587
  /* Mobile UI */
1454
1588
  body.mobile .hud {
1589
+ top: 15px;
1455
1590
  left: 50%;
1456
1591
  transform: translateX(-50%);
1457
- bottom: 35px;
1592
+ bottom: auto;
1458
1593
  right: auto;
1459
1594
  }
1460
1595
 
1461
1596
  body.mobile .inventory-hud {
1462
- bottom: 30px;
1597
+ bottom: 28px;
1598
+ left: 24px;
1599
+ right: auto;
1600
+ top: auto;
1601
+ transform: none;
1602
+ display: flex;
1603
+ gap: 10px;
1463
1604
  }
1464
1605
 
1465
1606
  body.mobile .inventory-slot {
1466
- width: 45px;
1467
- height: 45px;
1468
- }
1469
-
1470
- body.mobile .slot-number {
1471
- font-size: 12px;
1472
- top: -16px;
1607
+ width: 50px;
1608
+ height: 50px;
1473
1609
  }
1474
1610
 
1611
+ body.mobile .slot-number,
1475
1612
  body.mobile .slot-name {
1476
- font-size: 8px;
1477
- bottom: -14px;
1613
+ display: none;
1478
1614
  }
1479
1615
 
1480
1616
  body.mobile .slot-quantity {
1481
1617
  font-size: 10px;
1482
1618
  }
1483
1619
 
1484
- body.mobile .shield-bar,
1485
- body.mobile .health-bar,
1486
1620
  body.mobile .exp-bar {
1621
+ width: 160px;
1622
+ height: 16px;
1623
+ margin-bottom: 8px;
1624
+ }
1625
+
1626
+ body.mobile .exp-text {
1627
+ font-size: 0.7em;
1628
+ }
1629
+
1630
+ body.mobile .shield-bar,
1631
+ body.mobile .health-bar {
1487
1632
  width: 120px;
1488
1633
  height: 16px;
1489
1634
  }
1490
1635
 
1491
1636
  body.mobile .shield-text,
1492
- body.mobile .health-text,
1493
- body.mobile .exp-text {
1637
+ body.mobile .health-text {
1494
1638
  font-size: 0.7em;
1495
1639
  }
1496
1640
 
1641
+ body.mobile .info-container {
1642
+ flex-direction: column;
1643
+ gap: 6px;
1644
+ }
1645
+
1646
+ body.mobile .health-shield-row {
1647
+ display: flex;
1648
+ gap: 10px;
1649
+ }
1650
+
1497
1651
  body.mobile .shield-icon,
1498
1652
  body.mobile .health-icon {
1499
1653
  width: 10px;
@@ -1505,31 +1659,57 @@
1505
1659
  height: 35px;
1506
1660
  }
1507
1661
 
1662
+ body.mobile .leaderboard {
1663
+ top: 20px;
1664
+ right: 20px;
1665
+ width: 180px;
1666
+ max-height: none;
1667
+ z-index: 120;
1668
+ }
1669
+
1508
1670
  body.mobile .leaderboard-title {
1509
1671
  font-size: 14px;
1510
1672
  }
1511
1673
 
1512
- body.mobile .leaderboard-timer {
1513
- font-size: 12px;
1674
+ body.mobile .leaderboard-timer,
1675
+ body.mobile .leaderboard-players-count {
1676
+ font-size: 11px;
1677
+ padding: 3px 4px;
1514
1678
  }
1515
1679
 
1516
- body.mobile .leaderboard-players-count {
1517
- display: none;
1518
- font-size: 12px;
1680
+ body.mobile .leaderboard-mobile-summary {
1681
+ display: flex;
1682
+ flex-direction: column;
1683
+ gap: 4px;
1519
1684
  }
1520
1685
 
1521
- body.mobile .leaderboard-header {
1522
- font-size: 10px;
1686
+ body.mobile .leaderboard-info-row {
1687
+ margin-bottom: 0px;
1688
+ }
1689
+
1690
+ body.mobile .leaderboard-mobile-summary .leaderboard-summary-entry:last-child {
1691
+ margin-bottom: 0;
1692
+ }
1693
+
1694
+ body.mobile .leaderboard-header,
1695
+ body.mobile .leaderboard-players {
1696
+ display: none;
1523
1697
  }
1524
1698
 
1525
1699
  body.mobile .leaderboard-player {
1526
1700
  font-size: 10px;
1527
1701
  }
1528
1702
 
1703
+ body.mobile .materials-amount {
1704
+ font-size: 14px;
1705
+ }
1706
+
1529
1707
  body.mobile .materials-counter {
1530
- right: 20px;
1531
- bottom: 115px;
1532
- font-size: 12px;
1708
+ left: 24px;
1709
+ bottom: 90px;
1710
+ top: auto;
1711
+ right: auto;
1712
+ font-size: 10px;
1533
1713
  }
1534
1714
 
1535
1715
  body.mobile .floating-number {
@@ -1545,31 +1725,34 @@
1545
1725
  }
1546
1726
 
1547
1727
  body.mobile .mobile-buttons-container {
1548
- display: flex;
1549
- gap: 10px;
1728
+ display: block;
1550
1729
  position: fixed;
1551
- bottom: 113px;
1552
- right: 118px;
1730
+ bottom: 30px;
1731
+ right: 50px;
1732
+ width: 250px;
1733
+ height: 230px;
1553
1734
  user-select: none;
1554
- pointer-events: auto !important;
1735
+ pointer-events: none;
1736
+ z-index: 1000;
1555
1737
  }
1556
1738
 
1557
1739
  body.mobile .mobile-button {
1558
- background-color: rgba(0, 0, 0, 0.5);
1740
+ position: absolute;
1741
+ background-color: rgba(0, 0, 0, 0.55);
1559
1742
  border-radius: 50%;
1560
1743
  align-items: center;
1561
1744
  justify-content: center;
1562
1745
  display: flex;
1563
- width: 45px;
1564
- height: 45px;
1746
+ width: 56px;
1747
+ height: 56px;
1565
1748
  -webkit-tap-highlight-color: transparent;
1566
- touch-action: none;
1749
+ touch-action: manipulation;
1567
1750
  user-select: none;
1568
1751
  transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
1569
1752
  will-change: transform, background-color;
1570
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
1753
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
1571
1754
  font-family: 'Inter', sans-serif;
1572
- font-size: 14px;
1755
+ font-size: 13px;
1573
1756
  font-weight: bold;
1574
1757
  color: rgba(255, 255, 255, 0.8);
1575
1758
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
@@ -1583,8 +1766,48 @@
1583
1766
  }
1584
1767
 
1585
1768
  body.mobile .mobile-button img {
1586
- width: 25px;
1587
- height: 25px;
1769
+ width: 22px;
1770
+ height: 22px;
1771
+ }
1772
+
1773
+ body.mobile #mobile-attack-button {
1774
+ width: 100px;
1775
+ height: 100px;
1776
+ bottom: 0;
1777
+ right: 0;
1778
+ }
1779
+
1780
+ body.mobile #mobile-attack-button img {
1781
+ width: 40px;
1782
+ height: 40px;
1783
+ }
1784
+
1785
+ body.mobile #mobile-jump-button {
1786
+ width: 66px;
1787
+ height: 66px;
1788
+ bottom: 110px;
1789
+ right: -10px;
1790
+ }
1791
+
1792
+ body.mobile #mobile-place-block-button {
1793
+ width: 62px;
1794
+ height: 62px;
1795
+ bottom: -20px;
1796
+ right: 105px;
1797
+ }
1798
+
1799
+ body.mobile #mobile-interact-button {
1800
+ width: 58px;
1801
+ height: 58px;
1802
+ bottom: 50px;
1803
+ right: 110px;
1804
+ }
1805
+
1806
+ body.mobile #mobile-reload-button {
1807
+ width: 58px;
1808
+ height: 58px;
1809
+ bottom: 100px;
1810
+ right: 65px;
1588
1811
  }
1589
1812
 
1590
1813
  body.mobile .rank-up-title {
@@ -17,9 +17,9 @@ import GunEntity from './GunEntity';
17
17
  import ItemEntity from './ItemEntity';
18
18
  import { SPAWN_REGION_AABB } from '../gameConfig';
19
19
 
20
- const AIM_JITTER_RADIANS = 0.035;
21
- const AIM_JITTER_RANDOM_MIN_SCALE = 0.75;
22
- const AIM_JITTER_RANDOM_MAX_SCALE = 2.1;
20
+ const AIM_JITTER_RADIANS = 0.055;
21
+ const AIM_JITTER_RANDOM_MIN_SCALE = 0.6;
22
+ const AIM_JITTER_RANDOM_MAX_SCALE = 2.6;
23
23
  const MELEE_ATTACK_RANGE = 2.4;
24
24
  const PICKAXE_SLOT_INDEX = 0;
25
25
  const LOOT_INTERACT_RANGE = 1.5;
@@ -28,6 +28,7 @@ const NAVIGATION_MIN_PROGRESS = 0.35;
28
28
  const MAX_VERTICAL_TARGET_DELTA = 12;
29
29
  const MELEE_LOOT_OPPORTUNITY_RANGE = 8;
30
30
  const BEHAVIOR_LOCK_MS = 450;
31
+ const REACTION_DELAY_MS = 180;
31
32
  const ENEMY_RETARGET_COOLDOWN_MS = 750;
32
33
  const ENEMY_LOST_GRACE_MS = 1400;
33
34
  const LOOT_RETARGET_COOLDOWN_MS = 550;
@@ -194,7 +195,7 @@ class BotStubPlayer extends EventRouter {
194
195
  export default class BotPlayerEntity extends GamePlayerEntity {
195
196
  private static readonly _botsByWorld: Map<number, Set<BotPlayerEntity>> = new Map();
196
197
  private static readonly _activeWorlds: Set<number> = new Set();
197
- private static readonly _maxBots = 6;
198
+ private static readonly _maxBots = 50; //5 + Math.floor(Math.random() * 4); // 5-8 inclusive
198
199
 
199
200
  public static ensureForWorld(world: World): void {
200
201
  const bots = this._botsByWorld.get(world.id) ?? new Set<BotPlayerEntity>();
@@ -292,6 +293,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
292
293
  private _lootForgetAt = 0;
293
294
  private _activeLootTargetId: number | undefined;
294
295
  private _lootOverrideUntil = 0;
296
+ private _nextReactionAt = 0;
295
297
 
296
298
  private constructor(driver: BotStubPlayer) {
297
299
  super(driver as unknown as Player);
@@ -552,6 +554,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
552
554
  this._enemyForgetAt = now + ENEMY_LOST_GRACE_MS;
553
555
  this._blockBreakTarget = undefined;
554
556
  this._blockBreakExpiresAt = 0;
557
+ this._nextReactionAt = now + REACTION_DELAY_MS + Math.random() * REACTION_DELAY_MS;
555
558
  }
556
559
 
557
560
  return;
@@ -562,6 +565,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
562
565
  (!current.isSpawned || current.isDead || now > this._enemyForgetAt)
563
566
  ) {
564
567
  this._targetEnemy = undefined;
568
+ this._nextReactionAt = 0;
565
569
  }
566
570
  }
567
571
 
@@ -676,6 +680,11 @@ export default class BotPlayerEntity extends GamePlayerEntity {
676
680
 
677
681
  const enemyPosition = this._targetEnemy.position;
678
682
  const distance = Math.sqrt(this._distanceSq(this.position, enemyPosition));
683
+ if (performance.now() < this._nextReactionAt) {
684
+ this._facePosition(enemyPosition, true, AIM_JITTER_RADIANS);
685
+ return;
686
+ }
687
+
679
688
  const gun = this._ensureBestWeaponEquipped();
680
689
 
681
690
  if (gun && gun.hasUsableAmmo()) {
@@ -786,7 +795,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
786
795
  const shouldJump = this._shouldAutoJump(target);
787
796
  if (shouldJump) {
788
797
  input.sp = true;
789
- this._jumpRetryDebounceAt = performance.now() + 400;
798
+ this._jumpRetryDebounceAt = performance.now() + 550;
790
799
  } else if (!this._hasHeadroom() && this.playerController.isGrounded) {
791
800
  input.sp = true;
792
801
  }
@@ -795,7 +804,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
795
804
  this._strafe(0);
796
805
  if (this.playerController.isGrounded && performance.now() > this._jumpRetryDebounceAt) {
797
806
  input.sp = true;
798
- this._jumpRetryDebounceAt = performance.now() + 400;
807
+ this._jumpRetryDebounceAt = performance.now() + 550;
799
808
  }
800
809
  }
801
810
 
@@ -806,7 +815,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
806
815
  const now = performance.now();
807
816
  if (now > this._strafeSwitchAt) {
808
817
  this._strafeDirection = this._strafeDirection === 1 ? -1 : 1;
809
- this._strafeSwitchAt = now + 1000 + Math.random() * 750;
818
+ this._strafeSwitchAt = now + 1500 + Math.random() * 1200;
810
819
  }
811
820
 
812
821
  const input = this.player.input as PlayerInput;
@@ -816,7 +825,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
816
825
  input.a = true;
817
826
  }
818
827
 
819
- if (deltaTimeMs > 0 && Math.random() < 0.02 && this.playerController.isGrounded) {
828
+ if (deltaTimeMs > 0 && Math.random() < 0.008 && this.playerController.isGrounded) {
820
829
  input.sp = true;
821
830
  }
822
831
  }
@@ -942,7 +951,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
942
951
  const now = performance.now();
943
952
  if (now > this._jumpRetryDebounceAt && this.playerController.isGrounded) {
944
953
  (this.player.input as PlayerInput).sp = true;
945
- this._jumpRetryDebounceAt = now + 400;
954
+ this._jumpRetryDebounceAt = now + 550;
946
955
  }
947
956
 
948
957
  if (!this._blockBreakTarget) {
@@ -1058,7 +1067,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
1058
1067
 
1059
1068
  this.applyImpulse(impulse);
1060
1069
  (this.player.input as PlayerInput).sp = true;
1061
- this._jumpRetryDebounceAt = performance.now() + 450;
1070
+ this._jumpRetryDebounceAt = performance.now() + 520;
1062
1071
 
1063
1072
  if (this._behaviorState === BotBehaviorState.LOOT) {
1064
1073
  this._targetLootEntity = undefined;
@@ -18,7 +18,6 @@ import {
18
18
  ITEM_SPAWNS,
19
19
  ITEM_SPAWNS_AT_START,
20
20
  ITEM_SPAWN_ITEMS,
21
- MINIMUM_PLAYERS_TO_START,
22
21
  SPAWN_REGION_AABB,
23
22
  RANK_WIN_EXP,
24
23
  } from '../gameConfig';
@@ -103,8 +102,6 @@ export default class GameManager {
103
102
  this.world.chatManager.sendBroadcastMessage('Game over! Starting the next round in 10 seconds...', 'FF0000');
104
103
 
105
104
  this._identifyWinningPlayer();
106
-
107
- BotPlayerEntity.despawnAll(this.world);
108
105
  this.refreshPlayerCount();
109
106
 
110
107
  // Clear any existing restart timer
@@ -214,8 +211,6 @@ export default class GameManager {
214
211
  private _cleanup() {
215
212
  if (!this.world) return;
216
213
 
217
- BotPlayerEntity.despawnAll(this.world);
218
-
219
214
  // Reset map to initial state
220
215
  this.world.loadMap(worldMap);
221
216
  this._spawnBedrock(this.world);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hytopia.com/examples",
3
- "version": "1.0.49",
3
+ "version": "1.0.51",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "",