feat: zip reader

This commit is contained in:
TrèsAbhi committed 2025-11-29 14:34:06 -06:00
1 parent 2101dba7c6
commit f33a73e1bb
9 files changed
+59 -5

No files matched your search

+5
View File
@@ -122,6 +122,7 @@
"steam-user": "^5.2.3",
"three": "^0.180.0",
"ts-proto": "^2.7.7",
"unzipit": "^1.4.3",
"yaml": "^2.8.1",
},
},
@@ -2413,6 +2414,8 @@
"unstorage": ["[email protected]", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^4.0.3", "destr": "^2.0.5", "h3": "^1.15.4", "lru-cache": "^10.4.3", "node-fetch-native": "^1.6.7", "ofetch": "^1.4.1", "ufo": "^1.6.1" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6.0.3 || ^7.0.0", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-KKGwRTT0iVBCErKemkJCLs7JdxNVfqTPc/85ae1XES0+bsHbc/sFBfVi5kJp156cc51BHinIH2l3k0EZ24vOBQ=="],
"unzipit": ["[email protected]", "", { "dependencies": { "uzip-module": "^1.0.2" } }, "sha512-gsq2PdJIWWGhx5kcdWStvNWit9FVdTewm4SEG7gFskWs+XCVaULt9+BwuoBtJiRE8eo3L1IPAOrbByNLtLtIlg=="],
"upath": ["[email protected]", "", {}, "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg=="],
"update-browserslist-db": ["[email protected]", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="],
@@ -2431,6 +2434,8 @@
"utility-types": ["[email protected]", "", {}, "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw=="],
"uzip-module": ["[email protected]", "", {}, "sha512-AMqwWZaknLM77G+VPYNZLEruMGWGzyigPK3/Whg99B3S6vGHuqsyl5ZrOv1UUF3paGK1U6PM0cnayioaryg/fA=="],
"varuna": ["varuna@workspace:packages/varuna"],
"vfile": ["[email protected]", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
+1
View File
@@ -31,6 +31,7 @@
"steam-user": "^5.2.3",
"three": "^0.180.0",
"ts-proto": "^2.7.7",
"unzipit": "^1.4.3",
"yaml": "^2.8.1"
},
"private": true,
@@ -1,5 +1,5 @@
import { assertSecret } from "@blitzkit/core";
import { SteamVFS } from "../core/steam/vfs";
import { SteamVFS } from "../core/vfs/vfs";
const APP = 444200;
const DEPOT = 444202;
@@ -6,7 +6,7 @@ import {
} from "@blitzkit/core";
import { Accessor, Document, Node, Scene } from "@gltf-transform/core";
import { times } from "lodash-es";
import { SteamVFS } from "../steam/vfs";
import { SteamVFS } from "../vfs/vfs";
import {
vertexAttributeGLTFName,
vertexAttributeGltfVectorSizes,
@@ -9,7 +9,7 @@ import { Document, Material, Node, Scene } from "@gltf-transform/core";
import { dedup, prune } from "@gltf-transform/functions";
import { times } from "lodash-es";
import { dirname } from "path";
import { SteamVFS } from "../../steam/vfs";
import { SteamVFS } from "../../vfs/vfs";
import { readBaseColor } from "../readBaseColor";
import { readNormal } from "../readNormal";
import { readRoughnessMetallic } from "../readRoughnessMetallic";
@@ -0,0 +1,3 @@
export abstract class AbstractVFS {
abstract init(): Promise<AbstractVFS>;
}
@@ -3,6 +3,7 @@ import { XMLParser } from "fast-xml-parser";
import { normalize } from "path/posix";
import SteamUser, { EConnectionProtocol } from "steam-user";
import { parse } from "yaml";
import { AbstractVFS } from "./abstract";
interface SteamManifestFile {
chunks: {
@@ -33,7 +34,7 @@ interface SteamManifest {
crc_clear: number;
}
export class SteamVFS {
export class SteamVFS extends AbstractVFS {
private steam = new SteamUser({ protocol: EConnectionProtocol.TCP });
private textDecoder = new TextDecoder();
private xmlParser = new XMLParser();
@@ -45,7 +46,9 @@ export class SteamVFS {
private password: string,
private app: number,
private depot: number
) {}
) {
super();
}
async init() {
this.steam.logOn({
+21
View File
@@ -0,0 +1,21 @@
import { HTTPRangeReader, unzip, ZipEntry } from "unzipit";
import { AbstractVFS } from "./abstract";
export class ZipVFS extends AbstractVFS {
entries: Record<string, ZipEntry> = {};
constructor(private url: string, private root = "app/") {
super();
}
async init() {
const reader = new HTTPRangeReader(this.url);
const { entries } = await unzip(reader);
for (const entry of Object.values(entries)) {
this.entries[entry.name.slice(this.root.length)] = entry;
}
return this;
}
}
@@ -0,0 +1,21 @@
---
import type { GetStaticPaths } from "astro";
import { api } from "../../../core/api/dynamic";
export const getStaticPaths = (async () => {
const { tanks } = await api.tanks();
return tanks.map((tank) => ({
params: { slug: tank.slug },
props: { id: tank.id },
}));
}) satisfies GetStaticPaths;
const { id } = Astro.props;
---
<h1>Tank {id}</h1>
<code>
<pre>{JSON.stringify(await api.tank(id), null, 2)}</pre>
</code>