tank icons

This commit is contained in:
tresabhi committed 2026-06-04 20:17:31 -05:00
1 parent 125f6c721d
commit 85ddedd481
10 files changed
+65 -58

No files matched your search

+4 -40
View File
@@ -24,56 +24,20 @@ public partial class GameInterface
private readonly BlitzFileProvider provider; private readonly BlitzFileProvider provider;
public HashSet<string> files; public HashSet<string> files;
public string[] tanksDirectoryNations;
public GameInterface(string directory, string map, string temp) public GameInterface(string directory, string map, string temp)
{ {
provider = new(directory, map, temp); provider = new(directory, map, temp);
files = [.. provider.Files.Keys]; files = [.. provider.Files.Keys];
var tanksBase = "Blitz/Content/Tanks/";
tanksDirectoryNations =
[
.. files
.Where(path => path.StartsWith(tanksBase))
.Select(path => path[tanksBase.Length..])
.Select(path => path.Split('/')[0])
.Where(nation => !nation.EndsWith(".uasset") && nation != "TankStub")
.Distinct(),
];
} }
public HashSet<string> Files => files; public HashSet<string> Files => files;
public string[] TanksDirectoryNations => tanksDirectoryNations;
public byte[] TankBigIcon(string tankId, string pdaName) public byte[] TankBigIcon(string tag)
{ {
foreach (var nation in tanksDirectoryNations) var pda = provider.Discovered<UPrimaryDataAsset>(tag);
{ var icon = pda.Get<FSoftObjectPath>("BigIcon");
var path = $"Blitz/Content/Tanks/{nation}/{tankId}/{pdaName}.{pdaName}"; return provider.Image(icon);
if (provider.TryLoadPackageObject<UPrimaryDataAsset>(path, out var pda))
{
var icon = pda.Get<FSoftObjectPath>("BigIcon");
var uTexture = icon.Load<UTexture2D>();
var cTexture = uTexture.Decode(ETexturePlatform.DesktopMobile);
if (cTexture is null)
{
Console.WriteLine($"No tank big icon found for {tankId} in {pdaName}");
return [];
}
var bitmap = cTexture.ToSkBitmap();
var data = bitmap.Encode(SKEncodedImageFormat.Webp, 80);
return data.ToArray();
}
}
Console.WriteLine($"No tank big icon found for {tankId} in {pdaName}");
return [];
} }
[GeneratedRegex(@"T_UI_Flag_(\w+)_S")] [GeneratedRegex(@"T_UI_Flag_(\w+)_S")]
@@ -67,6 +67,7 @@ public partial class BlitzFileProvider : DefaultFileProvider
public T Discovered<T>(string path) where T : UObject public T Discovered<T>(string path) where T : UObject
{ {
Console.WriteLine(discovered[path]);
return LoadPackageObject<T>(discovered[path]); return LoadPackageObject<T>(discovered[path]);
} }
+2 -1
View File
@@ -272,7 +272,8 @@
}, },
"loadout": { "loadout": {
"state": "State", "dynamics": "Dynamics",
"status": "Status",
"consumables": "Consumables", "consumables": "Consumables",
"modules": "Modules", "modules": "Modules",
"equipment": "Equipment", "equipment": "Equipment",
@@ -1,5 +1,5 @@
.characteristics-wrapper { .characteristics-wrapper {
margin: 0 var(--space-4); margin: var(--space-4);
--base-cell-width: 20rem; --base-cell-width: 20rem;
--group-span: 7; --group-span: 7;
@@ -13,7 +13,13 @@
} }
} }
.states { .state {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.status {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: var(--space-2); gap: var(--space-2);
@@ -55,22 +55,25 @@ export function TankopediaLoadout({ characteristics }: TankopediaLoadoutProps) {
return ( return (
<> <>
<State />
{showModules && <Modules />} {showModules && <Modules />}
<Equipment /> <Equipment />
<Consumables characteristics={characteristics} /> <Consumables characteristics={characteristics} />
<State />
<Status />
</> </>
); );
} }
function State() { function State() {
const strings = useStrings(); const strings = useStrings();
const status = Tankopedia.use((state) => state.protagonist.status);
const shell = Tankopedia.use((state) => state.protagonist.shell);
const speed = Tankopedia.use((state) => state.protagonist.speed);
return ( return (
<div className={styles.section}> <div className={styles.section}>
<div className={styles.header}> <div className={styles.header}>
<Heading size="4">{strings.tanks.loadout.state}</Heading> <Heading size="4">{strings.tanks.loadout.dynamics}</Heading>
<IconButton <IconButton
color="red" color="red"
@@ -84,7 +87,36 @@ function State() {
</IconButton> </IconButton>
</div> </div>
<div className={styles.states}> <div className={styles.state}>
<span>shell: {shell}</span>
<span>speed: {speed}</span>
</div>
</div>
);
}
function Status() {
const strings = useStrings();
const status = Tankopedia.use((state) => state.protagonist.status);
return (
<div className={styles.section}>
<div className={styles.header}>
<Heading size="4">{strings.tanks.loadout.status}</Heading>
<IconButton
color="red"
onClick={() => {
Tankopedia.mutate((draft) => {
draft.protagonist.consumables = [];
});
}}
>
<TrashIcon />
</IconButton>
</div>
<div className={styles.status}>
{vehicleStatusKeys.map((group, index) => ( {vehicleStatusKeys.map((group, index) => (
<div key={index} className={styles.group}> <div key={index} className={styles.group}>
{group.map((key) => ( {group.map((key) => (
@@ -1,24 +1,23 @@
import type { APIContext } from "astro"; import type { APIContext } from "astro";
import { api } from "../../../../api/dynamic"; import { api } from "../../../../api/dynamic";
import { import { clientUnmountedResponse } from "../../../../api/responses";
clientUnmountedResponse, import { mixStaticPaths } from "../../../../astro/mixStaticPaths";
notFoundResponse, import { assertDiscoveryTag } from "../../../../game/assertDiscoveryTag";
} from "../../../../api/responses";
import { game } from "../../../../game/game"; import { game } from "../../../../game/game";
import { clientUnmounted } from "../../../../game/unmounted"; import { clientUnmounted } from "../../../../game/unmounted";
import { getStaticPaths as _getStaticPaths } from "../../../[api]/tanks/[id].json"; import { getStaticPaths as _getStaticPaths } from "../../../[api]/tanks/[id].json";
import { getStaticPaths as __getStaticPaths } from "../../_index"; import { getStaticPaths as __getStaticPaths } from "../../_index";
import { mixStaticPaths } from "../../../../astro/mixStaticPaths";
export const getStaticPaths = mixStaticPaths(__getStaticPaths, _getStaticPaths); export const getStaticPaths = mixStaticPaths(__getStaticPaths, _getStaticPaths);
export async function GET({ params }: APIContext<never, { id: string }>) { export async function GET({ params }: APIContext<never, { id: string }>) {
if (clientUnmounted) return clientUnmountedResponse; if (clientUnmounted) return clientUnmountedResponse;
const tank = await api.tank(params.id); const item = api.metadata.item(params.id);
const image = game!.tankBigIcon(params.id, tank.tank!.visual_data); const assetDiscovery = item.BlitzStaticAssetsDiscovery();
const tag = assertDiscoveryTag(assetDiscovery);
const icon = game!.tankBigIcon(tag);
const array = new Uint8Array(icon);
if (image.length === 0) return notFoundResponse; return new Response(array);
return new Response(new Uint8Array(image));
} }
Whitespace-only changes.
@@ -17,6 +17,10 @@ export interface TankState {
speed: number; speed: number;
terrainHardness: TerrainHardness; terrainHardness: TerrainHardness;
isHullRotating: boolean;
isTurretRotating: boolean;
isGunRotating: boolean;
status: Record<VehicleStatusKey, boolean>; status: Record<VehicleStatusKey, boolean>;
} }