useCompatibility

This commit is contained in:
tresabhi committed 2026-09-23 10:39:12 -05:00
1 parent 33bb8ead3c
commit 750bdd236a
7 files changed
+59 -38

No files matched your search

@@ -9,14 +9,14 @@ message ConsumableDefinitions {
}
message Consumable {
required uint32 id = 1;
required I18nString name = 2;
required bool game_mode_exclusive = 5;
repeated ConsumableTankFilter include = 6;
repeated ConsumableTankFilter exclude = 7;
required uint32 id = 1;
required I18nString name = 2;
required bool game_mode_exclusive = 5;
repeated TankInclusivityFilter include = 6;
repeated TankInclusivityFilter exclude = 7;
}
message ConsumableTankFilter {
message TankInclusivityFilter {
oneof filter_type {
ConsumableTankTierFilter tiers = 1;
ConsumableTankIdsFilter ids = 2;
@@ -12,9 +12,9 @@ message ProvisionDefinitions {
message Provision {
reserved 3; // crew
required uint32 id = 1;
required I18nString name = 2;
required bool game_mode_exclusive = 5;
repeated ConsumableTankFilter include = 6;
repeated ConsumableTankFilter exclude = 7;
required uint32 id = 1;
required I18nString name = 2;
required bool game_mode_exclusive = 5;
repeated TankInclusivityFilter include = 6;
repeated TankInclusivityFilter exclude = 7;
}
@@ -1,5 +1,9 @@
import type { Consumable } from "@blitzkit/core";
import { TrashIcon } from "@radix-ui/react-icons";
import { useCompatibility } from "../../hooks/useCompatibility";
import { useConsumables } from "../../hooks/useConsumables";
import { useProtagonist } from "../../hooks/useProtagonist";
import { useProtagonistGun } from "../../hooks/useProtagonistGun";
import { useStrings } from "../../hooks/useStrings";
import { Tankopedia } from "../../stores/tankopedia";
import { hasUpgrades } from "../../tankopedia/hasUpgrades";
@@ -116,7 +120,8 @@ function Consumables({ characteristics }: ConsumablesProps) {
const strings = useStrings();
const consumables = useConsumables();
const tank = useProtagonist();
const isCompatible = useCompatibility(tank, characteristics);
const gun = useProtagonistGun();
const isCompatible = useCompatibility(tank, gun);
return (
<div className={styles.section}>
@@ -136,20 +141,13 @@ function Consumables({ characteristics }: ConsumablesProps) {
</div>
<div className={styles.consumables}>
{Object.entries(consumables.consumables).map(
([id, { compatibility, consumable, purchase }]) => {
if (!isCompatible(compatibility!)) return null;
{Object.entries(consumables.consumables).map(([id, consumable]) => {
if (!isCompatible(consumable.include, consumable.exclude)) {
return null;
}
return (
<Consumable
key={id}
id={id}
consumable={consumable!}
purchase={purchase!}
/>
);
},
)}
return <Consumable key={id} id={id} consumable={consumable} />;
})}
</div>
</div>
);
@@ -157,8 +155,7 @@ function Consumables({ characteristics }: ConsumablesProps) {
interface ConsumableProps {
id: string;
consumable: ConsumableComponent;
purchase: BlitzStaticPurchaseComponent;
consumable: Consumable;
}
function Consumable({ id, consumable, purchase }: ConsumableProps) {
@@ -1,17 +1,26 @@
import {
Consumable,
ConsumableTankCategoryFilterCategory,
GunDefinition,
Provision,
TankDefinition,
} from "@blitzkit/protos";
type GunDefinition,
type TankDefinition,
type TankInclusivityFilter,
} from "@blitzkit/core";
export function checkConsumableProvisionInclusivity(
consumableProvision: Consumable | Provision,
export function useCompatibility(tank: TankDefinition, gun: GunDefinition) {
return function (
include?: TankInclusivityFilter[],
exclude?: TankInclusivityFilter[],
) {
return tankCompatibility(tank, gun, include, exclude);
};
}
function tankCompatibility(
tank: TankDefinition,
gun: GunDefinition,
include?: TankInclusivityFilter[],
exclude?: TankInclusivityFilter[],
) {
const included = consumableProvision.include?.every((rule) => {
const included = include?.every((rule) => {
switch (rule.filter_type!.$case) {
case "tiers":
return (
@@ -29,7 +38,7 @@ export function checkConsumableProvisionInclusivity(
throw new SyntaxError("Category filtering found in include rule");
}
});
const excluded = consumableProvision.exclude?.some((rule) => {
const excluded = exclude?.some((rule) => {
switch (rule.filter_type!.$case) {
case "tiers":
return (
@@ -53,5 +62,5 @@ export function checkConsumableProvisionInclusivity(
}
});
return consumableProvision.include?.length > 0 && included && !excluded;
return include !== undefined && include?.length > 0 && included && !excluded;
}
@@ -5,6 +5,5 @@ import { useAwait } from "./useAwait";
export function useProtagonist() {
const id = Tankopedia.use((state) => state.protagonist.tank);
const tank = useAwait(() => api.tank(id), `tank-${id}`);
return tank;
}
@@ -0,0 +1,8 @@
import { Tankopedia } from "../stores/tankopedia";
import { useProtagonistTurret } from "./useProtagonistTurret";
export function useProtagonistGun() {
const id = Tankopedia.use((state) => state.protagonist.gun);
const turret = useProtagonistTurret();
return turret.guns[id];
}
@@ -0,0 +1,8 @@
import { Tankopedia } from "../stores/tankopedia";
import { useProtagonist } from "./useProtagonist";
export function useProtagonistTurret() {
const id = Tankopedia.use((state) => state.protagonist.gun);
const tank = useProtagonist();
return tank.turrets[id];
}