reaper-arcade-hub 2.0.8 → 2.1.0

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/index.html CHANGED
@@ -58,8 +58,8 @@
58
58
  </div>
59
59
  </div>
60
60
 
61
- <!-- Key Gatekeeper Modal (In-Page Clean UI) -->
62
- <div id="key-gate-modal" class="admin-modal" style="z-index: 99998; background: radial-gradient(circle at center, #07152b 0%, #02050a 100%);">
61
+ <!-- Key Gatekeeper Modal (Hard Wall - Blocks All Interaction) -->
62
+ <div id="key-gate-modal" style="display: none; position: fixed; inset: 0; width: 100vw; height: 100vh; background: #02050a; z-index: 999999999; align-items: center; justify-content: center; padding: 1.5rem; flex-direction: column; pointer-events: all; user-select: none;">
63
63
  <div class="admin-window" style="max-width: 480px; text-align: center; border-color: var(--blue-primary); box-shadow: 0 0 45px var(--blue-glow); padding: 2.5rem 2rem;">
64
64
  <div style="font-family: var(--font-logo); font-size: 3.5rem; color: #fff; font-weight: 900; margin-bottom: 0.25rem; letter-spacing: 0.1em;">reaper</div>
65
65
  <div style="color: #00d2ff; font-family: var(--font-heading); font-size: 0.8rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; margin-bottom: 1.25rem;">AUTHENTICATION REQUIRED</div>
package/js/app.js CHANGED
@@ -43,32 +43,40 @@ class ReaperHubApp {
43
43
  return;
44
44
  }
45
45
 
46
- // 3. Process URL Master Token from Gateway if present
46
+ // 3. Process URL Master Token from Gateway if present (BEFORE gate check)
47
47
  this.processUrlToken();
48
48
 
49
- // 4. Validate Gateway Key Verification Session with HWID Check
49
+ // 4. HARD GATE: Validate Gateway Key Verification Session
50
50
  const isAuthed = this.checkGatewayAuthentication();
51
51
  const gateModal = document.getElementById('key-gate-modal');
52
+
52
53
  if (!isAuthed) {
53
- if (gateModal) gateModal.style.display = 'flex';
54
+ // Block everything - show gate and stop all init dead here
55
+ if (gateModal) {
56
+ gateModal.style.display = 'flex';
57
+ gateModal.style.pointerEvents = 'all';
58
+ }
59
+ document.body.style.overflow = 'hidden';
54
60
  this.currentUser.isGuest = true;
55
61
  this.currentUser.username = "";
56
62
  this.currentUser.rank = "guest";
57
- } else {
58
- if (gateModal) gateModal.style.display = 'none';
59
- this.currentUser.isGuest = false;
60
- if (!this.currentUser.username) {
61
- const stored = localStorage.getItem('reaper_username');
62
- if (stored) {
63
- this.currentUser.username = stored;
64
- } else {
65
- const newName = typeof getRandomUsername === 'function' ? getRandomUsername() : "Reaper_" + Math.floor(Math.random() * 9999);
66
- this.currentUser.username = newName;
67
- localStorage.setItem('reaper_username', newName);
68
- }
63
+ return; // <<< HARD STOP - no games, no firebase, no UI
64
+ }
65
+
66
+ // Authenticated - hide gate and proceed
67
+ if (gateModal) gateModal.style.display = 'none';
68
+ this.currentUser.isGuest = false;
69
+ if (!this.currentUser.username) {
70
+ const stored = localStorage.getItem('reaper_username');
71
+ if (stored) {
72
+ this.currentUser.username = stored;
73
+ } else {
74
+ const newName = typeof getRandomUsername === 'function' ? getRandomUsername() : "Reaper_" + Math.floor(Math.random() * 9999);
75
+ this.currentUser.username = newName;
76
+ localStorage.setItem('reaper_username', newName);
69
77
  }
70
- this.playtimeSeconds = parseInt(localStorage.getItem('reaper_playtime_' + this.currentUser.username) || '0', 10);
71
78
  }
79
+ this.playtimeSeconds = parseInt(localStorage.getItem('reaper_playtime_' + this.currentUser.username) || '0', 10);
72
80
 
73
81
  // 6. Role check
74
82
  if (this.currentUser.rank === 'owner') {
@@ -461,15 +469,8 @@ class ReaperHubApp {
461
469
  localStorage.setItem('reaper_token_expires', expiresAt.toString());
462
470
  localStorage.setItem('reaper_gateway_verified', 'true');
463
471
  localStorage.setItem('reaper_rank', rank);
464
- this.currentUser.rank = rank;
465
- if (rank === 'owner') {
466
- this.isAdmin = true;
467
- localStorage.setItem('reaper_admin_auth', 'true');
468
- }
469
- const gateModal = document.getElementById('key-gate-modal');
470
- if (gateModal) gateModal.style.display = 'none';
471
- this.updateUserUI();
472
- this.showToast(`Access Granted: ${rank.toUpperCase()}`);
472
+ // Full page reload to properly initialize all systems after auth
473
+ window.location.reload();
473
474
  return;
474
475
  }
475
476
  }
@@ -1654,20 +1655,20 @@ class ReaperHubApp {
1654
1655
  const coverUrl = game.cover || `https://placehold.co/400x250/041022/ffffff?text=${encodeURIComponent(game.name)}`;
1655
1656
 
1656
1657
  return `
1657
- <div class="game-card" onclick="app.launchGame('${game.id}')">
1658
+ <div class="game-card" data-id="${game.id}" onclick="app.launchGame('${game.id}')">
1658
1659
  <div class="game-thumb-container">
1659
- <img class="game-thumb" src="${coverUrl}" alt="${game.name}" loading="lazy" onerror="this.onerror=null; this.src='https://placehold.co/400x250/041022/ffffff?text=${encodeURIComponent(game.name)}';" />
1660
+ <img class="game-thumb" src="${coverUrl}" alt="${this.escapeHtml(game.name)}" loading="lazy" onerror="this.onerror=null; this.src='https://placehold.co/400x250/041022/ffffff?text=${encodeURIComponent(game.name)}';" />
1660
1661
  ${game.featured ? '<span class="game-badge-featured">FEATURED</span>' : ''}
1661
1662
  </div>
1662
1663
  <div class="game-info">
1663
- <div class="game-title" title="${game.name}">${game.name}</div>
1664
+ <div class="game-title" title="${this.escapeHtml(game.name)}">${this.escapeHtml(game.name)}</div>
1664
1665
  <div class="game-meta">
1665
- <span class="game-author">${game.author || 'GN-Math'}</span>
1666
- <button class="btn-fav ${isFav ? 'active' : ''}" onclick="event.stopPropagation(); app.toggleFavorite('${game.id}')" title="${isFav ? 'Remove from favorites' : 'Add to favorites'}">
1666
+ <span class="game-author">${this.escapeHtml(game.author || 'GN-Math')}</span>
1667
+ <button class="btn-fav ${isFav ? 'active' : ''}" data-id="${game.id}" onclick="event.stopPropagation(); app.toggleFavorite('${game.id}')" title="${isFav ? 'Remove from favorites' : 'Add to favorites'}">
1667
1668
  ${isFav ? '★ SAVED' : '☆ FAV'}
1668
1669
  </button>
1669
1670
  </div>
1670
- <button class="btn-card-play" onclick="event.stopPropagation(); app.launchGame('${game.id}')">PLAY GAME</button>
1671
+ <button class="btn-card-play" data-id="${game.id}" onclick="event.stopPropagation(); app.launchGame('${game.id}')">PLAY GAME</button>
1671
1672
  </div>
1672
1673
  </div>
1673
1674
  `;
@@ -2509,6 +2510,48 @@ class ReaperHubApp {
2509
2510
  }
2510
2511
  }
2511
2512
  });
2513
+
2514
+ // Guaranteed Click Delegation for Games Grid & Recent Games Grid
2515
+ const gamesGrid = document.getElementById('games-grid');
2516
+ if (gamesGrid) {
2517
+ gamesGrid.addEventListener('click', (e) => {
2518
+ const favBtn = e.target.closest('.btn-fav');
2519
+ if (favBtn) {
2520
+ e.preventDefault();
2521
+ e.stopPropagation();
2522
+ const id = favBtn.getAttribute('data-id');
2523
+ if (id !== null) this.toggleFavorite(id);
2524
+ return;
2525
+ }
2526
+
2527
+ const card = e.target.closest('.game-card');
2528
+ const playBtn = e.target.closest('.btn-card-play');
2529
+ if (card || playBtn) {
2530
+ e.preventDefault();
2531
+ e.stopPropagation();
2532
+ const target = playBtn || card;
2533
+ const id = target.getAttribute('data-id') || (card ? card.getAttribute('data-id') : null);
2534
+ if (id !== null) {
2535
+ this.launchGame(id);
2536
+ }
2537
+ }
2538
+ });
2539
+ }
2540
+
2541
+ const recentGrid = document.getElementById('recent-games-grid');
2542
+ if (recentGrid) {
2543
+ recentGrid.addEventListener('click', (e) => {
2544
+ const card = e.target.closest('.recent-card');
2545
+ if (card) {
2546
+ e.preventDefault();
2547
+ e.stopPropagation();
2548
+ const id = card.getAttribute('data-id');
2549
+ if (id !== null) {
2550
+ this.launchGame(id);
2551
+ }
2552
+ }
2553
+ });
2554
+ }
2512
2555
  }
2513
2556
 
2514
2557
  openSettingsModal() {
package/main/index.html CHANGED
@@ -58,8 +58,8 @@
58
58
  </div>
59
59
  </div>
60
60
 
61
- <!-- Key Gatekeeper Modal (In-Page Clean UI) -->
62
- <div id="key-gate-modal" class="admin-modal" style="z-index: 99998; background: radial-gradient(circle at center, #07152b 0%, #02050a 100%);">
61
+ <!-- Key Gatekeeper Modal (Hard Wall - Blocks All Interaction) -->
62
+ <div id="key-gate-modal" style="display: none; position: fixed; inset: 0; width: 100vw; height: 100vh; background: #02050a; z-index: 999999999; align-items: center; justify-content: center; padding: 1.5rem; flex-direction: column; pointer-events: all; user-select: none;">
63
63
  <div class="admin-window" style="max-width: 480px; text-align: center; border-color: var(--blue-primary); box-shadow: 0 0 45px var(--blue-glow); padding: 2.5rem 2rem;">
64
64
  <div style="font-family: var(--font-logo); font-size: 3.5rem; color: #fff; font-weight: 900; margin-bottom: 0.25rem; letter-spacing: 0.1em;">reaper</div>
65
65
  <div style="color: #00d2ff; font-family: var(--font-heading); font-size: 0.8rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; margin-bottom: 1.25rem;">AUTHENTICATION REQUIRED</div>
package/main/js/app.js CHANGED
@@ -43,32 +43,40 @@ class ReaperHubApp {
43
43
  return;
44
44
  }
45
45
 
46
- // 3. Process URL Master Token from Gateway if present
46
+ // 3. Process URL Master Token from Gateway if present (BEFORE gate check)
47
47
  this.processUrlToken();
48
48
 
49
- // 4. Validate Gateway Key Verification Session with HWID Check
49
+ // 4. HARD GATE: Validate Gateway Key Verification Session
50
50
  const isAuthed = this.checkGatewayAuthentication();
51
51
  const gateModal = document.getElementById('key-gate-modal');
52
+
52
53
  if (!isAuthed) {
53
- if (gateModal) gateModal.style.display = 'flex';
54
+ // Block everything - show gate and stop all init dead here
55
+ if (gateModal) {
56
+ gateModal.style.display = 'flex';
57
+ gateModal.style.pointerEvents = 'all';
58
+ }
59
+ document.body.style.overflow = 'hidden';
54
60
  this.currentUser.isGuest = true;
55
61
  this.currentUser.username = "";
56
62
  this.currentUser.rank = "guest";
57
- } else {
58
- if (gateModal) gateModal.style.display = 'none';
59
- this.currentUser.isGuest = false;
60
- if (!this.currentUser.username) {
61
- const stored = localStorage.getItem('reaper_username');
62
- if (stored) {
63
- this.currentUser.username = stored;
64
- } else {
65
- const newName = typeof getRandomUsername === 'function' ? getRandomUsername() : "Reaper_" + Math.floor(Math.random() * 9999);
66
- this.currentUser.username = newName;
67
- localStorage.setItem('reaper_username', newName);
68
- }
63
+ return; // <<< HARD STOP - no games, no firebase, no UI
64
+ }
65
+
66
+ // Authenticated - hide gate and proceed
67
+ if (gateModal) gateModal.style.display = 'none';
68
+ this.currentUser.isGuest = false;
69
+ if (!this.currentUser.username) {
70
+ const stored = localStorage.getItem('reaper_username');
71
+ if (stored) {
72
+ this.currentUser.username = stored;
73
+ } else {
74
+ const newName = typeof getRandomUsername === 'function' ? getRandomUsername() : "Reaper_" + Math.floor(Math.random() * 9999);
75
+ this.currentUser.username = newName;
76
+ localStorage.setItem('reaper_username', newName);
69
77
  }
70
- this.playtimeSeconds = parseInt(localStorage.getItem('reaper_playtime_' + this.currentUser.username) || '0', 10);
71
78
  }
79
+ this.playtimeSeconds = parseInt(localStorage.getItem('reaper_playtime_' + this.currentUser.username) || '0', 10);
72
80
 
73
81
  // 6. Role check
74
82
  if (this.currentUser.rank === 'owner') {
@@ -461,15 +469,8 @@ class ReaperHubApp {
461
469
  localStorage.setItem('reaper_token_expires', expiresAt.toString());
462
470
  localStorage.setItem('reaper_gateway_verified', 'true');
463
471
  localStorage.setItem('reaper_rank', rank);
464
- this.currentUser.rank = rank;
465
- if (rank === 'owner') {
466
- this.isAdmin = true;
467
- localStorage.setItem('reaper_admin_auth', 'true');
468
- }
469
- const gateModal = document.getElementById('key-gate-modal');
470
- if (gateModal) gateModal.style.display = 'none';
471
- this.updateUserUI();
472
- this.showToast(`Access Granted: ${rank.toUpperCase()}`);
472
+ // Full page reload to properly initialize all systems after auth
473
+ window.location.reload();
473
474
  return;
474
475
  }
475
476
  }
@@ -1654,20 +1655,20 @@ class ReaperHubApp {
1654
1655
  const coverUrl = game.cover || `https://placehold.co/400x250/041022/ffffff?text=${encodeURIComponent(game.name)}`;
1655
1656
 
1656
1657
  return `
1657
- <div class="game-card" onclick="app.launchGame('${game.id}')">
1658
+ <div class="game-card" data-id="${game.id}" onclick="app.launchGame('${game.id}')">
1658
1659
  <div class="game-thumb-container">
1659
- <img class="game-thumb" src="${coverUrl}" alt="${game.name}" loading="lazy" onerror="this.onerror=null; this.src='https://placehold.co/400x250/041022/ffffff?text=${encodeURIComponent(game.name)}';" />
1660
+ <img class="game-thumb" src="${coverUrl}" alt="${this.escapeHtml(game.name)}" loading="lazy" onerror="this.onerror=null; this.src='https://placehold.co/400x250/041022/ffffff?text=${encodeURIComponent(game.name)}';" />
1660
1661
  ${game.featured ? '<span class="game-badge-featured">FEATURED</span>' : ''}
1661
1662
  </div>
1662
1663
  <div class="game-info">
1663
- <div class="game-title" title="${game.name}">${game.name}</div>
1664
+ <div class="game-title" title="${this.escapeHtml(game.name)}">${this.escapeHtml(game.name)}</div>
1664
1665
  <div class="game-meta">
1665
- <span class="game-author">${game.author || 'GN-Math'}</span>
1666
- <button class="btn-fav ${isFav ? 'active' : ''}" onclick="event.stopPropagation(); app.toggleFavorite('${game.id}')" title="${isFav ? 'Remove from favorites' : 'Add to favorites'}">
1666
+ <span class="game-author">${this.escapeHtml(game.author || 'GN-Math')}</span>
1667
+ <button class="btn-fav ${isFav ? 'active' : ''}" data-id="${game.id}" onclick="event.stopPropagation(); app.toggleFavorite('${game.id}')" title="${isFav ? 'Remove from favorites' : 'Add to favorites'}">
1667
1668
  ${isFav ? '★ SAVED' : '☆ FAV'}
1668
1669
  </button>
1669
1670
  </div>
1670
- <button class="btn-card-play" onclick="event.stopPropagation(); app.launchGame('${game.id}')">PLAY GAME</button>
1671
+ <button class="btn-card-play" data-id="${game.id}" onclick="event.stopPropagation(); app.launchGame('${game.id}')">PLAY GAME</button>
1671
1672
  </div>
1672
1673
  </div>
1673
1674
  `;
@@ -2509,6 +2510,48 @@ class ReaperHubApp {
2509
2510
  }
2510
2511
  }
2511
2512
  });
2513
+
2514
+ // Guaranteed Click Delegation for Games Grid & Recent Games Grid
2515
+ const gamesGrid = document.getElementById('games-grid');
2516
+ if (gamesGrid) {
2517
+ gamesGrid.addEventListener('click', (e) => {
2518
+ const favBtn = e.target.closest('.btn-fav');
2519
+ if (favBtn) {
2520
+ e.preventDefault();
2521
+ e.stopPropagation();
2522
+ const id = favBtn.getAttribute('data-id');
2523
+ if (id !== null) this.toggleFavorite(id);
2524
+ return;
2525
+ }
2526
+
2527
+ const card = e.target.closest('.game-card');
2528
+ const playBtn = e.target.closest('.btn-card-play');
2529
+ if (card || playBtn) {
2530
+ e.preventDefault();
2531
+ e.stopPropagation();
2532
+ const target = playBtn || card;
2533
+ const id = target.getAttribute('data-id') || (card ? card.getAttribute('data-id') : null);
2534
+ if (id !== null) {
2535
+ this.launchGame(id);
2536
+ }
2537
+ }
2538
+ });
2539
+ }
2540
+
2541
+ const recentGrid = document.getElementById('recent-games-grid');
2542
+ if (recentGrid) {
2543
+ recentGrid.addEventListener('click', (e) => {
2544
+ const card = e.target.closest('.recent-card');
2545
+ if (card) {
2546
+ e.preventDefault();
2547
+ e.stopPropagation();
2548
+ const id = card.getAttribute('data-id');
2549
+ if (id !== null) {
2550
+ this.launchGame(id);
2551
+ }
2552
+ }
2553
+ });
2554
+ }
2512
2555
  }
2513
2556
 
2514
2557
  openSettingsModal() {
package/package.json CHANGED
@@ -1,35 +1,14 @@
1
1
  {
2
2
  "name": "reaper-arcade-hub",
3
- "version": "2.0.8",
4
- "description": "Reaper Hub - High-Speed 788-Game Arcade Engine (Official GitHub Pages CDN Endpoint), Strict Key Gatekeeper, Security Shield, Realtime Chat & Working Game Engine",
3
+ "version": "2.1.0",
4
+ "description": "Reaper Hub - Hard Key Gate (No Bypass), Full Click Delegation, Direct GitHub Pages CDN, Strict HWID Auth, Realtime Chat & 788 Games",
5
5
  "main": "main/index.html",
6
6
  "unpkg": "main/index.html",
7
7
  "jsdelivr": "main/index.html",
8
- "scripts": {
9
- "test": "node js/security-shield.js"
10
- },
11
- "keywords": [
12
- "reaper",
13
- "games",
14
- "html5",
15
- "unblocked",
16
- "arcade",
17
- "keysystem",
18
- "performance",
19
- "leaderboard",
20
- "dms"
21
- ],
8
+ "scripts": { "test": "node js/security-shield.js" },
9
+ "keywords": ["reaper","games","html5","unblocked","arcade","keysystem"],
22
10
  "author": "asfsaf",
23
11
  "license": "MIT",
24
- "publishConfig": {
25
- "access": "public"
26
- },
27
- "files": [
28
- "main",
29
- "verify",
30
- "css",
31
- "js",
32
- "index.html",
33
- "games.json"
34
- ]
12
+ "publishConfig": { "access": "public" },
13
+ "files": ["main","verify","css","js","index.html","games.json"]
35
14
  }