// Plants vs Zombies PWA Service Worker (Offline Support) const CACHE_NAME = 'pvz-web-v2.3'; const ASSETS_TO_CACHE = [ './', './index.html', './manifest.json', './favicon.ico', './icon-192.png', './icon-512.png', './css/style.css', './js/main.js', './js/game.js', './js/entities/plant.js', './js/entities/zombie.js', './js/entities/projectile.js', './js/systems/grid.js', './js/systems/economy.js', './js/systems/combat.js', './js/systems/campaign.js', './js/systems/feedback.js', './js/systems/wave.js', './js/systems/workshop.js', './js/systems/zengarden.js', './js/systems/almanac.js', './js/systems/achievements.js', './js/systems/roguelike.js', './js/systems/tree.js', './js/systems/boss.js', './js/systems/leaderboard.js', './js/systems/auth.js', './js/utils/assets.js', './js/utils/test_api.js' ]; self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE_NAME).then((cache) => { return cache.addAll(ASSETS_TO_CACHE); }).then(() => self.skipWaiting()) ); }); self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then((keys) => { return Promise.all( keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key)) ); }).then(() => self.clients.claim()) ); }); self.addEventListener('fetch', (event) => { // Navigation or static asset request if (event.request.method !== 'GET') return; event.respondWith( caches.match(event.request).then((cachedResponse) => { if (cachedResponse) { // Fetch in background to update cache fetch(event.request).then((networkResponse) => { if (networkResponse && networkResponse.status === 200) { caches.open(CACHE_NAME).then((cache) => cache.put(event.request, networkResponse)); } }).catch(() => {}); return cachedResponse; } return fetch(event.request).then((networkResponse) => { if (!networkResponse || networkResponse.status !== 200 || networkResponse.type !== 'basic') { return networkResponse; } const responseToCache = networkResponse.clone(); caches.open(CACHE_NAME).then((cache) => { cache.put(event.request, responseToCache); }); return networkResponse; }).catch(() => { // Fallback to cached index.html for navigation requests if (event.request.mode === 'navigate') { return caches.match('./index.html'); } }); }) ); });