reaper-arcade-hub 2.9.0 → 2.9.1
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 +1 -1
- package/js/app.js +178 -98
- package/js/firebase-client.js +4 -4
- package/js/security-shield.js +2 -2
- package/js/visuals.js +1 -1
- package/main/index.html +1 -1
- package/main/js/app.js +178 -98
- package/main/js/firebase-client.js +4 -4
- package/main/js/security-shield.js +2 -2
- package/main/js/visuals.js +1 -1
- package/package.json +1 -1
- package/verify/index.html +4 -0
- package/verify/js/firebase-client.js +2 -2
package/index.html
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
<div class="loader-brand-title">reaper</div>
|
|
39
39
|
<div class="loader-badge-tag">
|
|
40
40
|
<span class="badge-dot-live"></span>
|
|
41
|
-
<span>V2.
|
|
41
|
+
<span>V2.9.1 ZERO-LAG ENGINE</span> • 788 GAMES • 60 FPS
|
|
42
42
|
</div>
|
|
43
43
|
|
|
44
44
|
<!-- Live Terminal Kernel Diagnostics -->
|
package/js/app.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// REAPER HUB - Core Engine (v2.9.
|
|
2
|
-
window.REAPER_VERSION = "2.9.
|
|
3
|
-
window.REAPER_LATEST_URL = "https://unpkg.com/reaper-arcade-hub@2.9.
|
|
1
|
+
// REAPER HUB - Core Engine (v2.9.1 100% Zero-Lag 60 FPS Engine & Auto about:blank Isolation)
|
|
2
|
+
window.REAPER_VERSION = "2.9.1";
|
|
3
|
+
window.REAPER_LATEST_URL = "https://unpkg.com/reaper-arcade-hub@2.9.1/main/index.html";
|
|
4
4
|
|
|
5
5
|
function _isMasterOwnerToken(k) {
|
|
6
6
|
if (!k) return false;
|
|
@@ -21,8 +21,8 @@ class ReaperHubApp {
|
|
|
21
21
|
};
|
|
22
22
|
this.isAdmin = this.currentUser.rank === 'owner';
|
|
23
23
|
this.bannedUsers = JSON.parse(localStorage.getItem('reaper_banned_users') || '[]');
|
|
24
|
-
this.siteLockdown =
|
|
25
|
-
this.isChatLocked =
|
|
24
|
+
this.siteLockdown = false; // Always start clean so visitors are never trapped by stale localStorage
|
|
25
|
+
this.isChatLocked = false;
|
|
26
26
|
this.aiBypass = localStorage.getItem('reaper_ai_bypass') === 'true';
|
|
27
27
|
this.activeTab = 'home';
|
|
28
28
|
this.activeCategory = 'all';
|
|
@@ -94,11 +94,11 @@ class ReaperHubApp {
|
|
|
94
94
|
this.isAdmin = true;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
// 7.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
97
|
+
// 7. Cleanse any stale lockdown flags from old visits
|
|
98
|
+
try {
|
|
99
|
+
localStorage.removeItem('reaper_site_lockdown');
|
|
100
|
+
localStorage.removeItem('reaper_verify_lockdown');
|
|
101
|
+
} catch (e) {}
|
|
102
102
|
|
|
103
103
|
// 8. Connect Firebase
|
|
104
104
|
if (window.reaperFirebase) {
|
|
@@ -2515,31 +2515,8 @@ Query: **"${prompt}"**
|
|
|
2515
2515
|
}
|
|
2516
2516
|
|
|
2517
2517
|
attachCardTiltListeners() {
|
|
2518
|
-
|
|
2519
|
-
cards
|
|
2520
|
-
card.addEventListener('mouseenter', () => {
|
|
2521
|
-
if (window.reaperSFX) window.reaperSFX.playHover();
|
|
2522
|
-
});
|
|
2523
|
-
|
|
2524
|
-
card.addEventListener('mousemove', (e) => {
|
|
2525
|
-
const rect = card.getBoundingClientRect();
|
|
2526
|
-
const x = e.clientX - rect.left;
|
|
2527
|
-
const y = e.clientY - rect.top;
|
|
2528
|
-
const centerX = rect.width / 2;
|
|
2529
|
-
const centerY = rect.height / 2;
|
|
2530
|
-
|
|
2531
|
-
const rotateX = ((y - centerY) / centerY) * -12;
|
|
2532
|
-
const rotateY = ((x - centerX) / centerX) * 12;
|
|
2533
|
-
|
|
2534
|
-
card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(1.03, 1.03, 1.03)`;
|
|
2535
|
-
card.style.setProperty('--mouse-x', `${x}px`);
|
|
2536
|
-
card.style.setProperty('--mouse-y', `${y}px`);
|
|
2537
|
-
});
|
|
2538
|
-
|
|
2539
|
-
card.addEventListener('mouseleave', () => {
|
|
2540
|
-
card.style.transform = '';
|
|
2541
|
-
});
|
|
2542
|
-
});
|
|
2518
|
+
// Zero-lag optimization: Heavy per-pixel getBoundingClientRect() tilt calculations
|
|
2519
|
+
// across 788 cards are disabled in favor of hardware-accelerated CSS 3D transforms.
|
|
2543
2520
|
}
|
|
2544
2521
|
|
|
2545
2522
|
recordRecentlyPlayed(game) {
|
|
@@ -2701,6 +2678,11 @@ Query: **"${prompt}"**
|
|
|
2701
2678
|
window.reaperStarfield.pause();
|
|
2702
2679
|
}
|
|
2703
2680
|
|
|
2681
|
+
// Auto open in clean about:blank tab for 60 FPS zero-lag gameplay & school cloaking!
|
|
2682
|
+
this.openGameAboutBlank(game);
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
openGameInModal(game) {
|
|
2704
2686
|
const modal = document.getElementById('game-player-modal');
|
|
2705
2687
|
const iframe = document.getElementById('player-iframe');
|
|
2706
2688
|
const nameEl = document.getElementById('player-game-name');
|
|
@@ -2721,37 +2703,31 @@ Query: **"${prompt}"**
|
|
|
2721
2703
|
const filename = game.url.split('/').pop();
|
|
2722
2704
|
iframe.removeAttribute('srcdoc');
|
|
2723
2705
|
|
|
2724
|
-
// 1. Instant Memory Cache Check (0.01s Load)
|
|
2725
2706
|
if (this.turboGameCache && this.turboGameCache[filename]) {
|
|
2726
2707
|
iframe.srcdoc = this.cleanAndOptimizeGameHTML(this.turboGameCache[filename]);
|
|
2727
2708
|
if (statusBadge) statusBadge.textContent = '⚡ TURBO INSTANT (60 FPS)';
|
|
2728
2709
|
return;
|
|
2729
2710
|
}
|
|
2730
2711
|
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2712
|
+
fetch(`https://gn-math.github.io/html/${filename}`)
|
|
2713
|
+
.then(res => {
|
|
2714
|
+
if (res.ok) return res.text();
|
|
2715
|
+
throw new Error("CDN fallback");
|
|
2716
|
+
})
|
|
2717
|
+
.then(html => {
|
|
2736
2718
|
if (html && html.length > 50) {
|
|
2737
2719
|
this.turboGameCache[filename] = html;
|
|
2738
2720
|
iframe.srcdoc = this.cleanAndOptimizeGameHTML(html);
|
|
2739
2721
|
if (statusBadge) statusBadge.textContent = 'ONLINE (60 FPS)';
|
|
2740
|
-
|
|
2722
|
+
} else {
|
|
2723
|
+
iframe.src = `https://gn-math.github.io/html/${filename}`;
|
|
2724
|
+
if (statusBadge) statusBadge.textContent = 'ONLINE';
|
|
2741
2725
|
}
|
|
2742
|
-
}
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
// 3. Fallback to direct iframe URL
|
|
2748
|
-
try {
|
|
2749
|
-
iframe.src = `https://gn-math.github.io/html/${filename}`;
|
|
2750
|
-
if (statusBadge) statusBadge.textContent = 'ONLINE';
|
|
2751
|
-
} catch(e) {
|
|
2752
|
-
iframe.src = `https://fastly.jsdelivr.net/gh/gn-math/html@main/${filename}`;
|
|
2753
|
-
if (statusBadge) statusBadge.textContent = 'ONLINE';
|
|
2754
|
-
}
|
|
2726
|
+
})
|
|
2727
|
+
.catch(() => {
|
|
2728
|
+
iframe.src = `https://fastly.jsdelivr.net/gh/gn-math/html@main/${filename}`;
|
|
2729
|
+
if (statusBadge) statusBadge.textContent = 'ONLINE';
|
|
2730
|
+
});
|
|
2755
2731
|
}
|
|
2756
2732
|
}
|
|
2757
2733
|
|
|
@@ -2785,92 +2761,178 @@ Query: **"${prompt}"**
|
|
|
2785
2761
|
togglePlayerFullscreen() {
|
|
2786
2762
|
const frameWrapper = document.querySelector('.player-frame-wrapper');
|
|
2787
2763
|
if (!document.fullscreenElement) {
|
|
2788
|
-
frameWrapper.requestFullscreen().catch(e => console.error(e));
|
|
2764
|
+
if (frameWrapper && frameWrapper.requestFullscreen) frameWrapper.requestFullscreen().catch(e => console.error(e));
|
|
2789
2765
|
} else {
|
|
2790
2766
|
document.exitFullscreen();
|
|
2791
2767
|
}
|
|
2792
2768
|
}
|
|
2793
2769
|
|
|
2794
|
-
async openGameAboutBlank() {
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2770
|
+
async openGameAboutBlank(gameArg) {
|
|
2771
|
+
const game = gameArg || this.currentGame;
|
|
2772
|
+
if (!game) return;
|
|
2773
|
+
this.currentGame = game;
|
|
2774
|
+
|
|
2775
|
+
const filename = game.url.split('/').pop();
|
|
2776
|
+
const gameName = game.name;
|
|
2798
2777
|
const siteUrl = window.location.href;
|
|
2799
|
-
const
|
|
2800
|
-
|
|
2778
|
+
const directUrl = `https://gn-math.github.io/html/${filename}`;
|
|
2779
|
+
const fallbackUrl = `https://fastly.jsdelivr.net/gh/gn-math/html@main/${filename}`;
|
|
2780
|
+
|
|
2781
|
+
// 1. Immediately open window in user click call stack to bypass browser popup blockers
|
|
2782
|
+
let win = null;
|
|
2783
|
+
try {
|
|
2784
|
+
win = window.open('about:blank', '_blank');
|
|
2785
|
+
} catch (e) {
|
|
2786
|
+
console.warn("Popup blocked:", e);
|
|
2787
|
+
}
|
|
2788
|
+
|
|
2789
|
+
if (!win) {
|
|
2790
|
+
// Browser popup blocker prevented window.open -> gracefully fallback to player modal
|
|
2791
|
+
this.showToast("Popup blocked by browser. Opening in player modal...");
|
|
2792
|
+
this.openGameInModal(game);
|
|
2793
|
+
return;
|
|
2794
|
+
}
|
|
2795
|
+
|
|
2796
|
+
this.isPlayingGame = true;
|
|
2797
|
+
this.lastActivityTime = Date.now();
|
|
2798
|
+
this.isPausedForInactivity = false;
|
|
2799
|
+
this.updatePlaytimeStatusUI();
|
|
2800
|
+
|
|
2801
|
+
// 2. Format about:blank with Google Classroom cloak, floating control bar, and full-screen isolation
|
|
2802
|
+
try {
|
|
2801
2803
|
const doc = win.document;
|
|
2802
2804
|
doc.title = "Home - Google Classroom";
|
|
2803
|
-
|
|
2804
|
-
let gameHtml = '';
|
|
2805
|
-
if (this.turboGameCache && this.turboGameCache[filename]) {
|
|
2806
|
-
gameHtml = this.turboGameCache[filename];
|
|
2807
|
-
} else {
|
|
2808
|
-
try {
|
|
2809
|
-
const res = await fetch(`https://gn-math.github.io/html/${filename}`);
|
|
2810
|
-
if (res.ok) {
|
|
2811
|
-
gameHtml = await res.text();
|
|
2812
|
-
}
|
|
2813
|
-
} catch (e) {}
|
|
2814
|
-
}
|
|
2815
2805
|
|
|
2816
2806
|
doc.open();
|
|
2817
2807
|
doc.write(`
|
|
2818
2808
|
<!DOCTYPE html>
|
|
2819
|
-
<html>
|
|
2809
|
+
<html lang="en">
|
|
2820
2810
|
<head>
|
|
2811
|
+
<meta charset="UTF-8">
|
|
2812
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
2821
2813
|
<title>Home - Google Classroom</title>
|
|
2822
|
-
<link rel="icon" href="https://ssl.gstatic.com/classroom/favicon.png">
|
|
2814
|
+
<link rel="icon" type="image/png" href="https://ssl.gstatic.com/classroom/favicon.png">
|
|
2823
2815
|
<style>
|
|
2824
2816
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
2825
|
-
body {
|
|
2826
|
-
|
|
2817
|
+
html, body {
|
|
2818
|
+
width: 100vw; height: 100vh;
|
|
2819
|
+
overflow: hidden; background: #000;
|
|
2820
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
2821
|
+
}
|
|
2822
|
+
#game-frame {
|
|
2823
|
+
width: 100vw; height: 100vh;
|
|
2824
|
+
border: none; position: fixed; top: 0; left: 0; z-index: 1;
|
|
2825
|
+
display: block; background: #000;
|
|
2826
|
+
}
|
|
2827
2827
|
.reaper-bar {
|
|
2828
|
-
position: fixed; top:
|
|
2828
|
+
position: fixed; top: 10px; left: 12px; z-index: 99999;
|
|
2829
2829
|
display: flex; gap: 8px; align-items: center;
|
|
2830
|
-
background: rgba(3,
|
|
2831
|
-
border:
|
|
2832
|
-
box-shadow: 0 4px
|
|
2833
|
-
opacity: 0.
|
|
2830
|
+
background: rgba(3, 10, 24, 0.92); backdrop-filter: blur(10px);
|
|
2831
|
+
border: 1px solid rgba(0, 210, 255, 0.5); border-radius: 8px; padding: 6px 12px;
|
|
2832
|
+
box-shadow: 0 4px 25px rgba(0, 0, 0, 0.8), 0 0 15px rgba(0, 210, 255, 0.2);
|
|
2833
|
+
opacity: 0.9; transition: opacity 0.2s ease, border-color 0.2s ease;
|
|
2834
2834
|
}
|
|
2835
2835
|
.reaper-bar:hover { opacity: 1; border-color: #00d2ff; }
|
|
2836
|
+
.game-label {
|
|
2837
|
+
color: #fff; font-size: 11px; font-weight: 800; letter-spacing: 0.05em;
|
|
2838
|
+
margin-right: 6px; font-family: monospace;
|
|
2839
|
+
}
|
|
2836
2840
|
.btn-action {
|
|
2837
|
-
background: #
|
|
2838
|
-
padding: 5px
|
|
2841
|
+
background: #06162d; color: #00d2ff; border: 1px solid rgba(0, 210, 255, 0.4);
|
|
2842
|
+
padding: 5px 11px; border-radius: 6px; font-size: 11px; font-weight: 800;
|
|
2839
2843
|
cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; gap: 4px;
|
|
2840
2844
|
transition: all 0.2s ease; font-family: inherit;
|
|
2841
2845
|
}
|
|
2842
|
-
.btn-action:hover {
|
|
2846
|
+
.btn-action:hover {
|
|
2847
|
+
background: #0088ff; color: #fff; box-shadow: 0 0 12px rgba(0, 136, 255, 0.7);
|
|
2848
|
+
}
|
|
2843
2849
|
.reaper-watermark {
|
|
2844
|
-
position: fixed; bottom:
|
|
2845
|
-
font-family: serif; font-weight: 900; font-size:
|
|
2846
|
-
color: rgba(255, 255, 255, 0.35); text-shadow: 0 0
|
|
2850
|
+
position: fixed; bottom: 8px; right: 12px; z-index: 99999;
|
|
2851
|
+
font-family: serif; font-weight: 900; font-size: 12px; letter-spacing: 0.15em;
|
|
2852
|
+
color: rgba(255, 255, 255, 0.35); text-shadow: 0 0 8px rgba(0, 210, 255, 0.5);
|
|
2847
2853
|
pointer-events: none; user-select: none;
|
|
2848
2854
|
}
|
|
2855
|
+
#loader-spinner {
|
|
2856
|
+
position: fixed; inset: 0; background: #020610; z-index: 10;
|
|
2857
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
2858
|
+
color: #00d2ff; font-family: monospace; font-size: 14px; gap: 14px;
|
|
2859
|
+
}
|
|
2860
|
+
.spin {
|
|
2861
|
+
width: 42px; height: 42px; border: 3px solid rgba(0, 210, 255, 0.2);
|
|
2862
|
+
border-top: 3px solid #00d2ff; border-radius: 50%;
|
|
2863
|
+
animation: sp 0.8s linear infinite;
|
|
2864
|
+
}
|
|
2865
|
+
@keyframes sp { to { transform: rotate(360deg); } }
|
|
2849
2866
|
</style>
|
|
2850
2867
|
<script>
|
|
2851
|
-
//
|
|
2852
|
-
window.open = function() {
|
|
2868
|
+
// Ad-block & Pop-up Neutralizer
|
|
2869
|
+
window.open = function() { return null; };
|
|
2853
2870
|
<\/script>
|
|
2854
2871
|
</head>
|
|
2855
2872
|
<body>
|
|
2873
|
+
<div id="loader-spinner">
|
|
2874
|
+
<div class="spin"></div>
|
|
2875
|
+
<div style="font-weight: 800; letter-spacing: 0.1em;">LAUNCHING ${this.escapeHtml(gameName)} (60 FPS TURBO)...</div>
|
|
2876
|
+
</div>
|
|
2856
2877
|
<div class="reaper-bar">
|
|
2857
|
-
<
|
|
2878
|
+
<span class="game-label">⚡ ${this.escapeHtml(gameName)}</span>
|
|
2879
|
+
<a href="${siteUrl}" class="btn-action" title="Back to Reaper Hub">🏠 HUB</a>
|
|
2858
2880
|
<button onclick="document.getElementById('game-frame').requestFullscreen()" class="btn-action">⛶ FULLSCREEN</button>
|
|
2859
2881
|
<button onclick="document.getElementById('game-frame').contentWindow.location.reload()" class="btn-action">🔄 RELOAD</button>
|
|
2860
2882
|
</div>
|
|
2861
|
-
<div class="reaper-watermark">REAPER HUB</div>
|
|
2862
|
-
<iframe id="game-frame" allow="autoplay; fullscreen; gamepad; focus-without-user-activation; pointer-lock"
|
|
2883
|
+
<div class="reaper-watermark">REAPER HUB // 60 FPS ZERO LAG</div>
|
|
2884
|
+
<iframe id="game-frame" allow="autoplay; fullscreen; gamepad; focus-without-user-activation; pointer-lock" style="opacity: 0; transition: opacity 0.3s ease;"></iframe>
|
|
2863
2885
|
</body>
|
|
2864
2886
|
</html>
|
|
2865
2887
|
`);
|
|
2866
2888
|
doc.close();
|
|
2867
2889
|
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2890
|
+
const frame = doc.getElementById('game-frame');
|
|
2891
|
+
const spinner = doc.getElementById('loader-spinner');
|
|
2892
|
+
|
|
2893
|
+
const finalizeLoad = () => {
|
|
2894
|
+
if (frame) frame.style.opacity = '1';
|
|
2895
|
+
if (spinner) spinner.style.display = 'none';
|
|
2896
|
+
try {
|
|
2897
|
+
if (frame && frame.contentWindow) {
|
|
2898
|
+
frame.contentWindow.focus();
|
|
2899
|
+
}
|
|
2900
|
+
} catch(e) {}
|
|
2901
|
+
};
|
|
2902
|
+
|
|
2903
|
+
// 3. High-Speed Memory Pre-Cache Check
|
|
2904
|
+
if (this.turboGameCache && this.turboGameCache[filename]) {
|
|
2905
|
+
frame.srcdoc = this.cleanAndOptimizeGameHTML(this.turboGameCache[filename]);
|
|
2906
|
+
frame.onload = finalizeLoad;
|
|
2907
|
+
setTimeout(finalizeLoad, 400);
|
|
2908
|
+
} else {
|
|
2909
|
+
// Direct fetch & clean injection for zero lag
|
|
2910
|
+
fetch(directUrl)
|
|
2911
|
+
.then(res => {
|
|
2912
|
+
if (res.ok) return res.text();
|
|
2913
|
+
throw new Error("Direct fetch fallback");
|
|
2914
|
+
})
|
|
2915
|
+
.then(html => {
|
|
2916
|
+
if (html && html.length > 50) {
|
|
2917
|
+
if (this.turboGameCache) this.turboGameCache[filename] = html;
|
|
2918
|
+
frame.srcdoc = this.cleanAndOptimizeGameHTML(html);
|
|
2919
|
+
frame.onload = finalizeLoad;
|
|
2920
|
+
setTimeout(finalizeLoad, 500);
|
|
2921
|
+
} else {
|
|
2922
|
+
frame.src = directUrl;
|
|
2923
|
+
frame.onload = finalizeLoad;
|
|
2924
|
+
}
|
|
2925
|
+
})
|
|
2926
|
+
.catch(() => {
|
|
2927
|
+
frame.src = fallbackUrl;
|
|
2928
|
+
frame.onload = finalizeLoad;
|
|
2929
|
+
});
|
|
2871
2930
|
}
|
|
2872
2931
|
|
|
2873
|
-
this.showToast("
|
|
2932
|
+
this.showToast(`Launched "${gameName}" in about:blank (60 FPS Turbo)`);
|
|
2933
|
+
} catch (err) {
|
|
2934
|
+
console.error("about:blank initialization error:", err);
|
|
2935
|
+
this.openGameInModal(game);
|
|
2874
2936
|
}
|
|
2875
2937
|
}
|
|
2876
2938
|
|
|
@@ -2906,6 +2968,24 @@ Query: **"${prompt}"**
|
|
|
2906
2968
|
}
|
|
2907
2969
|
}
|
|
2908
2970
|
|
|
2971
|
+
startFPSMonitor() {
|
|
2972
|
+
let lastTime = performance.now();
|
|
2973
|
+
let frames = 0;
|
|
2974
|
+
const updateFps = () => {
|
|
2975
|
+
frames++;
|
|
2976
|
+
const now = performance.now();
|
|
2977
|
+
if (now - lastTime >= 1000) {
|
|
2978
|
+
this.clientFps = Math.round((frames * 1000) / (now - lastTime));
|
|
2979
|
+
const fpsEl = document.getElementById('stat-fps-counter');
|
|
2980
|
+
if (fpsEl) fpsEl.textContent = `${this.clientFps} FPS`;
|
|
2981
|
+
frames = 0;
|
|
2982
|
+
lastTime = now;
|
|
2983
|
+
}
|
|
2984
|
+
requestAnimationFrame(updateFps);
|
|
2985
|
+
};
|
|
2986
|
+
requestAnimationFrame(updateFps);
|
|
2987
|
+
}
|
|
2988
|
+
|
|
2909
2989
|
handleOpiumSearch() {
|
|
2910
2990
|
const input = document.getElementById('opium-search-input');
|
|
2911
2991
|
if (!input || !input.value.trim()) return;
|
package/js/firebase-client.js
CHANGED
|
@@ -305,10 +305,10 @@ class FirebaseService {
|
|
|
305
305
|
callback(isLocked);
|
|
306
306
|
});
|
|
307
307
|
} catch (e) {
|
|
308
|
-
callback(
|
|
308
|
+
callback(false);
|
|
309
309
|
}
|
|
310
310
|
} else {
|
|
311
|
-
callback(
|
|
311
|
+
callback(false);
|
|
312
312
|
}
|
|
313
313
|
}
|
|
314
314
|
|
|
@@ -331,10 +331,10 @@ class FirebaseService {
|
|
|
331
331
|
callback(isLocked);
|
|
332
332
|
});
|
|
333
333
|
} catch (e) {
|
|
334
|
-
callback(
|
|
334
|
+
callback(false);
|
|
335
335
|
}
|
|
336
336
|
} else {
|
|
337
|
-
callback(
|
|
337
|
+
callback(false);
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
340
|
|
package/js/security-shield.js
CHANGED
|
@@ -117,9 +117,9 @@
|
|
|
117
117
|
observer.observe(target, { childList: true, subtree: true });
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
// 4.
|
|
120
|
+
// 4. Lightweight Idle Purge Check (MutationObserver already handles live DOM with zero lag)
|
|
121
121
|
if (this.autoShield) {
|
|
122
|
-
setInterval(() => this.purgeSpyInjections(),
|
|
122
|
+
setInterval(() => this.purgeSpyInjections(), 30000);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
// Initial scan
|
package/js/visuals.js
CHANGED
|
@@ -12,7 +12,7 @@ class StarfieldCanvas {
|
|
|
12
12
|
this.isWarping = false;
|
|
13
13
|
this.warpSpeedMultiplier = 1;
|
|
14
14
|
this.isPaused = false;
|
|
15
|
-
this.turboMode = localStorage.getItem('reaper_turbo_mode')
|
|
15
|
+
this.turboMode = localStorage.getItem('reaper_turbo_mode') !== 'false'; // Default TRUE for ultra 60 FPS
|
|
16
16
|
this.rafId = null;
|
|
17
17
|
|
|
18
18
|
this.init();
|
package/main/index.html
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
<div class="loader-brand-title">reaper</div>
|
|
39
39
|
<div class="loader-badge-tag">
|
|
40
40
|
<span class="badge-dot-live"></span>
|
|
41
|
-
<span>V2.
|
|
41
|
+
<span>V2.9.1 ZERO-LAG ENGINE</span> • 788 GAMES • 60 FPS
|
|
42
42
|
</div>
|
|
43
43
|
|
|
44
44
|
<!-- Live Terminal Kernel Diagnostics -->
|
package/main/js/app.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// REAPER HUB - Core Engine (v2.9.
|
|
2
|
-
window.REAPER_VERSION = "2.9.
|
|
3
|
-
window.REAPER_LATEST_URL = "https://unpkg.com/reaper-arcade-hub@2.9.
|
|
1
|
+
// REAPER HUB - Core Engine (v2.9.1 100% Zero-Lag 60 FPS Engine & Auto about:blank Isolation)
|
|
2
|
+
window.REAPER_VERSION = "2.9.1";
|
|
3
|
+
window.REAPER_LATEST_URL = "https://unpkg.com/reaper-arcade-hub@2.9.1/main/index.html";
|
|
4
4
|
|
|
5
5
|
function _isMasterOwnerToken(k) {
|
|
6
6
|
if (!k) return false;
|
|
@@ -21,8 +21,8 @@ class ReaperHubApp {
|
|
|
21
21
|
};
|
|
22
22
|
this.isAdmin = this.currentUser.rank === 'owner';
|
|
23
23
|
this.bannedUsers = JSON.parse(localStorage.getItem('reaper_banned_users') || '[]');
|
|
24
|
-
this.siteLockdown =
|
|
25
|
-
this.isChatLocked =
|
|
24
|
+
this.siteLockdown = false; // Always start clean so visitors are never trapped by stale localStorage
|
|
25
|
+
this.isChatLocked = false;
|
|
26
26
|
this.aiBypass = localStorage.getItem('reaper_ai_bypass') === 'true';
|
|
27
27
|
this.activeTab = 'home';
|
|
28
28
|
this.activeCategory = 'all';
|
|
@@ -94,11 +94,11 @@ class ReaperHubApp {
|
|
|
94
94
|
this.isAdmin = true;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
// 7.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
97
|
+
// 7. Cleanse any stale lockdown flags from old visits
|
|
98
|
+
try {
|
|
99
|
+
localStorage.removeItem('reaper_site_lockdown');
|
|
100
|
+
localStorage.removeItem('reaper_verify_lockdown');
|
|
101
|
+
} catch (e) {}
|
|
102
102
|
|
|
103
103
|
// 8. Connect Firebase
|
|
104
104
|
if (window.reaperFirebase) {
|
|
@@ -2515,31 +2515,8 @@ Query: **"${prompt}"**
|
|
|
2515
2515
|
}
|
|
2516
2516
|
|
|
2517
2517
|
attachCardTiltListeners() {
|
|
2518
|
-
|
|
2519
|
-
cards
|
|
2520
|
-
card.addEventListener('mouseenter', () => {
|
|
2521
|
-
if (window.reaperSFX) window.reaperSFX.playHover();
|
|
2522
|
-
});
|
|
2523
|
-
|
|
2524
|
-
card.addEventListener('mousemove', (e) => {
|
|
2525
|
-
const rect = card.getBoundingClientRect();
|
|
2526
|
-
const x = e.clientX - rect.left;
|
|
2527
|
-
const y = e.clientY - rect.top;
|
|
2528
|
-
const centerX = rect.width / 2;
|
|
2529
|
-
const centerY = rect.height / 2;
|
|
2530
|
-
|
|
2531
|
-
const rotateX = ((y - centerY) / centerY) * -12;
|
|
2532
|
-
const rotateY = ((x - centerX) / centerX) * 12;
|
|
2533
|
-
|
|
2534
|
-
card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(1.03, 1.03, 1.03)`;
|
|
2535
|
-
card.style.setProperty('--mouse-x', `${x}px`);
|
|
2536
|
-
card.style.setProperty('--mouse-y', `${y}px`);
|
|
2537
|
-
});
|
|
2538
|
-
|
|
2539
|
-
card.addEventListener('mouseleave', () => {
|
|
2540
|
-
card.style.transform = '';
|
|
2541
|
-
});
|
|
2542
|
-
});
|
|
2518
|
+
// Zero-lag optimization: Heavy per-pixel getBoundingClientRect() tilt calculations
|
|
2519
|
+
// across 788 cards are disabled in favor of hardware-accelerated CSS 3D transforms.
|
|
2543
2520
|
}
|
|
2544
2521
|
|
|
2545
2522
|
recordRecentlyPlayed(game) {
|
|
@@ -2701,6 +2678,11 @@ Query: **"${prompt}"**
|
|
|
2701
2678
|
window.reaperStarfield.pause();
|
|
2702
2679
|
}
|
|
2703
2680
|
|
|
2681
|
+
// Auto open in clean about:blank tab for 60 FPS zero-lag gameplay & school cloaking!
|
|
2682
|
+
this.openGameAboutBlank(game);
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
openGameInModal(game) {
|
|
2704
2686
|
const modal = document.getElementById('game-player-modal');
|
|
2705
2687
|
const iframe = document.getElementById('player-iframe');
|
|
2706
2688
|
const nameEl = document.getElementById('player-game-name');
|
|
@@ -2721,37 +2703,31 @@ Query: **"${prompt}"**
|
|
|
2721
2703
|
const filename = game.url.split('/').pop();
|
|
2722
2704
|
iframe.removeAttribute('srcdoc');
|
|
2723
2705
|
|
|
2724
|
-
// 1. Instant Memory Cache Check (0.01s Load)
|
|
2725
2706
|
if (this.turboGameCache && this.turboGameCache[filename]) {
|
|
2726
2707
|
iframe.srcdoc = this.cleanAndOptimizeGameHTML(this.turboGameCache[filename]);
|
|
2727
2708
|
if (statusBadge) statusBadge.textContent = '⚡ TURBO INSTANT (60 FPS)';
|
|
2728
2709
|
return;
|
|
2729
2710
|
}
|
|
2730
2711
|
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2712
|
+
fetch(`https://gn-math.github.io/html/${filename}`)
|
|
2713
|
+
.then(res => {
|
|
2714
|
+
if (res.ok) return res.text();
|
|
2715
|
+
throw new Error("CDN fallback");
|
|
2716
|
+
})
|
|
2717
|
+
.then(html => {
|
|
2736
2718
|
if (html && html.length > 50) {
|
|
2737
2719
|
this.turboGameCache[filename] = html;
|
|
2738
2720
|
iframe.srcdoc = this.cleanAndOptimizeGameHTML(html);
|
|
2739
2721
|
if (statusBadge) statusBadge.textContent = 'ONLINE (60 FPS)';
|
|
2740
|
-
|
|
2722
|
+
} else {
|
|
2723
|
+
iframe.src = `https://gn-math.github.io/html/${filename}`;
|
|
2724
|
+
if (statusBadge) statusBadge.textContent = 'ONLINE';
|
|
2741
2725
|
}
|
|
2742
|
-
}
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
// 3. Fallback to direct iframe URL
|
|
2748
|
-
try {
|
|
2749
|
-
iframe.src = `https://gn-math.github.io/html/${filename}`;
|
|
2750
|
-
if (statusBadge) statusBadge.textContent = 'ONLINE';
|
|
2751
|
-
} catch(e) {
|
|
2752
|
-
iframe.src = `https://fastly.jsdelivr.net/gh/gn-math/html@main/${filename}`;
|
|
2753
|
-
if (statusBadge) statusBadge.textContent = 'ONLINE';
|
|
2754
|
-
}
|
|
2726
|
+
})
|
|
2727
|
+
.catch(() => {
|
|
2728
|
+
iframe.src = `https://fastly.jsdelivr.net/gh/gn-math/html@main/${filename}`;
|
|
2729
|
+
if (statusBadge) statusBadge.textContent = 'ONLINE';
|
|
2730
|
+
});
|
|
2755
2731
|
}
|
|
2756
2732
|
}
|
|
2757
2733
|
|
|
@@ -2785,92 +2761,178 @@ Query: **"${prompt}"**
|
|
|
2785
2761
|
togglePlayerFullscreen() {
|
|
2786
2762
|
const frameWrapper = document.querySelector('.player-frame-wrapper');
|
|
2787
2763
|
if (!document.fullscreenElement) {
|
|
2788
|
-
frameWrapper.requestFullscreen().catch(e => console.error(e));
|
|
2764
|
+
if (frameWrapper && frameWrapper.requestFullscreen) frameWrapper.requestFullscreen().catch(e => console.error(e));
|
|
2789
2765
|
} else {
|
|
2790
2766
|
document.exitFullscreen();
|
|
2791
2767
|
}
|
|
2792
2768
|
}
|
|
2793
2769
|
|
|
2794
|
-
async openGameAboutBlank() {
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2770
|
+
async openGameAboutBlank(gameArg) {
|
|
2771
|
+
const game = gameArg || this.currentGame;
|
|
2772
|
+
if (!game) return;
|
|
2773
|
+
this.currentGame = game;
|
|
2774
|
+
|
|
2775
|
+
const filename = game.url.split('/').pop();
|
|
2776
|
+
const gameName = game.name;
|
|
2798
2777
|
const siteUrl = window.location.href;
|
|
2799
|
-
const
|
|
2800
|
-
|
|
2778
|
+
const directUrl = `https://gn-math.github.io/html/${filename}`;
|
|
2779
|
+
const fallbackUrl = `https://fastly.jsdelivr.net/gh/gn-math/html@main/${filename}`;
|
|
2780
|
+
|
|
2781
|
+
// 1. Immediately open window in user click call stack to bypass browser popup blockers
|
|
2782
|
+
let win = null;
|
|
2783
|
+
try {
|
|
2784
|
+
win = window.open('about:blank', '_blank');
|
|
2785
|
+
} catch (e) {
|
|
2786
|
+
console.warn("Popup blocked:", e);
|
|
2787
|
+
}
|
|
2788
|
+
|
|
2789
|
+
if (!win) {
|
|
2790
|
+
// Browser popup blocker prevented window.open -> gracefully fallback to player modal
|
|
2791
|
+
this.showToast("Popup blocked by browser. Opening in player modal...");
|
|
2792
|
+
this.openGameInModal(game);
|
|
2793
|
+
return;
|
|
2794
|
+
}
|
|
2795
|
+
|
|
2796
|
+
this.isPlayingGame = true;
|
|
2797
|
+
this.lastActivityTime = Date.now();
|
|
2798
|
+
this.isPausedForInactivity = false;
|
|
2799
|
+
this.updatePlaytimeStatusUI();
|
|
2800
|
+
|
|
2801
|
+
// 2. Format about:blank with Google Classroom cloak, floating control bar, and full-screen isolation
|
|
2802
|
+
try {
|
|
2801
2803
|
const doc = win.document;
|
|
2802
2804
|
doc.title = "Home - Google Classroom";
|
|
2803
|
-
|
|
2804
|
-
let gameHtml = '';
|
|
2805
|
-
if (this.turboGameCache && this.turboGameCache[filename]) {
|
|
2806
|
-
gameHtml = this.turboGameCache[filename];
|
|
2807
|
-
} else {
|
|
2808
|
-
try {
|
|
2809
|
-
const res = await fetch(`https://gn-math.github.io/html/${filename}`);
|
|
2810
|
-
if (res.ok) {
|
|
2811
|
-
gameHtml = await res.text();
|
|
2812
|
-
}
|
|
2813
|
-
} catch (e) {}
|
|
2814
|
-
}
|
|
2815
2805
|
|
|
2816
2806
|
doc.open();
|
|
2817
2807
|
doc.write(`
|
|
2818
2808
|
<!DOCTYPE html>
|
|
2819
|
-
<html>
|
|
2809
|
+
<html lang="en">
|
|
2820
2810
|
<head>
|
|
2811
|
+
<meta charset="UTF-8">
|
|
2812
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
2821
2813
|
<title>Home - Google Classroom</title>
|
|
2822
|
-
<link rel="icon" href="https://ssl.gstatic.com/classroom/favicon.png">
|
|
2814
|
+
<link rel="icon" type="image/png" href="https://ssl.gstatic.com/classroom/favicon.png">
|
|
2823
2815
|
<style>
|
|
2824
2816
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
2825
|
-
body {
|
|
2826
|
-
|
|
2817
|
+
html, body {
|
|
2818
|
+
width: 100vw; height: 100vh;
|
|
2819
|
+
overflow: hidden; background: #000;
|
|
2820
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
2821
|
+
}
|
|
2822
|
+
#game-frame {
|
|
2823
|
+
width: 100vw; height: 100vh;
|
|
2824
|
+
border: none; position: fixed; top: 0; left: 0; z-index: 1;
|
|
2825
|
+
display: block; background: #000;
|
|
2826
|
+
}
|
|
2827
2827
|
.reaper-bar {
|
|
2828
|
-
position: fixed; top:
|
|
2828
|
+
position: fixed; top: 10px; left: 12px; z-index: 99999;
|
|
2829
2829
|
display: flex; gap: 8px; align-items: center;
|
|
2830
|
-
background: rgba(3,
|
|
2831
|
-
border:
|
|
2832
|
-
box-shadow: 0 4px
|
|
2833
|
-
opacity: 0.
|
|
2830
|
+
background: rgba(3, 10, 24, 0.92); backdrop-filter: blur(10px);
|
|
2831
|
+
border: 1px solid rgba(0, 210, 255, 0.5); border-radius: 8px; padding: 6px 12px;
|
|
2832
|
+
box-shadow: 0 4px 25px rgba(0, 0, 0, 0.8), 0 0 15px rgba(0, 210, 255, 0.2);
|
|
2833
|
+
opacity: 0.9; transition: opacity 0.2s ease, border-color 0.2s ease;
|
|
2834
2834
|
}
|
|
2835
2835
|
.reaper-bar:hover { opacity: 1; border-color: #00d2ff; }
|
|
2836
|
+
.game-label {
|
|
2837
|
+
color: #fff; font-size: 11px; font-weight: 800; letter-spacing: 0.05em;
|
|
2838
|
+
margin-right: 6px; font-family: monospace;
|
|
2839
|
+
}
|
|
2836
2840
|
.btn-action {
|
|
2837
|
-
background: #
|
|
2838
|
-
padding: 5px
|
|
2841
|
+
background: #06162d; color: #00d2ff; border: 1px solid rgba(0, 210, 255, 0.4);
|
|
2842
|
+
padding: 5px 11px; border-radius: 6px; font-size: 11px; font-weight: 800;
|
|
2839
2843
|
cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; gap: 4px;
|
|
2840
2844
|
transition: all 0.2s ease; font-family: inherit;
|
|
2841
2845
|
}
|
|
2842
|
-
.btn-action:hover {
|
|
2846
|
+
.btn-action:hover {
|
|
2847
|
+
background: #0088ff; color: #fff; box-shadow: 0 0 12px rgba(0, 136, 255, 0.7);
|
|
2848
|
+
}
|
|
2843
2849
|
.reaper-watermark {
|
|
2844
|
-
position: fixed; bottom:
|
|
2845
|
-
font-family: serif; font-weight: 900; font-size:
|
|
2846
|
-
color: rgba(255, 255, 255, 0.35); text-shadow: 0 0
|
|
2850
|
+
position: fixed; bottom: 8px; right: 12px; z-index: 99999;
|
|
2851
|
+
font-family: serif; font-weight: 900; font-size: 12px; letter-spacing: 0.15em;
|
|
2852
|
+
color: rgba(255, 255, 255, 0.35); text-shadow: 0 0 8px rgba(0, 210, 255, 0.5);
|
|
2847
2853
|
pointer-events: none; user-select: none;
|
|
2848
2854
|
}
|
|
2855
|
+
#loader-spinner {
|
|
2856
|
+
position: fixed; inset: 0; background: #020610; z-index: 10;
|
|
2857
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
2858
|
+
color: #00d2ff; font-family: monospace; font-size: 14px; gap: 14px;
|
|
2859
|
+
}
|
|
2860
|
+
.spin {
|
|
2861
|
+
width: 42px; height: 42px; border: 3px solid rgba(0, 210, 255, 0.2);
|
|
2862
|
+
border-top: 3px solid #00d2ff; border-radius: 50%;
|
|
2863
|
+
animation: sp 0.8s linear infinite;
|
|
2864
|
+
}
|
|
2865
|
+
@keyframes sp { to { transform: rotate(360deg); } }
|
|
2849
2866
|
</style>
|
|
2850
2867
|
<script>
|
|
2851
|
-
//
|
|
2852
|
-
window.open = function() {
|
|
2868
|
+
// Ad-block & Pop-up Neutralizer
|
|
2869
|
+
window.open = function() { return null; };
|
|
2853
2870
|
<\/script>
|
|
2854
2871
|
</head>
|
|
2855
2872
|
<body>
|
|
2873
|
+
<div id="loader-spinner">
|
|
2874
|
+
<div class="spin"></div>
|
|
2875
|
+
<div style="font-weight: 800; letter-spacing: 0.1em;">LAUNCHING ${this.escapeHtml(gameName)} (60 FPS TURBO)...</div>
|
|
2876
|
+
</div>
|
|
2856
2877
|
<div class="reaper-bar">
|
|
2857
|
-
<
|
|
2878
|
+
<span class="game-label">⚡ ${this.escapeHtml(gameName)}</span>
|
|
2879
|
+
<a href="${siteUrl}" class="btn-action" title="Back to Reaper Hub">🏠 HUB</a>
|
|
2858
2880
|
<button onclick="document.getElementById('game-frame').requestFullscreen()" class="btn-action">⛶ FULLSCREEN</button>
|
|
2859
2881
|
<button onclick="document.getElementById('game-frame').contentWindow.location.reload()" class="btn-action">🔄 RELOAD</button>
|
|
2860
2882
|
</div>
|
|
2861
|
-
<div class="reaper-watermark">REAPER HUB</div>
|
|
2862
|
-
<iframe id="game-frame" allow="autoplay; fullscreen; gamepad; focus-without-user-activation; pointer-lock"
|
|
2883
|
+
<div class="reaper-watermark">REAPER HUB // 60 FPS ZERO LAG</div>
|
|
2884
|
+
<iframe id="game-frame" allow="autoplay; fullscreen; gamepad; focus-without-user-activation; pointer-lock" style="opacity: 0; transition: opacity 0.3s ease;"></iframe>
|
|
2863
2885
|
</body>
|
|
2864
2886
|
</html>
|
|
2865
2887
|
`);
|
|
2866
2888
|
doc.close();
|
|
2867
2889
|
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2890
|
+
const frame = doc.getElementById('game-frame');
|
|
2891
|
+
const spinner = doc.getElementById('loader-spinner');
|
|
2892
|
+
|
|
2893
|
+
const finalizeLoad = () => {
|
|
2894
|
+
if (frame) frame.style.opacity = '1';
|
|
2895
|
+
if (spinner) spinner.style.display = 'none';
|
|
2896
|
+
try {
|
|
2897
|
+
if (frame && frame.contentWindow) {
|
|
2898
|
+
frame.contentWindow.focus();
|
|
2899
|
+
}
|
|
2900
|
+
} catch(e) {}
|
|
2901
|
+
};
|
|
2902
|
+
|
|
2903
|
+
// 3. High-Speed Memory Pre-Cache Check
|
|
2904
|
+
if (this.turboGameCache && this.turboGameCache[filename]) {
|
|
2905
|
+
frame.srcdoc = this.cleanAndOptimizeGameHTML(this.turboGameCache[filename]);
|
|
2906
|
+
frame.onload = finalizeLoad;
|
|
2907
|
+
setTimeout(finalizeLoad, 400);
|
|
2908
|
+
} else {
|
|
2909
|
+
// Direct fetch & clean injection for zero lag
|
|
2910
|
+
fetch(directUrl)
|
|
2911
|
+
.then(res => {
|
|
2912
|
+
if (res.ok) return res.text();
|
|
2913
|
+
throw new Error("Direct fetch fallback");
|
|
2914
|
+
})
|
|
2915
|
+
.then(html => {
|
|
2916
|
+
if (html && html.length > 50) {
|
|
2917
|
+
if (this.turboGameCache) this.turboGameCache[filename] = html;
|
|
2918
|
+
frame.srcdoc = this.cleanAndOptimizeGameHTML(html);
|
|
2919
|
+
frame.onload = finalizeLoad;
|
|
2920
|
+
setTimeout(finalizeLoad, 500);
|
|
2921
|
+
} else {
|
|
2922
|
+
frame.src = directUrl;
|
|
2923
|
+
frame.onload = finalizeLoad;
|
|
2924
|
+
}
|
|
2925
|
+
})
|
|
2926
|
+
.catch(() => {
|
|
2927
|
+
frame.src = fallbackUrl;
|
|
2928
|
+
frame.onload = finalizeLoad;
|
|
2929
|
+
});
|
|
2871
2930
|
}
|
|
2872
2931
|
|
|
2873
|
-
this.showToast("
|
|
2932
|
+
this.showToast(`Launched "${gameName}" in about:blank (60 FPS Turbo)`);
|
|
2933
|
+
} catch (err) {
|
|
2934
|
+
console.error("about:blank initialization error:", err);
|
|
2935
|
+
this.openGameInModal(game);
|
|
2874
2936
|
}
|
|
2875
2937
|
}
|
|
2876
2938
|
|
|
@@ -2906,6 +2968,24 @@ Query: **"${prompt}"**
|
|
|
2906
2968
|
}
|
|
2907
2969
|
}
|
|
2908
2970
|
|
|
2971
|
+
startFPSMonitor() {
|
|
2972
|
+
let lastTime = performance.now();
|
|
2973
|
+
let frames = 0;
|
|
2974
|
+
const updateFps = () => {
|
|
2975
|
+
frames++;
|
|
2976
|
+
const now = performance.now();
|
|
2977
|
+
if (now - lastTime >= 1000) {
|
|
2978
|
+
this.clientFps = Math.round((frames * 1000) / (now - lastTime));
|
|
2979
|
+
const fpsEl = document.getElementById('stat-fps-counter');
|
|
2980
|
+
if (fpsEl) fpsEl.textContent = `${this.clientFps} FPS`;
|
|
2981
|
+
frames = 0;
|
|
2982
|
+
lastTime = now;
|
|
2983
|
+
}
|
|
2984
|
+
requestAnimationFrame(updateFps);
|
|
2985
|
+
};
|
|
2986
|
+
requestAnimationFrame(updateFps);
|
|
2987
|
+
}
|
|
2988
|
+
|
|
2909
2989
|
handleOpiumSearch() {
|
|
2910
2990
|
const input = document.getElementById('opium-search-input');
|
|
2911
2991
|
if (!input || !input.value.trim()) return;
|
|
@@ -305,10 +305,10 @@ class FirebaseService {
|
|
|
305
305
|
callback(isLocked);
|
|
306
306
|
});
|
|
307
307
|
} catch (e) {
|
|
308
|
-
callback(
|
|
308
|
+
callback(false);
|
|
309
309
|
}
|
|
310
310
|
} else {
|
|
311
|
-
callback(
|
|
311
|
+
callback(false);
|
|
312
312
|
}
|
|
313
313
|
}
|
|
314
314
|
|
|
@@ -331,10 +331,10 @@ class FirebaseService {
|
|
|
331
331
|
callback(isLocked);
|
|
332
332
|
});
|
|
333
333
|
} catch (e) {
|
|
334
|
-
callback(
|
|
334
|
+
callback(false);
|
|
335
335
|
}
|
|
336
336
|
} else {
|
|
337
|
-
callback(
|
|
337
|
+
callback(false);
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
340
|
|
|
@@ -117,9 +117,9 @@
|
|
|
117
117
|
observer.observe(target, { childList: true, subtree: true });
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
// 4.
|
|
120
|
+
// 4. Lightweight Idle Purge Check (MutationObserver already handles live DOM with zero lag)
|
|
121
121
|
if (this.autoShield) {
|
|
122
|
-
setInterval(() => this.purgeSpyInjections(),
|
|
122
|
+
setInterval(() => this.purgeSpyInjections(), 30000);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
// Initial scan
|
package/main/js/visuals.js
CHANGED
|
@@ -12,7 +12,7 @@ class StarfieldCanvas {
|
|
|
12
12
|
this.isWarping = false;
|
|
13
13
|
this.warpSpeedMultiplier = 1;
|
|
14
14
|
this.isPaused = false;
|
|
15
|
-
this.turboMode = localStorage.getItem('reaper_turbo_mode')
|
|
15
|
+
this.turboMode = localStorage.getItem('reaper_turbo_mode') !== 'false'; // Default TRUE for ultra 60 FPS
|
|
16
16
|
this.rafId = null;
|
|
17
17
|
|
|
18
18
|
this.init();
|
package/package.json
CHANGED
package/verify/index.html
CHANGED
|
@@ -185,6 +185,10 @@
|
|
|
185
185
|
const DEFAULT_MASTER_KEYS = {};
|
|
186
186
|
|
|
187
187
|
window.addEventListener('DOMContentLoaded', () => {
|
|
188
|
+
try {
|
|
189
|
+
localStorage.removeItem('reaper_verify_lockdown');
|
|
190
|
+
} catch(e) {}
|
|
191
|
+
|
|
188
192
|
if (window.reaperFirebase) {
|
|
189
193
|
window.reaperFirebase.init();
|
|
190
194
|
|
|
@@ -331,10 +331,10 @@ class FirebaseService {
|
|
|
331
331
|
callback(isLocked);
|
|
332
332
|
});
|
|
333
333
|
} catch (e) {
|
|
334
|
-
callback(
|
|
334
|
+
callback(false);
|
|
335
335
|
}
|
|
336
336
|
} else {
|
|
337
|
-
callback(
|
|
337
|
+
callback(false);
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
340
|
|