mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
tank icons
This commit is contained in:
1 parent
125f6c721d
commit
85ddedd481
10 files changed
+65
-58
No files matched your search
+1
-1
Submodule packages/closed updated: e14207178a...ebdf6236ca.
@@ -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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user