/** * Anti-Tamper Protection Module * Copyright (c) 2026 Wspólnie - wspolpraca@togethere.cloud * Wykrywa próby modyfikacji kodu i oszustw */ (function() { 'use strict'; class AntiTamper { constructor() { this.checksEnabled = true; this.violations = 0; this.maxViolations = 3; this.originalCode = {}; if (this.checksEnabled) { this.init(); } } init() { // 1. Sprawdź integrity kodu this.checkCodeIntegrity(); // 2. Wykrywaj Developer Tools this.detectDevTools(); // 3. Monitoruj modyfikacje DOM this.monitorDOMChanges(); // 4. Sprawdzaj timing (speed hacks) this.checkTiming(); // 5. Blokuj console this.disableConsole(); } /** * Sprawdza czy kod został zmodyfikowany */ checkCodeIntegrity() { // Zapisz hash funkcji krytycznych const criticalFunctions = [ window.PingPongGame, window.botAI, window.audioManager ]; setInterval(() => { criticalFunctions.forEach(func => { if (func && typeof func === 'function') { const currentCode = func.toString(); const funcName = func.name; if (this.originalCode[funcName]) { if (this.originalCode[funcName] !== currentCode) { this.reportViolation('Code modification detected'); } } else { this.originalCode[funcName] = currentCode; } } }); }, 5000); } /** * Wykrywa otwarcie DevTools */ detectDevTools() { const devtools = { isOpen: false, orientation: null }; const threshold = 160; const emitEvent = (isOpen, orientation) => { if (devtools.isOpen !== isOpen || devtools.orientation !== orientation) { devtools.isOpen = isOpen; devtools.orientation = orientation; if (isOpen) { this.reportViolation('DevTools detected'); } } }; setInterval(() => { const widthThreshold = window.outerWidth - window.innerWidth > threshold; const heightThreshold = window.outerHeight - window.innerHeight > threshold; const orientation = widthThreshold ? 'vertical' : 'horizontal'; if (widthThreshold || heightThreshold) { emitEvent(true, orientation); } else { emitEvent(false, null); } }, 500); } /** * Monitoruje nielegalne zmiany DOM */ monitorDOMChanges() { const canvas = document.getElementById('gameCanvas'); if (!canvas) return; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { // Sprawdź czy ktoś próbuje modyfikować canvas if (mutation.type === 'attributes' && mutation.target === canvas) { this.reportViolation('Canvas modification detected'); } }); }); observer.observe(canvas, { attributes: true, attributeOldValue: true }); } /** * Wykrywa speed hacks poprzez sprawdzanie czasu */ checkTiming() { let lastTime = Date.now(); let frameCount = 0; setInterval(() => { const currentTime = Date.now(); const delta = currentTime - lastTime; // Normalny interval to ~1000ms // Jeśli jest znacznie szybszy, ktoś modyfikuje czas if (delta < 800 || delta > 1200) { frameCount++; if (frameCount > 3) { this.reportViolation('Timing manipulation detected'); frameCount = 0; } } else { frameCount = 0; } lastTime = currentTime; }, 1000); } /** * Blokuje console.log i inne metody debugowania */ disableConsole() { if (window.location.hostname !== 'localhost' && window.location.hostname !== '127.0.0.1') { // W produkcji wyłącz console const noop = () => {}; ['log', 'debug', 'info', 'warn', 'error'].forEach(method => { console[method] = noop; }); } } /** * Raportuje wykryte naruszenie */ reportViolation(reason) { this.violations++; console.warn(`Anti-Tamper: ${reason} (${this.violations}/${this.maxViolations})`); // Wyślij do serwera (opcjonalnie) this.sendToServer({ type: 'violation', reason: reason, timestamp: Date.now(), userAgent: navigator.userAgent }); if (this.violations >= this.maxViolations) { this.blockUser(); } } /** * Blokuje użytkownika po wykryciu oszustwa */ blockUser() { // Zatrzymaj grę if (window.game) { window.game.stop(); } // Wyczyść canvas const canvas = document.getElementById('gameCanvas'); if (canvas) { const ctx = canvas.getContext('2d'); ctx.fillStyle = '#ff0000'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#ffffff'; ctx.font = '30px Arial'; ctx.textAlign = 'center'; ctx.fillText('CHEATING DETECTED', canvas.width / 2, canvas.height / 2); ctx.font = '16px Arial'; ctx.fillText('Your session has been terminated', canvas.width / 2, canvas.height / 2 + 40); } // Zablokuj interakcję document.body.style.pointerEvents = 'none'; // Przekieruj po 5 sekundach setTimeout(() => { window.location.href = '/'; }, 5000); } /** * Wysyła dane do serwera */ sendToServer(data) { // TODO: Zaimplementuj endpoint na serwerze /* fetch('/api/anti-tamper/report', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data) }).catch(err => { // Silent fail }); */ } } // Inicjalizuj anti-tamper protection if (typeof window !== 'undefined') { window.antiTamper = new AntiTamper(); } })();