summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authorJan Tuomi <jan@jantuomi.fi>2025-11-13 23:51:15 +0200
committerJan Tuomi <jan@jantuomi.fi>2025-11-13 23:51:15 +0200
commit1e1ff4a39635952513c20bdb002f2586a55152a8 (patch)
tree7316bb01f57231c672c118332c9a7a9f5039a6db /docs
parentc59c2179725a205743d6f5edf60ea0db866969e9 (diff)
Add pwa
Diffstat (limited to 'docs')
-rw-r--r--docs/index.144x144.pngbin0 -> 8761 bytes
-rw-r--r--docs/index.144x144.png.import40
-rw-r--r--docs/index.180x180.pngbin0 -> 11929 bytes
-rw-r--r--docs/index.180x180.png.import40
-rw-r--r--docs/index.512x512.pngbin0 -> 49018 bytes
-rw-r--r--docs/index.512x512.png.import40
-rw-r--r--docs/index.html3
-rw-r--r--docs/index.manifest.json1
-rw-r--r--docs/index.offline.html41
-rw-r--r--docs/index.service.worker.js166
10 files changed, 330 insertions, 1 deletions
diff --git a/docs/index.144x144.png b/docs/index.144x144.png
new file mode 100644
index 0000000..cb86ad9
--- /dev/null
+++ b/docs/index.144x144.png
Binary files differ
diff --git a/docs/index.144x144.png.import b/docs/index.144x144.png.import
new file mode 100644
index 0000000..d9b6219
--- /dev/null
+++ b/docs/index.144x144.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://nylqh0ydh5tb"
+path="res://.godot/imported/index.144x144.png-92b83f3768c7cca659fbe2ac02cd6924.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://docs/index.144x144.png"
+dest_files=["res://.godot/imported/index.144x144.png-92b83f3768c7cca659fbe2ac02cd6924.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/docs/index.180x180.png b/docs/index.180x180.png
new file mode 100644
index 0000000..4299b3e
--- /dev/null
+++ b/docs/index.180x180.png
Binary files differ
diff --git a/docs/index.180x180.png.import b/docs/index.180x180.png.import
new file mode 100644
index 0000000..5a1583e
--- /dev/null
+++ b/docs/index.180x180.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dhv3uwpmsc8qf"
+path="res://.godot/imported/index.180x180.png-df2c9c60e7d0ad994df71f75ff8fc6c4.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://docs/index.180x180.png"
+dest_files=["res://.godot/imported/index.180x180.png-df2c9c60e7d0ad994df71f75ff8fc6c4.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/docs/index.512x512.png b/docs/index.512x512.png
new file mode 100644
index 0000000..ec8786f
--- /dev/null
+++ b/docs/index.512x512.png
Binary files differ
diff --git a/docs/index.512x512.png.import b/docs/index.512x512.png.import
new file mode 100644
index 0000000..cb923fb
--- /dev/null
+++ b/docs/index.512x512.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://co68onym5nd3x"
+path="res://.godot/imported/index.512x512.png-9c95060c3a6daf64e19402e931238c81.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://docs/index.512x512.png"
+dest_files=["res://.godot/imported/index.512x512.png-9c95060c3a6daf64e19402e931238c81.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/docs/index.html b/docs/index.html
index b56ee9c..af6696a 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -92,6 +92,7 @@ body {
</style>
<link id="-gd-engine-icon" rel="icon" type="image/png" href="index.icon.png" />
<link rel="apple-touch-icon" href="index.apple-touch-icon.png"/>
+<link rel="manifest" href="index.manifest.json">
</head>
<body>
@@ -111,7 +112,7 @@ body {
<script src="index.js"></script>
<script>
-const GODOT_CONFIG = {"args":[],"canvasResizePolicy":2,"emscriptenPoolSize":8,"ensureCrossOriginIsolationHeaders":true,"executable":"index","experimentalVK":false,"fileSizes":{"index.pck":737240,"index.wasm":38034280},"focusCanvas":true,"gdextensionLibs":[],"godotPoolSize":4};
+const GODOT_CONFIG = {"args":[],"canvasResizePolicy":2,"emscriptenPoolSize":8,"ensureCrossOriginIsolationHeaders":false,"executable":"index","experimentalVK":false,"fileSizes":{"index.pck":737240,"index.wasm":38034280},"focusCanvas":true,"gdextensionLibs":[],"godotPoolSize":4,"serviceWorker":"index.service.worker.js"};
const GODOT_THREADS_ENABLED = false;
const engine = new Engine(GODOT_CONFIG);
diff --git a/docs/index.manifest.json b/docs/index.manifest.json
new file mode 100644
index 0000000..b31b976
--- /dev/null
+++ b/docs/index.manifest.json
@@ -0,0 +1 @@
+{"background_color":"#000000","display":"fullscreen","icons":[{"sizes":"144x144","src":"index.144x144.png","type":"image/png"},{"sizes":"180x180","src":"index.180x180.png","type":"image/png"},{"sizes":"512x512","src":"index.512x512.png","type":"image/png"}],"name":"MobileMetroidvania","orientation":"landscape","start_url":"./index.html"} \ No newline at end of file
diff --git a/docs/index.offline.html b/docs/index.offline.html
new file mode 100644
index 0000000..ae5298a
--- /dev/null
+++ b/docs/index.offline.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>You are offline</title>
+ <style>
+html {
+ background-color: #000000;
+ color: #ffffff;
+}
+
+body {
+ font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ margin: 2rem;
+}
+
+p {
+ margin-block: 1rem;
+}
+
+button {
+ display: block;
+ padding: 1rem 2rem;
+ margin: 3rem auto 0;
+}
+ </style>
+ </head>
+ <body>
+ <h1>You are offline</h1>
+ <p>This application requires an Internet connection to run for the first time.</p>
+ <p>Press the button below to try reloading:</p>
+ <button type="button">Reload</button>
+ <script>
+document.querySelector('button').addEventListener('click', () => {
+ window.location.reload();
+});
+ </script>
+ </body>
+</html>
diff --git a/docs/index.service.worker.js b/docs/index.service.worker.js
new file mode 100644
index 0000000..ddf416f
--- /dev/null
+++ b/docs/index.service.worker.js
@@ -0,0 +1,166 @@
+// This service worker is required to expose an exported Godot project as a
+// Progressive Web App. It provides an offline fallback page telling the user
+// that they need an Internet connection to run the project if desired.
+// Incrementing CACHE_VERSION will kick off the install event and force
+// previously cached resources to be updated from the network.
+/** @type {string} */
+const CACHE_VERSION = '1763070536|3676227673';
+/** @type {string} */
+const CACHE_PREFIX = 'MobileMetroidvan-sw-cache-';
+const CACHE_NAME = CACHE_PREFIX + CACHE_VERSION;
+/** @type {string} */
+const OFFLINE_URL = 'index.offline.html';
+/** @type {boolean} */
+const ENSURE_CROSSORIGIN_ISOLATION_HEADERS = false;
+// Files that will be cached on load.
+/** @type {string[]} */
+const CACHED_FILES = ["index.html","index.js","index.offline.html","index.icon.png","index.apple-touch-icon.png","index.audio.worklet.js","index.audio.position.worklet.js"];
+// Files that we might not want the user to preload, and will only be cached on first load.
+/** @type {string[]} */
+const CACHEABLE_FILES = ["index.wasm","index.pck"];
+const FULL_CACHE = CACHED_FILES.concat(CACHEABLE_FILES);
+
+self.addEventListener('install', (event) => {
+ event.waitUntil(caches.open(CACHE_NAME).then((cache) => cache.addAll(CACHED_FILES)));
+});
+
+self.addEventListener('activate', (event) => {
+ event.waitUntil(caches.keys().then(
+ function (keys) {
+ // Remove old caches.
+ return Promise.all(keys.filter((key) => key.startsWith(CACHE_PREFIX) && key !== CACHE_NAME).map((key) => caches.delete(key)));
+ }
+ ).then(function () {
+ // Enable navigation preload if available.
+ return ('navigationPreload' in self.registration) ? self.registration.navigationPreload.enable() : Promise.resolve();
+ }));
+});
+
+/**
+ * Ensures that the response has the correct COEP/COOP headers
+ * @param {Response} response
+ * @returns {Response}
+ */
+function ensureCrossOriginIsolationHeaders(response) {
+ if (response.headers.get('Cross-Origin-Embedder-Policy') === 'require-corp'
+ && response.headers.get('Cross-Origin-Opener-Policy') === 'same-origin') {
+ return response;
+ }
+
+ const crossOriginIsolatedHeaders = new Headers(response.headers);
+ crossOriginIsolatedHeaders.set('Cross-Origin-Embedder-Policy', 'require-corp');
+ crossOriginIsolatedHeaders.set('Cross-Origin-Opener-Policy', 'same-origin');
+ const newResponse = new Response(response.body, {
+ status: response.status,
+ statusText: response.statusText,
+ headers: crossOriginIsolatedHeaders,
+ });
+
+ return newResponse;
+}
+
+/**
+ * Calls fetch and cache the result if it is cacheable
+ * @param {FetchEvent} event
+ * @param {Cache} cache
+ * @param {boolean} isCacheable
+ * @returns {Response}
+ */
+async function fetchAndCache(event, cache, isCacheable) {
+ // Use the preloaded response, if it's there
+ /** @type { Response } */
+ let response = await event.preloadResponse;
+ if (response == null) {
+ // Or, go over network.
+ response = await self.fetch(event.request);
+ }
+
+ if (ENSURE_CROSSORIGIN_ISOLATION_HEADERS) {
+ response = ensureCrossOriginIsolationHeaders(response);
+ }
+
+ if (isCacheable) {
+ // And update the cache
+ cache.put(event.request, response.clone());
+ }
+
+ return response;
+}
+
+self.addEventListener(
+ 'fetch',
+ /**
+ * Triggered on fetch
+ * @param {FetchEvent} event
+ */
+ (event) => {
+ const isNavigate = event.request.mode === 'navigate';
+ const url = event.request.url || '';
+ const referrer = event.request.referrer || '';
+ const base = referrer.slice(0, referrer.lastIndexOf('/') + 1);
+ const local = url.startsWith(base) ? url.replace(base, '') : '';
+ const isCacheable = FULL_CACHE.some((v) => v === local) || (base === referrer && base.endsWith(CACHED_FILES[0]));
+ if (isNavigate || isCacheable) {
+ event.respondWith((async () => {
+ // Try to use cache first
+ const cache = await caches.open(CACHE_NAME);
+ if (isNavigate) {
+ // Check if we have full cache during HTML page request.
+ /** @type {Response[]} */
+ const fullCache = await Promise.all(FULL_CACHE.map((name) => cache.match(name)));
+ const missing = fullCache.some((v) => v === undefined);
+ if (missing) {
+ try {
+ // Try network if some cached file is missing (so we can display offline page in case).
+ const response = await fetchAndCache(event, cache, isCacheable);
+ return response;
+ } catch (e) {
+ // And return the hopefully always cached offline page in case of network failure.
+ console.error('Network error: ', e); // eslint-disable-line no-console
+ return caches.match(OFFLINE_URL);
+ }
+ }
+ }
+ let cached = await cache.match(event.request);
+ if (cached != null) {
+ if (ENSURE_CROSSORIGIN_ISOLATION_HEADERS) {
+ cached = ensureCrossOriginIsolationHeaders(cached);
+ }
+ return cached;
+ }
+ // Try network if don't have it in cache.
+ const response = await fetchAndCache(event, cache, isCacheable);
+ return response;
+ })());
+ } else if (ENSURE_CROSSORIGIN_ISOLATION_HEADERS) {
+ event.respondWith((async () => {
+ let response = await fetch(event.request);
+ response = ensureCrossOriginIsolationHeaders(response);
+ return response;
+ })());
+ }
+ }
+);
+
+self.addEventListener('message', (event) => {
+ // No cross origin
+ if (event.origin !== self.origin) {
+ return;
+ }
+ const id = event.source.id || '';
+ const msg = event.data || '';
+ // Ensure it's one of our clients.
+ self.clients.get(id).then(function (client) {
+ if (!client) {
+ return; // Not a valid client.
+ }
+ if (msg === 'claim') {
+ self.skipWaiting().then(() => self.clients.claim());
+ } else if (msg === 'clear') {
+ caches.delete(CACHE_NAME);
+ } else if (msg === 'update') {
+ self.skipWaiting().then(() => self.clients.claim()).then(() => self.clients.matchAll()).then((all) => all.forEach((c) => c.navigate(c.url)));
+ }
+ });
+});
+