mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: mirrors
This commit is contained in:
1 parent
8087752172
commit
a8dc3313cf
16 files changed
+268
-148
No files matched your search
@@ -1,13 +1,7 @@
|
|||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
import "packages/core/src/protos/tank.proto";
|
|
||||||
|
|
||||||
package blitzkit;
|
package blitzkit;
|
||||||
|
|
||||||
message Tanks {
|
message Tanks {
|
||||||
repeated string tanks = 1;
|
repeated string tanks = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message TanksFull {
|
|
||||||
repeated Tank tanks = 1;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
syntax = "proto2";
|
||||||
|
|
||||||
|
import "packages/core/src/protos/tank.proto";
|
||||||
|
|
||||||
|
package blitzkit;
|
||||||
|
|
||||||
|
message TanksFull {
|
||||||
|
repeated Tank tanks = 1;
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import { fetchPB, type MessageFns } from '@blitzkit/core';
|
import { fetchPB, type MessageFns } from '@blitzkit/core';
|
||||||
import type { APIRoute } from 'astro';
|
|
||||||
|
|
||||||
export async function blobMirror(url: string) {
|
export async function blobProxy(url: string) {
|
||||||
if (import.meta.env.MODE === 'development') {
|
if (import.meta.env.MODE === 'development') {
|
||||||
return Response.redirect(url);
|
return Response.redirect(url);
|
||||||
} else {
|
} else {
|
||||||
@@ -11,16 +10,23 @@ export async function blobMirror(url: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function apiMirror(path: string) {
|
export function apiBlobProxy(path: string) {
|
||||||
const get: APIRoute = () => blobMirror(`http://localhost:5000${path}`);
|
return blobProxy(`http://localhost:5000${path}`);
|
||||||
return get;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function jsonMirror<Type>(path: string, message: MessageFns<Type>) {
|
export function apiBlobProxyCurry(path: string) {
|
||||||
const get: APIRoute = async () => {
|
return () => apiBlobProxy(path);
|
||||||
return new Response(
|
}
|
||||||
JSON.stringify(await fetchPB(`http://localhost:5000${path}`, message)),
|
|
||||||
);
|
export async function jsonMirror<Type>(
|
||||||
};
|
path: string,
|
||||||
return get;
|
message: MessageFns<Type>,
|
||||||
|
) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify(await fetchPB(`http://localhost:5000${path}`, message)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function jsonMirrorCurry<Type>(path: string, message: MessageFns<Type>) {
|
||||||
|
return () => jsonMirror(path, message);
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,21 @@
|
|||||||
import { OpenInNewWindowIcon } from '@radix-ui/react-icons';
|
import { assertSecret } from '@blitzkit/core';
|
||||||
import { Box, Code, IconButton, Link, Table } from '@radix-ui/themes';
|
import {
|
||||||
import { useState } from 'react';
|
FileTextIcon,
|
||||||
import { Var } from '../../../core/radix/var';
|
OpenInNewWindowIcon,
|
||||||
|
RocketIcon,
|
||||||
|
} from '@radix-ui/react-icons';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Code,
|
||||||
|
Dialog,
|
||||||
|
Flex,
|
||||||
|
IconButton,
|
||||||
|
Inset,
|
||||||
|
Link,
|
||||||
|
Separator,
|
||||||
|
Table,
|
||||||
|
} from '@radix-ui/themes';
|
||||||
|
import { BlitzKitTheme } from '../../../components/BlitzKitTheme';
|
||||||
import type { APIPath } from './index.astro';
|
import type { APIPath } from './index.astro';
|
||||||
|
|
||||||
interface SlugsTableProps {
|
interface SlugsTableProps {
|
||||||
@@ -9,13 +23,12 @@ interface SlugsTableProps {
|
|||||||
path: string;
|
path: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_UNEXPANDED = 3;
|
interface TableRootProps {
|
||||||
|
slugs: NonNullable<APIPath['slugs']>;
|
||||||
export function SlugsTable({ slugs, path }: SlugsTableProps) {
|
path: string;
|
||||||
if (slugs === undefined) return null;
|
}
|
||||||
|
|
||||||
const [expanded, setExpanded] = useState(false);
|
|
||||||
|
|
||||||
|
function TableRoot({ slugs, path }: TableRootProps) {
|
||||||
return (
|
return (
|
||||||
<Table.Root variant="surface">
|
<Table.Root variant="surface">
|
||||||
<Table.Header>
|
<Table.Header>
|
||||||
@@ -34,7 +47,6 @@ export function SlugsTable({ slugs, path }: SlugsTableProps) {
|
|||||||
|
|
||||||
<Table.Body>
|
<Table.Body>
|
||||||
{slugs.groups.map((group, groupIndex) => {
|
{slugs.groups.map((group, groupIndex) => {
|
||||||
if (!expanded && groupIndex >= MAX_UNEXPANDED) return null;
|
|
||||||
let draftPath = path;
|
let draftPath = path;
|
||||||
|
|
||||||
slugs.titles.forEach((title) => {
|
slugs.titles.forEach((title) => {
|
||||||
@@ -60,53 +72,84 @@ export function SlugsTable({ slugs, path }: SlugsTableProps) {
|
|||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<Table.Cell>
|
<Table.Cell align="right">
|
||||||
<Link target="_blank" href={`/api/${draftPath}`}>
|
<Link target="_blank" href={`/api/${draftPath}`}>
|
||||||
<IconButton variant="surface">
|
<IconButton variant="solid">
|
||||||
<OpenInNewWindowIcon />
|
<RocketIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Link>
|
</Link>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
<Table.Row style={{ position: 'relative' }}>
|
|
||||||
{!expanded && (
|
|
||||||
<Box
|
|
||||||
width="100%"
|
|
||||||
height="100%"
|
|
||||||
position="absolute"
|
|
||||||
top="0"
|
|
||||||
style={{
|
|
||||||
transform: 'translate(0, -100%)',
|
|
||||||
background: `linear-gradient(${Var('black-a1')}, ${Var('black-a5')})`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Table.Cell />
|
|
||||||
|
|
||||||
<Link
|
|
||||||
href="#"
|
|
||||||
underline="always"
|
|
||||||
style={{
|
|
||||||
position: 'absolute',
|
|
||||||
top: '50%',
|
|
||||||
left: '50%',
|
|
||||||
transform: 'translate(-50%, -50%)',
|
|
||||||
}}
|
|
||||||
onClick={(event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
setExpanded((state) => !state);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{expanded
|
|
||||||
? 'Show less'
|
|
||||||
: `View all ${slugs.groups.length.toLocaleString('en')} slugs`}
|
|
||||||
</Link>
|
|
||||||
</Table.Row>
|
|
||||||
</Table.Body>
|
</Table.Body>
|
||||||
</Table.Root>
|
</Table.Root>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function SlugsTable({ slugs, path }: SlugsTableProps) {
|
||||||
|
if (slugs === undefined) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BlitzKitTheme>
|
||||||
|
<Dialog.Root>
|
||||||
|
<Dialog.Trigger>
|
||||||
|
<Button color="amber">
|
||||||
|
Slugs <OpenInNewWindowIcon />
|
||||||
|
</Button>
|
||||||
|
</Dialog.Trigger>
|
||||||
|
|
||||||
|
<Dialog.Content>
|
||||||
|
<Inset>
|
||||||
|
<TableRoot slugs={slugs} path={path} />
|
||||||
|
</Inset>
|
||||||
|
</Dialog.Content>
|
||||||
|
</Dialog.Root>
|
||||||
|
</BlitzKitTheme>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SchemaProps {
|
||||||
|
schema: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Schema({ schema, name }: SchemaProps) {
|
||||||
|
return (
|
||||||
|
<BlitzKitTheme>
|
||||||
|
<Dialog.Root>
|
||||||
|
<Dialog.Trigger>
|
||||||
|
<Button color="amber" variant="outline">
|
||||||
|
Schema <FileTextIcon />
|
||||||
|
</Button>
|
||||||
|
</Dialog.Trigger>
|
||||||
|
|
||||||
|
<Dialog.Content>
|
||||||
|
<Flex direction="column" gap="5">
|
||||||
|
<Link
|
||||||
|
target="_blank"
|
||||||
|
href={`https://github.com/${assertSecret(
|
||||||
|
import.meta.env.PUBLIC_REPO,
|
||||||
|
)}/blob/${assertSecret(
|
||||||
|
import.meta.env.PUBLIC_BRANCH,
|
||||||
|
)}/packages/core/src/protos/${name}.proto`}
|
||||||
|
>
|
||||||
|
<Code>{name}.proto</Code> on GitHub <OpenInNewWindowIcon />
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Separator size="4" />
|
||||||
|
|
||||||
|
<Code
|
||||||
|
color="gray"
|
||||||
|
highContrast
|
||||||
|
variant="ghost"
|
||||||
|
style={{ whiteSpace: 'pre' }}
|
||||||
|
>
|
||||||
|
{schema}
|
||||||
|
</Code>
|
||||||
|
</Flex>
|
||||||
|
</Dialog.Content>
|
||||||
|
</Dialog.Root>
|
||||||
|
</BlitzKitTheme>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
import { OpenInNewWindowIcon } from '@radix-ui/react-icons';
|
import { RocketIcon } from '@radix-ui/react-icons';
|
||||||
import {
|
import {
|
||||||
|
Button,
|
||||||
Code,
|
Code,
|
||||||
Flex,
|
Flex,
|
||||||
Heading,
|
Heading,
|
||||||
@@ -10,10 +11,11 @@ import {
|
|||||||
type CodeProps,
|
type CodeProps,
|
||||||
} from '@radix-ui/themes';
|
} from '@radix-ui/themes';
|
||||||
import type { GetStaticPaths, GetStaticPathsOptions } from 'astro';
|
import type { GetStaticPaths, GetStaticPathsOptions } from 'astro';
|
||||||
|
import { readFile } from 'fs/promises';
|
||||||
import { PageWrapper } from '../../../components/PageWrapper';
|
import { PageWrapper } from '../../../components/PageWrapper';
|
||||||
import { apiTool } from '../../../constants/tools';
|
import { apiTool } from '../../../constants/tools';
|
||||||
import ToolLayout from '../../../layouts/ToolLayout.astro';
|
import ToolLayout from '../../../layouts/ToolLayout.astro';
|
||||||
import { SlugsTable } from './_index';
|
import { Schema, SlugsTable } from './_index';
|
||||||
|
|
||||||
export { getStaticPaths } from '../index.astro';
|
export { getStaticPaths } from '../index.astro';
|
||||||
|
|
||||||
@@ -32,6 +34,10 @@ export interface APIPath {
|
|||||||
titles: string[];
|
titles: string[];
|
||||||
groups: SlugGroup[];
|
groups: SlugGroup[];
|
||||||
};
|
};
|
||||||
|
schema?: {
|
||||||
|
name: string;
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type SlugGroup = Record<string, string | number | undefined>;
|
type SlugGroup = Record<string, string | number | undefined>;
|
||||||
@@ -88,9 +94,11 @@ for (const rawPath in globRaw) {
|
|||||||
);
|
);
|
||||||
const path = rawPath.replace(ROOT, '').replace('.ts', '');
|
const path = rawPath.replace(ROOT, '').replace('.ts', '');
|
||||||
let comment = '';
|
let comment = '';
|
||||||
|
let schema: APIPath['schema'];
|
||||||
|
|
||||||
const tags: Tag[] = [];
|
const tags: Tag[] = [];
|
||||||
commentWithTags.split('\n').forEach((line) => {
|
|
||||||
|
for (const line of commentWithTags.split('\n')) {
|
||||||
const match = line.match(tagRegex);
|
const match = line.match(tagRegex);
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
@@ -103,6 +111,16 @@ for (const rawPath in globRaw) {
|
|||||||
const firstWordMatch = descriptionRaw.match(firstWordRegex)!;
|
const firstWordMatch = descriptionRaw.match(firstWordRegex)!;
|
||||||
discriminator = firstWordMatch[1];
|
discriminator = firstWordMatch[1];
|
||||||
description = firstWordMatch[2];
|
description = firstWordMatch[2];
|
||||||
|
} else if (tag === '@proto') {
|
||||||
|
const firstWordMatch = descriptionRaw.match(firstWordRegex)!;
|
||||||
|
const fileName = firstWordMatch[1];
|
||||||
|
const buffer = await readFile(
|
||||||
|
`../../packages/core/src/protos/${fileName}.proto`,
|
||||||
|
);
|
||||||
|
const content = buffer.toString();
|
||||||
|
|
||||||
|
schema = { name: fileName, content };
|
||||||
|
discriminator = firstWordMatch[1];
|
||||||
} else {
|
} else {
|
||||||
description = descriptionRaw;
|
description = descriptionRaw;
|
||||||
}
|
}
|
||||||
@@ -115,10 +133,10 @@ for (const rawPath in globRaw) {
|
|||||||
} else {
|
} else {
|
||||||
comment += `${line}\n`;
|
comment += `${line}\n`;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
comment = comment.trim();
|
comment = comment.trim();
|
||||||
apis.push({ path, content, comment, tags, slugs });
|
apis.push({ path, content, comment, tags, slugs, schema });
|
||||||
}
|
}
|
||||||
|
|
||||||
apis.sort((a, b) => a.path.localeCompare(b.path));
|
apis.sort((a, b) => a.path.localeCompare(b.path));
|
||||||
@@ -131,21 +149,35 @@ apis.sort((a, b) => a.path.localeCompare(b.path));
|
|||||||
apis.map((api, index) => (
|
apis.map((api, index) => (
|
||||||
<>
|
<>
|
||||||
<Flex direction="column" gap="5">
|
<Flex direction="column" gap="5">
|
||||||
<Link
|
<Flex align="center" justify="between">
|
||||||
href={api.slugs ? undefined : `/api/${api.path}`}
|
|
||||||
underline="always"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<Heading>
|
<Heading>
|
||||||
<Flex align="center" gap="2">
|
<Code variant="ghost">{api.path}</Code>
|
||||||
<Code variant="ghost">{api.path}</Code>
|
|
||||||
|
|
||||||
{!api.slugs && (
|
|
||||||
<OpenInNewWindowIcon width="1em" height="1em" />
|
|
||||||
)}
|
|
||||||
</Flex>
|
|
||||||
</Heading>
|
</Heading>
|
||||||
</Link>
|
|
||||||
|
<Flex justify="end" gap="2">
|
||||||
|
{api.schema && (
|
||||||
|
<Schema
|
||||||
|
client:load
|
||||||
|
schema={api.schema.content}
|
||||||
|
name={api.schema.name}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!api.slugs && (
|
||||||
|
<Link
|
||||||
|
href={`/api/${api.path}`}
|
||||||
|
underline="always"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<Button color="amber">
|
||||||
|
Test <RocketIcon />
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<SlugsTable client:load path={api.path} slugs={api.slugs} />
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
<Text>{api.comment}</Text>
|
<Text>{api.comment}</Text>
|
||||||
|
|
||||||
@@ -180,11 +212,7 @@ apis.sort((a, b) => a.path.localeCompare(b.path));
|
|||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<SlugsTable path={api.path} client:load slugs={api.slugs} />
|
{index < apis.length - 1 && <Separator size="4" />}
|
||||||
|
|
||||||
{index < apis.length - 1 && (
|
|
||||||
<Separator size="4" style={{ height: 0.5 }} />
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { APIRoute } from 'astro';
|
import type { APIRoute } from 'astro';
|
||||||
import packageJSON from '../../../../../package.json';
|
import packageJSON from '../../../../../package.json';
|
||||||
|
import { TOOLS } from '../../constants/tools';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns information on the current build of BlitzKit like the version
|
* Returns information on the current build of BlitzKit like the version
|
||||||
@@ -8,6 +9,10 @@ import packageJSON from '../../../../../package.json';
|
|||||||
* @todo Add more meta data.
|
* @todo Add more meta data.
|
||||||
* @returns JSON.
|
* @returns JSON.
|
||||||
*/
|
*/
|
||||||
export const GET: APIRoute = async () => {
|
export const GET: APIRoute = async ({ request }) => {
|
||||||
return Response.json({ version: packageJSON.version });
|
return Response.json({
|
||||||
|
url: new URL(request.url).origin,
|
||||||
|
version: packageJSON.version,
|
||||||
|
tools: TOOLS.map((tool) => tool.id),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { asset } from '@blitzkit/core';
|
import { asset } from '@blitzkit/core';
|
||||||
import type { APIRoute } from 'astro';
|
import type { APIRoute } from 'astro';
|
||||||
import { blobMirror } from '../../../../../core/blitzkit/blobMirror';
|
import { blobProxy } from '../../../../../core/blitzkit/blobMirror';
|
||||||
|
|
||||||
export { getStaticPaths } from '../meta.json';
|
export { getStaticPaths } from '../meta.json';
|
||||||
|
|
||||||
@@ -11,5 +11,5 @@ export { getStaticPaths } from '../meta.json';
|
|||||||
* @returns PNG.
|
* @returns PNG.
|
||||||
*/
|
*/
|
||||||
export const GET: APIRoute<{}, { id: string }> = async ({ params }) => {
|
export const GET: APIRoute<{}, { id: string }> = async ({ params }) => {
|
||||||
return await blobMirror(asset(`/tanks/${params.id}/icons/big.png`));
|
return await blobProxy(asset(`/tanks/${params.id}/icons/big.png`));
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { asset } from '@blitzkit/core';
|
import { asset } from '@blitzkit/core';
|
||||||
import type { APIRoute } from 'astro';
|
import type { APIRoute } from 'astro';
|
||||||
import { blobMirror } from '../../../../../core/blitzkit/blobMirror';
|
import { blobProxy } from '../../../../../core/blitzkit/blobMirror';
|
||||||
|
|
||||||
export { getStaticPaths } from '../meta.json';
|
export { getStaticPaths } from '../meta.json';
|
||||||
|
|
||||||
@@ -11,5 +11,5 @@ export { getStaticPaths } from '../meta.json';
|
|||||||
* @returns PNG.
|
* @returns PNG.
|
||||||
*/
|
*/
|
||||||
export const GET: APIRoute<{}, { id: string }> = async ({ params }) => {
|
export const GET: APIRoute<{}, { id: string }> = async ({ params }) => {
|
||||||
return await blobMirror(asset(`/tanks/${params.id}/icons/small.png`));
|
return await blobProxy(asset(`/tanks/${params.id}/icons/small.png`));
|
||||||
};
|
};
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { fetchTank, fetchTanks } from '@blitzkit/core';
|
import { fetchTanks, Tank } from '@blitzkit/core';
|
||||||
import type { APIRoute, GetStaticPaths } from 'astro';
|
import type { APIRoute, GetStaticPaths } from 'astro';
|
||||||
|
import { jsonMirror } from '../../../../core/blitzkit/blobMirror';
|
||||||
|
|
||||||
export const getStaticPaths = (async () => {
|
export const getStaticPaths = (async () => {
|
||||||
const tanks = await fetchTanks();
|
const tanks = await fetchTanks();
|
||||||
@@ -7,15 +8,10 @@ export const getStaticPaths = (async () => {
|
|||||||
}) satisfies GetStaticPaths;
|
}) satisfies GetStaticPaths;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the meta data on a tank which includes its modules, characteristics,
|
* Identical to tanks/[id]/meta.pb but in JSON.
|
||||||
* ancestry, descendants, equipment, characteristics, etc. However, this does
|
|
||||||
* not include information on the tank model. Use tanks/list.json to get all
|
|
||||||
* valid ids.
|
|
||||||
*
|
*
|
||||||
* @param id The tank id.
|
* @param id The tank id.
|
||||||
* @returns JSON.
|
* @returns JSON.
|
||||||
*/
|
*/
|
||||||
export const GET: APIRoute<{}, { id: string }> = async ({ params }) => {
|
export const GET: APIRoute<{}, { id: string }> = ({ params }) =>
|
||||||
const tank = await fetchTank(params.id);
|
jsonMirror(`/tanks/${params.id}.pb`, Tank);
|
||||||
return Response.json(tank);
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { fetchTanks } from '@blitzkit/core';
|
||||||
|
import type { APIRoute, GetStaticPaths } from 'astro';
|
||||||
|
import { apiBlobProxy } from '../../../../core/blitzkit/blobMirror';
|
||||||
|
|
||||||
|
export const getStaticPaths = (async () => {
|
||||||
|
const tanks = await fetchTanks();
|
||||||
|
return tanks.tanks.map((id) => ({ params: { id } }));
|
||||||
|
}) satisfies GetStaticPaths;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the meta data on a tank which includes its modules, characteristics,
|
||||||
|
* ancestry, descendants, equipment, characteristics, etc. However, this does
|
||||||
|
* not include information on the tank model. Use tanks/list.json to get all
|
||||||
|
* valid ids.
|
||||||
|
*
|
||||||
|
* @param id The tank id.
|
||||||
|
* @proto tank
|
||||||
|
*/
|
||||||
|
export const GET: APIRoute<{}, { id: string }> = ({ params }) =>
|
||||||
|
apiBlobProxy(`/tanks/${params.id}.pb`);
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { TanksFull } from '@blitzkit/core';
|
import { TanksFull } from '@blitzkit/core';
|
||||||
import { jsonMirror } from '../../../core/blitzkit/blobMirror';
|
import { jsonMirrorCurry } from '../../../core/blitzkit/blobMirror';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identical to tanks/full.pb but in JSON.
|
* Identical to tanks/full.pb but in JSON.
|
||||||
@@ -7,4 +7,4 @@ import { jsonMirror } from '../../../core/blitzkit/blobMirror';
|
|||||||
* @warning This is a large response. Consider using tanks/[id]/meta.json for individual tanks.
|
* @warning This is a large response. Consider using tanks/[id]/meta.json for individual tanks.
|
||||||
* @returns JSON.
|
* @returns JSON.
|
||||||
*/
|
*/
|
||||||
export const GET = jsonMirror('/tanks/full.pb', TanksFull);
|
export const GET = jsonMirrorCurry('/tanks/full.pb', TanksFull);
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { apiMirror } from '../../../core/blitzkit/blobMirror';
|
import { apiBlobProxyCurry } from '../../../core/blitzkit/blobMirror';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns meta data similar to tanks/[id].json but for all tanks as an array. There is no guarantee of order.
|
* Returns meta data similar to tanks/[id].json but for all tanks as an array. There is no guarantee of order.
|
||||||
*
|
*
|
||||||
* @proto TanksFull
|
* @proto tanks_full
|
||||||
*/
|
*/
|
||||||
export const GET = apiMirror('/tanks/full.pb');
|
export const GET = apiBlobProxyCurry('/tanks/full.pb');
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Tanks } from '@blitzkit/core';
|
import { Tanks } from '@blitzkit/core';
|
||||||
import { jsonMirror } from '../../../core/blitzkit/blobMirror';
|
import { jsonMirrorCurry } from '../../../core/blitzkit/blobMirror';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identical to tanks/list.pb but in JSON.
|
* Identical to tanks/list.pb but in JSON.
|
||||||
*
|
*
|
||||||
* @returns JSON.
|
* @returns JSON.
|
||||||
*/
|
*/
|
||||||
export const GET = jsonMirror('/tanks/list.pb', Tanks);
|
export const GET = jsonMirrorCurry('/tanks/list.pb', Tanks);
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { apiMirror } from '../../../core/blitzkit/blobMirror';
|
import { apiBlobProxyCurry } from '../../../core/blitzkit/blobMirror';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all tank ids. There is no guarantee of order.
|
* Returns a list of all tank ids. There is no guarantee of order.
|
||||||
*
|
*
|
||||||
* @returns JSON.
|
* @proto tanks
|
||||||
*/
|
*/
|
||||||
export const GET = apiMirror('/tanks/list.pb');
|
export const GET = apiBlobProxyCurry('/tanks/list.pb');
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using AssetRipper.TextureDecoder.Rgb.Channels;
|
||||||
|
using Blitzkit;
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace BlitzKit.CLI.Functions
|
namespace BlitzKit.CLI.Functions
|
||||||
{
|
{
|
||||||
@@ -9,19 +13,19 @@ namespace BlitzKit.CLI.Functions
|
|||||||
readonly Mangler mangler = new(args);
|
readonly Mangler mangler = new(args);
|
||||||
|
|
||||||
void Map<T>(string path, Func<Task<T>> func)
|
void Map<T>(string path, Func<Task<T>> func)
|
||||||
|
where T : IMessage<T> =>
|
||||||
|
app.MapGet(path, async context => await Octet(context, await func()));
|
||||||
|
|
||||||
|
void Map<T>(string path, Func<T> func)
|
||||||
|
where T : IMessage<T> => Map(path, () => Task.FromResult(func()));
|
||||||
|
|
||||||
|
static async Task Octet<T>(HttpContext context, T message)
|
||||||
where T : IMessage<T>
|
where T : IMessage<T>
|
||||||
{
|
{
|
||||||
app.MapGet(
|
var bytes = message.ToByteArray();
|
||||||
path,
|
|
||||||
async (context) =>
|
|
||||||
{
|
|
||||||
var message = await func();
|
|
||||||
var bytes = message.ToByteArray();
|
|
||||||
|
|
||||||
context.Response.ContentType = "application/octet-stream";
|
context.Response.ContentType = "application/octet-stream";
|
||||||
await context.Response.Body.WriteAsync(bytes);
|
await context.Response.Body.WriteAsync(bytes);
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Run()
|
public async Task Run()
|
||||||
@@ -31,6 +35,11 @@ namespace BlitzKit.CLI.Functions
|
|||||||
Map("/tanks/full.pb", mangler.TanksFull);
|
Map("/tanks/full.pb", mangler.TanksFull);
|
||||||
Map("/tanks/list.pb", mangler.Tanks);
|
Map("/tanks/list.pb", mangler.Tanks);
|
||||||
|
|
||||||
|
app.MapGet(
|
||||||
|
"/tanks/{id}.pb",
|
||||||
|
(HttpContext context, string id) => Octet(context, mangler.Tank(id))
|
||||||
|
);
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,11 +49,21 @@ namespace BlitzKit.CLI.Functions
|
|||||||
readonly BlitzProvider provider = new(args.Contains("--depot"));
|
readonly BlitzProvider provider = new(args.Contains("--depot"));
|
||||||
Locales? locales;
|
Locales? locales;
|
||||||
readonly Dictionary<string, Dictionary<string, string>> strings = [];
|
readonly Dictionary<string, Dictionary<string, string>> strings = [];
|
||||||
|
TanksFull tanksFull = null!;
|
||||||
|
|
||||||
public async Task<TanksFull> TanksFull()
|
public async Task Initialize()
|
||||||
{
|
{
|
||||||
|
await FetchStrings();
|
||||||
|
tanksFull = TanksFull();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TanksFull TanksFull()
|
||||||
|
{
|
||||||
|
if (tanksFull != null)
|
||||||
|
return tanksFull;
|
||||||
|
|
||||||
var dirs = provider.RootDirectory.GetDirectory("Blitz/Content/Tanks").Directories;
|
var dirs = provider.RootDirectory.GetDirectory("Blitz/Content/Tanks").Directories;
|
||||||
TanksFull tanksFull = new();
|
tanksFull = new();
|
||||||
|
|
||||||
foreach (var dir in dirs)
|
foreach (var dir in dirs)
|
||||||
{
|
{
|
||||||
@@ -62,7 +72,7 @@ namespace BlitzKit.CLI.Functions
|
|||||||
|
|
||||||
foreach (var tankDir in dir.Value.Directories)
|
foreach (var tankDir in dir.Value.Directories)
|
||||||
{
|
{
|
||||||
var tank = MangleTank(tankDir.Value);
|
var tank = Tank(tankDir.Value);
|
||||||
tanksFull.Tanks.Add(tank);
|
tanksFull.Tanks.Add(tank);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,7 +82,25 @@ namespace BlitzKit.CLI.Functions
|
|||||||
return tanksFull;
|
return tanksFull;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tank MangleTank(VFS tankDir)
|
public Tanks Tanks()
|
||||||
|
{
|
||||||
|
var tanksFull = TanksFull();
|
||||||
|
Tanks tanks = new();
|
||||||
|
|
||||||
|
foreach (var tank in tanksFull.Tanks)
|
||||||
|
{
|
||||||
|
tanks.Tanks_.Add(tank.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tanks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tank Tank(string id)
|
||||||
|
{
|
||||||
|
return tanksFull.Tanks.First(tank => tank.Id == id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tank Tank(VFS tankDir)
|
||||||
{
|
{
|
||||||
var pdaName = $"PDA_{tankDir.Name}";
|
var pdaName = $"PDA_{tankDir.Name}";
|
||||||
var pda = provider.LoadObject($"{tankDir.Path}/{pdaName}.{pdaName}");
|
var pda = provider.LoadObject($"{tankDir.Path}/{pdaName}.{pdaName}");
|
||||||
@@ -94,24 +122,6 @@ namespace BlitzKit.CLI.Functions
|
|||||||
return tank;
|
return tank;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Tanks> Tanks()
|
|
||||||
{
|
|
||||||
var tanksFull = await TanksFull();
|
|
||||||
Tanks tanks = new();
|
|
||||||
|
|
||||||
foreach (var tank in tanksFull.Tanks)
|
|
||||||
{
|
|
||||||
tanks.Tanks_.Add(tank.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tanks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Initialize()
|
|
||||||
{
|
|
||||||
await FetchStrings();
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
I18n GetString(string name)
|
I18n GetString(string name)
|
||||||
|
|||||||
Reference in new issue
Block a user