goodbye doom

This commit is contained in:
thororen1234 2026-03-19 20:25:25 -04:00
parent 2bfb2be8ee
commit 0ae52669b3
No known key found for this signature in database
11 changed files with 9 additions and 9686 deletions

View file

@ -13,7 +13,7 @@ import unusedImports from "eslint-plugin-unused-imports";
import tseslint from "typescript-eslint";
export default defineConfig(
{ ignores: ["dist", "browser", "packages/vencord-types", "src/equicordplugins/commandPalette/doom/assets"] },
{ ignores: ["dist", "browser", "packages/vencord-types"] },
{
files: ["src/**/*.{tsx,ts,mts,mjs,js,jsx}", "eslint.config.mjs"],
settings: {

View file

@ -1,15 +0,0 @@
Chocolate Doom WebAssembly runtime
Source: https://github.com/cloudflare/doom-wasm
Engine lineage: https://github.com/chocolate-doom/chocolate-doom
License: GNU GPL version 2 or later.
Chocolate Doom source headers state:
"This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version."
Game data
Source: https://github.com/freedoom/freedoom/releases/tag/v0.13.0
Asset used: freedoom1.wad
License: BSD 3-Clause.

View file

@ -1,11 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2026 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import freedoomWadGzipBase64 from "file://./assets/freedoom1.wad.gz?base64";
import doomWasmScriptSource from "file://./assets/websockets-doom.js";
import doomWasmBase64 from "file://./assets/websockets-doom.wasm?base64";
export { doomWasmBase64, doomWasmScriptSource, freedoomWadGzipBase64 };

View file

@ -1,153 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2026 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
export function getDoomBootstrapScript() {
return `
const setStatus = message => {
parent.postMessage({ type: "command-palette-doom-status", message: String(message ?? "") }, "*");
};
const defaultArgs = ["-iwad", "doom1.wad", "-window", "-nogui", "-nomusic"];
const defaultConfig = [
"use_mouse 0",
"joyb_speed 29",
"mouse_acceleration 2.0",
"snd_musicdevice 0"
].join("\\n");
async function gunzip(url) {
if (typeof DecompressionStream !== "function") {
throw new Error("This browser does not support gzip decompression");
}
const response = await fetch(url);
if (!response.ok || !response.body) {
throw new Error("Failed to load Freedoom data");
}
const stream = response.body.pipeThrough(new DecompressionStream("gzip"));
return new Uint8Array(await new Response(stream).arrayBuffer());
}
window.addEventListener("error", event => {
setStatus(\`error: \${event.message}\`);
});
window.addEventListener("unhandledrejection", event => {
setStatus(\`promise rejection: \${event.reason}\`);
});
window.addEventListener("message", async event => {
if (event.data === "focus-doom") {
document.getElementById("canvas")?.focus();
return;
}
if (event.data?.type !== "command-palette-doom-init" || window.__doomBooted) {
return;
}
window.__doomBooted = true;
const { doomWasmScriptUrl, doomWasmUrl, wadGzipUrl } = event.data;
const canvas = document.getElementById("canvas");
if (!(canvas instanceof HTMLCanvasElement)) {
setStatus("error: canvas missing");
return;
}
try {
setStatus("boot: unpacking Freedoom");
const wadBytes = await gunzip(wadGzipUrl);
setStatus("boot: starting Chocolate Doom");
window.Module = {
noInitialRun: true,
canvas,
locateFile(path) {
return path.endsWith(".wasm") ? doomWasmUrl : path;
},
preRun: [() => {
Module.FS.writeFile("/doom1.wad", wadBytes);
Module.FS.writeFile("/default.cfg", defaultConfig);
}],
onRuntimeInitialized() {
setStatus("boot: ready");
canvas.focus();
callMain([...defaultArgs, "-config", "default.cfg"]);
},
print(text) {
setStatus(text);
},
printErr(text) {
setStatus("stderr: " + text);
},
setStatus() { }
};
const scriptTag = document.createElement("script");
scriptTag.src = doomWasmScriptUrl;
scriptTag.onload = () => setStatus("boot: engine loaded");
scriptTag.onerror = () => setStatus("error: failed to load engine");
document.body.appendChild(scriptTag);
} catch (error) {
setStatus(\`error: \${error instanceof Error ? error.message : String(error)}\`);
}
});
`;
}
export function getDoomRuntimeHtml(bootstrapScriptUrl: string) {
return `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>DOOM</title>
<style>
html, body {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
background: #0a0a0a;
}
body {
display: flex;
align-items: center;
justify-content: center;
}
#doom-root {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background:
radial-gradient(circle at top, rgb(153 27 27 / 18%), transparent 42%),
linear-gradient(180deg, #171717 0%, #090909 100%);
overflow: hidden;
}
#canvas {
display: block;
width: min(960px, 96vw);
max-width: 100%;
aspect-ratio: 4 / 3;
margin: auto;
background: #000;
image-rendering: pixelated;
outline: none;
}
</style>
</head>
<body>
<div id="doom-root">
<canvas id="canvas" tabindex="-1"></canvas>
</div>
<script src="${bootstrapScriptUrl}"></script>
</body>
</html>`;
}

View file

@ -698,23 +698,6 @@
gap: 12px;
}
.vc-command-palette-doom-page {
display: flex;
align-items: center;
justify-content: center;
flex: 1 1 auto;
min-height: 0;
width: 100%;
}
.vc-command-palette-doom-iframe {
width: min(100%, 960px);
min-height: 68vh;
border: none;
border-radius: 14px;
background: #050505;
}
.vc-command-palette-page-field {
display: flex;
flex-direction: column;
@ -905,8 +888,13 @@
}
@keyframes vc-cp-actions-fade-in {
from { opacity: 0; }
to { opacity: 1; }
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.vc-command-palette-actions-dropdown-header {
@ -1073,4 +1061,4 @@ input.vc-command-palette-main-search-input:read-only,
input.vc-command-palette-main-search-input:not(:read-only),
.vc-command-palette-main-search-input input:not(:read-only) {
color: var(--cp-text-primary) !important;
}
}

View file

@ -71,7 +71,6 @@ interface PalettePageStackItem {
const MENTIONS_CATEGORY_ID = "mentions-actions";
const RECENTS_CATEGORY_ID = "recent-actions";
const DOOM_QUERY_TRIGGERS = new Set(["doom", "run doom", "can it run doom"]);
let persistedCategoryId: string | null = null;
const SINGLE_SELECT_PROMPT_COMMAND_IDS = new Set([
"command-palette-open-dm-query",
@ -97,10 +96,6 @@ function hasPrimaryModifier(event: ReactKeyboardEvent<HTMLElement>): boolean {
return IS_MAC ? event.metaKey && !event.ctrlKey : event.ctrlKey && !event.metaKey;
}
function matchesDoomQuery(query: string): boolean {
return DOOM_QUERY_TRIGGERS.has(query.trim().toLowerCase());
}
function getCommandBadge(command: CommandEntry, fallback: "Command" | "Recent" | "Pinned"): string {
const defaultBadge = fallback === "Recent" ? "Command" : fallback;
if (!command.id.startsWith("custom-")) return defaultBadge;
@ -564,13 +559,6 @@ export function CommandPaletteModal({ modalProps, instanceKey }: { modalProps: M
const activePageState = activePage?.state ?? null;
const isPageOpen = Boolean(activePageSpec && activePageState);
useEffect(() => {
if (!matchesDoomQuery(trimmedQuery)) return;
if (activePromptCommand) return;
if (activePage?.ref.id === "doom") return;
pushPage({ id: "doom" });
}, [activePage?.ref.id, activePromptCommand, trimmedQuery]);
const canDrillDown = !isPageOpen && isSelectable(selectedItem) && hasChildren(selectedItem.command, allCommands);
const canGoBack = isPageOpen || navigationLevel.type !== "root";
const selectedCommand = !isPageOpen && isSelectable(selectedItem) ? selectedItem.command : null;
@ -1287,12 +1275,6 @@ export function CommandPaletteModal({ modalProps, instanceKey }: { modalProps: M
return;
}
if (isMainInputTarget && event.key === "Enter" && !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey && matchesDoomQuery(trimmedQuery)) {
event.preventDefault();
pushPage({ id: "doom" });
return;
}
if (event.key === "ArrowRight") {
event.preventDefault();
if (canDrillDown) drillDown();

View file

@ -4,14 +4,12 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import doomPageSpec from "./specs/doomPage";
import scheduledCreatePageSpec from "./specs/scheduledCreatePage";
import sendDmPageSpec from "./specs/sendDmPage";
import statusTimerPageSpec from "./specs/statusTimerPage";
import type { PalettePageId, PalettePageSpec } from "./types";
const pageSpecs = new Map<PalettePageId, PalettePageSpec>([
[doomPageSpec.id, doomPageSpec],
[sendDmPageSpec.id, sendDmPageSpec],
[scheduledCreatePageSpec.id, scheduledCreatePageSpec],
[statusTimerPageSpec.id, statusTimerPageSpec]

View file

@ -1,117 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2026 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { classNameFactory } from "@utils/css";
import { Logger } from "@utils/Logger";
import { useEffect, useRef, useState } from "@webpack/common";
import { doomWasmBase64, doomWasmScriptSource, freedoomWadGzipBase64 } from "../../../doom/runtimeAssets";
import { getDoomBootstrapScript, getDoomRuntimeHtml } from "../../../doom/runtimeHtml";
import type { PalettePageSpec } from "../types";
const cl = classNameFactory("vc-command-palette-");
const logger = new Logger("CommandPalette", "DoomPage");
let focusDoomRuntime: (() => void) | null = null;
function base64ToBlobUrl(base64: string, type: string): string {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let index = 0; index < binary.length; index++) {
bytes[index] = binary.charCodeAt(index);
}
return URL.createObjectURL(new Blob([bytes], { type }));
}
function DoomRuntime() {
const iframeRef = useRef<HTMLIFrameElement | null>(null);
const doomWasmScriptUrlRef = useRef<string | null>(null);
const doomWasmUrlRef = useRef<string | null>(null);
const wadGzipUrlRef = useRef<string | null>(null);
const bootstrapUrlRef = useRef<string | null>(null);
const [iframeSrcDoc, setIframeSrcDoc] = useState("");
useEffect(() => {
doomWasmScriptUrlRef.current = URL.createObjectURL(new Blob([
doomWasmScriptSource
], { type: "text/javascript" }));
doomWasmUrlRef.current = base64ToBlobUrl(doomWasmBase64, "application/wasm");
wadGzipUrlRef.current = base64ToBlobUrl(freedoomWadGzipBase64, "application/gzip");
bootstrapUrlRef.current = URL.createObjectURL(new Blob([
getDoomBootstrapScript()
], { type: "text/javascript" }));
setIframeSrcDoc(getDoomRuntimeHtml(bootstrapUrlRef.current));
const focus = () => {
iframeRef.current?.focus();
iframeRef.current?.contentWindow?.postMessage("focus-doom", "*");
};
const onMessage = (event: MessageEvent) => {
if (event.data?.type === "command-palette-doom-status" && typeof event.data?.message === "string") {
logger.info(event.data.message);
}
};
const onLoad = () => {
if (!iframeRef.current?.contentWindow || !doomWasmScriptUrlRef.current || !doomWasmUrlRef.current || !wadGzipUrlRef.current) return;
iframeRef.current.contentWindow.postMessage({
type: "command-palette-doom-init",
doomWasmScriptUrl: doomWasmScriptUrlRef.current,
doomWasmUrl: doomWasmUrlRef.current,
wadGzipUrl: wadGzipUrlRef.current
}, "*");
};
focusDoomRuntime = focus;
const timer = window.setTimeout(focus, 200);
window.addEventListener("message", onMessage);
iframeRef.current?.addEventListener("load", onLoad);
return () => {
window.clearTimeout(timer);
window.removeEventListener("message", onMessage);
iframeRef.current?.removeEventListener("load", onLoad);
if (focusDoomRuntime === focus) {
focusDoomRuntime = null;
}
if (bootstrapUrlRef.current) URL.revokeObjectURL(bootstrapUrlRef.current);
if (doomWasmScriptUrlRef.current) URL.revokeObjectURL(doomWasmScriptUrlRef.current);
if (doomWasmUrlRef.current) URL.revokeObjectURL(doomWasmUrlRef.current);
if (wadGzipUrlRef.current) URL.revokeObjectURL(wadGzipUrlRef.current);
};
}, []);
return (
<div className={cl("doom-page")}>
<iframe
ref={iframeRef}
className={cl("doom-iframe")}
srcDoc={iframeSrcDoc}
title="DOOM"
allow="autoplay; fullscreen"
/>
</div>
);
}
const doomPageSpec: PalettePageSpec = {
id: "doom",
title: "DOOM",
submitLabel: "Refocus DOOM",
fields: [],
async submit(context) {
focusDoomRuntime?.();
context.showSuccess("Focused DOOM.");
},
renderPage() {
return <DoomRuntime />;
}
};
export default doomPageSpec;