mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-11-04 08:20:37 +01:00
Compare commits
5
Commits
6c31f663f6
...
402d054b30
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
402d054b30 | ||
|
|
61d6d42742 | ||
|
|
03e06b050e | ||
|
|
cca46957bc | ||
|
|
3c92ab3a19 |
No files matched your search
@@ -43,6 +43,11 @@ jobs:
|
||||
- name: Set up Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: latest
|
||||
|
||||
- name: Set up Dotnet
|
||||
uses: actions/setup-dotnet@v5
|
||||
with:
|
||||
|
||||
+1
-9
@@ -5,15 +5,7 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"setup": "chmod a+x scripts/*.sh && ./scripts/setup.sh",
|
||||
"dev": "bun run dev:website",
|
||||
"dev:website": "cd packages/website-ue && bun run dev",
|
||||
"build:game": "cd packages/game && bun run build",
|
||||
"build:website": "cd packages/website-ue && bun run build",
|
||||
"build:proxyclient": "cd packages/scripts && bun run build:proxyclient",
|
||||
"build:catalogitemaccessor": "cd packages/scripts && bun run build:catalogitemaccessor",
|
||||
"build:protos": "cd packages/scripts && bun run build:protos",
|
||||
"lint": "tsc",
|
||||
"lint:website": "cd packages/website-ue && bun run lint"
|
||||
"dev": "./scripts/dev.sh"
|
||||
},
|
||||
"type": "module",
|
||||
"workspaces": [
|
||||
|
||||
@@ -17,6 +17,8 @@ import type { Tiers } from "@protos/tiers";
|
||||
export abstract class AbstractAPI {
|
||||
abstract metadata: MetadataAccessor;
|
||||
|
||||
abstract mediaPrefix(path: string): string;
|
||||
|
||||
abstract tankList(): Promise<TankList>;
|
||||
abstract tank(id: string): Promise<Tank>;
|
||||
abstract tanks(): Promise<Tanks>;
|
||||
@@ -44,6 +46,7 @@ export abstract class AbstractAPI {
|
||||
abstract backgrounds(): Promise<Backgrounds>;
|
||||
|
||||
abstract currencyIcon(id: string): Promise<string>;
|
||||
abstract stuffIcon(id: string): Promise<string>;
|
||||
|
||||
private assertLocale(locale: string) {
|
||||
const supported = locales.supported.find(
|
||||
|
||||
@@ -18,6 +18,11 @@ export class ClientAPI extends AbstractAPI {
|
||||
throw new Error("MetadataAccessor is inaccessible on the client");
|
||||
}
|
||||
|
||||
@UnimplementedOnClient
|
||||
mediaPrefix(): never {
|
||||
throw rejected();
|
||||
}
|
||||
|
||||
@Cache()
|
||||
tankList() {
|
||||
return fetchPB("/api/tanks/list.pb", TankList);
|
||||
@@ -111,6 +116,11 @@ export class ClientAPI extends AbstractAPI {
|
||||
currencyIcon() {
|
||||
return rejected();
|
||||
}
|
||||
|
||||
@UnimplementedOnClient
|
||||
stuffIcon() {
|
||||
return rejected();
|
||||
}
|
||||
}
|
||||
|
||||
function UnimplementedOnClient(
|
||||
|
||||
@@ -36,6 +36,16 @@ export class ServerAPI extends AbstractAPI {
|
||||
super();
|
||||
}
|
||||
|
||||
mediaPrefix(path: string) {
|
||||
const config = this.resolveClientConfig();
|
||||
const metroResources = config.MetroResources();
|
||||
const remoteStorage = this.resolveRemoteUrl(
|
||||
metroResources.remote_storage!.remote_urls,
|
||||
);
|
||||
|
||||
return `${remoteStorage.url}/${remoteStorage.relative_path}${path}`;
|
||||
}
|
||||
|
||||
resolveRemoteUrl(remoteUrls: string[]) {
|
||||
let remoteStorage: RemoteStorageComponent | undefined = undefined;
|
||||
|
||||
@@ -378,14 +388,16 @@ export class ServerAPI extends AbstractAPI {
|
||||
|
||||
@Cache()
|
||||
async currencyIcon(id: string) {
|
||||
const item = this.metadata.item(`CurrencyEntity.${id}`);
|
||||
const item = this.metadata.item(id);
|
||||
const stuffUI = item.StuffUI("UIComponent");
|
||||
const config = this.resolveClientConfig();
|
||||
const metroResources = config.MetroResources();
|
||||
const remoteStorage = this.resolveRemoteUrl(
|
||||
metroResources.remote_storage!.remote_urls,
|
||||
);
|
||||
return this.mediaPrefix(stuffUI.icon!.value);
|
||||
}
|
||||
|
||||
return `${remoteStorage.url}/${remoteStorage.relative_path}${stuffUI.icon!.value}`;
|
||||
@Cache()
|
||||
async stuffIcon(id: string) {
|
||||
const item = this.metadata.item(id);
|
||||
console.log(id);
|
||||
const stuffUI = item.StuffUI("UIComponent");
|
||||
return this.mediaPrefix(stuffUI.icon!.value);
|
||||
}
|
||||
}
|
||||
@@ -26,23 +26,44 @@ interface PriceEntryProps {
|
||||
}
|
||||
|
||||
function PriceEntry({ entry }: PriceEntryProps) {
|
||||
const locale = useLocale();
|
||||
if (entry.premium_time_price !== undefined) {
|
||||
console.log(entry);
|
||||
|
||||
if (
|
||||
entry.premium_time_price !== undefined ||
|
||||
entry.stuff_price !== undefined ||
|
||||
entry.currency_price === undefined
|
||||
) {
|
||||
throw new Error("Unsupported price type");
|
||||
}
|
||||
|
||||
const [, iconName] = entry.currency_price.currency_catalog_id.split(".");
|
||||
return (
|
||||
<>
|
||||
{entry.currency_price && (
|
||||
<PriceInternal
|
||||
icon={`/api/currencies/${entry.currency_price.currency_catalog_id}.webp`}
|
||||
value={entry.currency_price.amount}
|
||||
/>
|
||||
)}
|
||||
|
||||
{entry.stuff_price && (
|
||||
<PriceInternal
|
||||
icon={`/api/stuff/${entry.stuff_price.stuff_catalog_id}.webp`}
|
||||
value={entry.stuff_price.amount}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
interface PriceInternalProps {
|
||||
icon: string;
|
||||
value: number;
|
||||
}
|
||||
|
||||
function PriceInternal({ icon, value }: PriceInternalProps) {
|
||||
const locale = useLocale();
|
||||
|
||||
return (
|
||||
<Text weight="light" size="minor" lowContrast className={styles.entry}>
|
||||
<div className={styles.wrapper}>
|
||||
<img className={styles.icon} src={`/api/currencies/${iconName}.webp`} />
|
||||
{formatCompact(locale, entry.currency_price.amount)}
|
||||
<img className={styles.icon} src={icon} />
|
||||
{formatCompact(locale, value)}
|
||||
</div>
|
||||
</Text>
|
||||
);
|
||||
|
||||
@@ -28,9 +28,15 @@ import { Text } from "../Text";
|
||||
import styles from "./index.module.css";
|
||||
|
||||
export function TankopediaLoadout() {
|
||||
const tank = useProtagonist();
|
||||
|
||||
const showModules = tank.tank!.upgrade_lines.some(
|
||||
(line) => line.stages.length > 1 || line.name in alternativeLines,
|
||||
);
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<Modules />
|
||||
{showModules && <Modules />}
|
||||
<Equipment />
|
||||
</Section>
|
||||
);
|
||||
@@ -199,6 +205,7 @@ function Modules() {
|
||||
</div>
|
||||
|
||||
<div className={styles.lines}>
|
||||
{/* TODO: hide lines with 1 module except for alts */}
|
||||
{tank.tank!.upgrade_lines.map((line) => (
|
||||
<Line
|
||||
key={line.name}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { assertSecret } from "@blitzkit/core";
|
||||
import { GameInterface } from "@blitzkit/game";
|
||||
import type { GameInterface } from "@blitzkit/game";
|
||||
import { clientUnmounted } from "./unmounted";
|
||||
|
||||
let _game: GameInterface | null = null;
|
||||
|
||||
if (!clientUnmounted) {
|
||||
const { GameInterface } = await import("@blitzkit/game");
|
||||
_game = new GameInterface(assertSecret(import.meta.env.PUBLIC_WOTB_CLIENT));
|
||||
}
|
||||
|
||||
|
||||
@@ -12,5 +12,7 @@ export { getStaticPaths } from "./[id].json";
|
||||
*/
|
||||
export async function GET({ params }: APIContext<never, { id: string }>) {
|
||||
const avatar = await api.avatar(params.id);
|
||||
return await imageProxy(avatar.profile_avatar!.avatar);
|
||||
return await imageProxy(
|
||||
api.mediaPrefix(avatar.profile_avatar!.avatar!.value),
|
||||
);
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { getStaticPaths as _getStaticPaths } from "../_index";
|
||||
|
||||
export const getStaticPaths = mixStaticPaths(_getStaticPaths, async () => {
|
||||
const group = api.metadata.group("CurrencyEntity");
|
||||
return group.map(({ name }) => ({ params: { id: name } }));
|
||||
return group.map(({ id }) => ({ params: { id } }));
|
||||
});
|
||||
|
||||
export async function GET({ params }: { params: { id: string } }) {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { api } from "../../../api/dynamic";
|
||||
import { imageProxy } from "../../../api/imageProxy";
|
||||
import { mixStaticPaths } from "../../../astro/mixStaticPaths";
|
||||
import { getStaticPaths as _getStaticPaths } from "../_index";
|
||||
|
||||
export const getStaticPaths = mixStaticPaths(_getStaticPaths, async () => {
|
||||
const group = api.metadata.group("ProxyEntity");
|
||||
return group.map(({ id }) => ({ params: { id } }));
|
||||
});
|
||||
|
||||
export async function GET({ params }: { params: { id: string } }) {
|
||||
const icon = await api.stuffIcon(params.id);
|
||||
return await imageProxy(icon);
|
||||
}
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
cd packages/website-ue
|
||||
bun run dev
|
||||
Reference in new issue
Block a user