Run Half-Life Using HTML (and Counter-Strike 1.6)

1 yohimik 0 7/23/2025, 6:50:49 AM
No clickbait, just pure HTML, CSS, JavaScript, and WASM

Simply copy and paste this HTML code and run Half-Life

https://www.npmjs.com/package/xash3d-fwgs

https://www.npmjs.com/package/cs16-client

https://www.npmjs.com/package/hlsdk-portable

https://github.com/yohimik/webxash3d-fwgs

<!DOCTYPE html> <html> <head> <title>Loading</title> <style> canvas { width: 100vw; height: 100vh; top: 0; left: 0; position: fixed; }

        body {
            margin: 0;
        }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/xash3d-fwgs@latest/dist/raw.js"></script>
</head> <body> <canvas id="canvas"></canvas> <script type="module"> import JSZip from 'https://cdn.skypack.dev/jszip@3.10.1';

    async function main() {
        const files = {}
        const res = await fetch('https://raw.githubusercontent.com/x8BitRain/webXash/main/public/hl/hldm.zip')
        const zip = await JSZip.loadAsync(await res.arrayBuffer());

        await Promise.all(Object.keys(zip.files).map(async p => {
            const file = zip.files[p]
            if (file.dir) return;

            const path = `/rodir/${p}`;

            files[path] = await file.async("uint8array")
        }))

        Xash3D({
            arguments: ['-windowed'],
            canvas: document.getElementById('canvas'),
            ctx: document.getElementById('canvas')
                .getContext('webgl2', {
                    alpha: false,
                    depth: true,
                    stencil: true,
                    antialias: true
                }),
            dynamicLibraries: [
                "filesystem_stdio.wasm",
                "libref_gles3compat.wasm",
                "cl_dlls/menu_emscripten_wasm32.wasm",
                "dlls/hl_emscripten_wasm32.so",
                "cl_dlls/client_emscripten_wasm32.wasm",
            ],
            onRuntimeInitialized: function () {
                Object.keys(files)
                    .forEach(k => {
                        const dir = k.split('/')
                            .slice(0, -1)
                            .join('/');
                        this.FS.mkdirTree(dir);
                        this.FS.writeFile(k, files[k]);
                    })
                this.FS.chdir('/rodir')
            },
            locateFile: (p) => {
                switch (p) {
                    case 'xash.wasm':
                        return 'https://cdn.jsdelivr.net/npm/xash3d-fwgs@latest/dist/xash.wasm'
                    case 'filesystem_stdio.wasm':
                        return 'https://cdn.jsdelivr.net/npm/xash3d-fwgs@latest/dist/filesystem_stdio.wasm'
                    case 'libref_gles3compat.wasm':
                        return 'https://cdn.jsdelivr.net/npm/xash3d-fwgs@latest/dist/libref_gles3compat.wasm'
                    case 'cl_dlls/menu_emscripten_wasm32.wasm':
                        return 'https://cdn.jsdelivr.net/npm/xash3d-fwgs@latest/dist/cl_dll/menu_emscripten_wasm32.wasm'
                    case 'dlls/hl_emscripten_wasm32.so':
                        return 'https://cdn.jsdelivr.net/npm/hlsdk-portable@latest/dist/dlls/hl_emscripten_wasm32.so'
                    case 'cl_dlls/client_emscripten_wasm32.wasm':
                        return 'https://cdn.jsdelivr.net/npm/hlsdk-portable@latest/dist/cl_dll/client_emscripten_wasm32.wasm'
                    default:
                        return p
                }
            },
        })
    }

    main()
</script> </body> </html>

Comments (0)

No comments yet