feat: upgrade tankopedia stores

This commit is contained in:
TrèsAbhi committed 2024-07-09 14:43:33 -05:00
1 parent 5bf9f8ca9e
commit 84bbb05d43
26 files changed
+356 -356

No files matched your search

+13 -10
View File
@@ -1,5 +1,6 @@
'use client';
import { create } from 'zustand';
import { TankClass, TreeType } from '../components/Tanks';
import { Tier } from '../core/blitzkit/tankDefinitions';
import { createNextSafeStore } from '../core/zustand/createNextSafeStore';
@@ -14,13 +15,15 @@ export interface TankFilters {
searching: boolean;
}
export const { Provider, use, useMutation, useStore } =
createNextSafeStore<TankFilters>({
tiers: [],
nations: [],
classes: [],
types: [],
testing: 'include',
search: undefined,
searching: false,
});
export const { Provider, use, useMutation, useStore } = createNextSafeStore(
() =>
create<TankFilters>()(() => ({
tiers: [],
nations: [],
classes: [],
types: [],
testing: 'include',
search: undefined,
searching: false,
})),
);
+8 -5
View File
@@ -1,5 +1,6 @@
'use client';
import { create } from 'zustand';
import { createNextSafeStore } from '../../core/zustand/createNextSafeStore';
import { tankPerformanceSortTypeNames } from './constants';
@@ -10,8 +11,10 @@ export interface TankPerformanceSort {
direction: -1 | 1;
}
export const { Provider, use, useMutation, useStore } =
createNextSafeStore<TankPerformanceSort>({
type: 'winrate',
direction: -1,
});
export const { Provider, use, useMutation, useStore } = createNextSafeStore(
() =>
create<TankPerformanceSort>()(() => ({
type: 'winrate',
direction: -1,
})),
);
-218
View File
@@ -1,218 +0,0 @@
import { produce } from 'immer';
import { merge } from 'lodash';
import { Vector3 } from 'three';
import { create } from 'zustand';
import { persist, subscribeWithSelector } from 'zustand/middleware';
import { ENVIRONMENTS } from '../app/tools/tankopedia/[id]/components/Lighting';
import { ArmorType } from '../components/Armor/components/SpacedArmorScene';
import { ExternalModuleVariant } from '../components/Armor/components/SpacedArmorSceneComponent';
import { TankClass, TreeType } from '../components/Tanks';
import { Tier } from '../core/blitzkit/tankDefinitions';
export type TankopediaSortBy = keyof typeof SORT_NAMES;
export type TankopediaSortDirection = 'ascending' | 'descending';
export type TankopediaTestTankDisplay = 'include' | 'exclude' | 'only';
export type TankopediaMode = 'model' | 'armor';
export interface TankopediaPersistent {
model: {
visual: {
wireframe: boolean;
opaque: boolean;
environment: (typeof ENVIRONMENTS)[number];
showGrid: boolean;
greenPenetration: boolean;
showEnvironment: boolean;
showSpacedArmor: boolean;
};
};
sort: {
by: TankopediaSortBy;
direction: TankopediaSortDirection;
};
filters: {
tiers: Tier[];
types: TankClass[];
treeTypes: TreeType[];
nations: string[];
test: TankopediaTestTankDisplay;
page: number;
};
mode: TankopediaMode;
}
interface TankopediaTemporary {
shot?: Shot;
skills: Record<string, number>;
controlsEnabled: boolean;
}
export interface ShotLayerBase {
index: number;
thickness: number;
point: Vector3;
surfaceNormal: Vector3;
status: 'blocked' | 'penetration' | 'ricochet';
}
interface ShotLayerExternal extends ShotLayerBase {
type: ArmorType.External;
variant: ExternalModuleVariant;
}
export interface ShotLayerNonExternal extends ShotLayerBase {
type: Exclude<ArmorType, ArmorType.External>;
angle: number;
thicknessAngled: number;
}
export interface ShotLayerGap {
type: null;
status: 'penetration' | 'blocked';
distance: number;
}
export type ShotLayer = ShotLayerExternal | ShotLayerNonExternal | ShotLayerGap;
export type Shot = {
containsGaps: boolean;
damage: number;
in: {
surfaceNormal: Vector3;
status: ShotStatus;
layers: ShotLayer[];
};
out?: {
surfaceNormal: Vector3;
status: ShotStatus;
layers: ShotLayer[];
};
};
export type ShotStatus = 'penetration' | 'blocked' | 'ricochet' | 'splash';
export type ArmorPiercingLayer =
| {
distance: number;
nominal: number;
angled: number;
ricochet: boolean;
type: 'core' | 'spaced' | 'external';
}
| {
type: 'gap';
gap: number;
};
export const SORT_NAMES = {
'meta.none': 'none',
'survivability.health': 'health',
'survivability.viewRange': 'view range',
'survivability.camouflageStill': 'camouflage still',
'survivability.camouflageMoving': 'camouflage moving',
'survivability.camouflageShooting': 'camouflage shooting',
'survivability.volume': 'volume',
'survivability.length': 'length',
'fire.dpm': 'standard DPM',
'fire.dpmPremium': 'premium DPM',
'fire.reload': 'reload',
'fire.caliber': 'caliber',
'fire.standardPenetration': 'standard penetration',
'fire.premiumPenetration': 'premium penetration',
'fire.damage': 'damage',
'fire.shellVelocity': 'shell velocity',
'fire.aimTime': 'aim time',
'fire.dispersionStill': 'dispersion still',
'fire.dispersionMoving': 'dispersion moving',
'fire.gunDepression': 'gun depression',
'fire.gunElevation': 'gun elevation',
'maneuverability.forwardsSpeed': 'forwards speed',
'maneuverability.backwardsSpeed': 'backwards speed',
'maneuverability.power': 'power',
'maneuverability.powerToWeight': 'power to weight',
'maneuverability.weight': 'weight',
'maneuverability.traverseSpeed': 'traverse speed',
} as const;
export const SORT_UNITS: Record<TankopediaSortBy, string | undefined> = {
'meta.none': undefined,
'survivability.health': 'hp',
'fire.aimTime': 's',
'fire.caliber': 'mm',
'fire.damage': 'hp',
'fire.dispersionMoving': 'm',
'fire.dispersionStill': 'm',
'fire.dpm': undefined,
'fire.dpmPremium': undefined,
'fire.gunDepression': '°',
'fire.gunElevation': '°',
'fire.premiumPenetration': 'mm',
'fire.reload': 's',
'fire.shellVelocity': 'm/s',
'fire.standardPenetration': 'mm',
'maneuverability.backwardsSpeed': 'kph',
'maneuverability.forwardsSpeed': 'kph',
'maneuverability.power': 'hp',
'maneuverability.powerToWeight': 'hp/tn',
'maneuverability.traverseSpeed': '°/s',
'maneuverability.weight': 'tn',
'survivability.camouflageMoving': '%',
'survivability.camouflageShooting': '%',
'survivability.camouflageStill': '%',
'survivability.length': 'm',
'survivability.viewRange': 'm',
'survivability.volume': 'm^3',
};
export const useTankopediaPersistent = create<TankopediaPersistent>()(
persist(
subscribeWithSelector<TankopediaPersistent>(() => ({
model: {
visual: {
showSpacedArmor: true,
wireframe: false,
opaque: false,
environment: ENVIRONMENTS[0],
controlsEnabled: true,
showGrid: true,
greenPenetration: false,
showEnvironment: false,
},
},
sort: {
by: 'meta.none',
direction: 'descending',
},
filters: {
tiers: [],
types: [],
treeTypes: [],
nations: [],
test: 'include',
page: 0,
},
mode: 'model',
})),
{ name: 'tankopedia', merge: (a, b) => merge(b, a) },
),
);
export const useTankopediaTemporary = create<TankopediaTemporary>()(
subscribeWithSelector<TankopediaTemporary>(() => ({
skills: {},
controlsEnabled: true,
})),
);
export default function mutateTankopediaPersistent(
recipe: (draft: TankopediaPersistent) => void,
) {
useTankopediaPersistent.setState(produce(recipe));
}
export function mutateTankopediaTemporary(
recipe: (draft: TankopediaTemporary) => void,
) {
useTankopediaTemporary.setState(produce(recipe));
}
+80
View File
@@ -0,0 +1,80 @@
import { Vector3 } from 'three';
import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware';
import { ArmorType } from '../components/Armor/components/SpacedArmorScene';
import { ExternalModuleVariant } from '../components/Armor/components/SpacedArmorSceneComponent';
import { createNextSafeStore } from '../core/zustand/createNextSafeStore';
interface TankopediaEphemeral {
shot?: Shot;
skills: Record<string, number>;
controlsEnabled: boolean;
}
export interface ShotLayerBase {
index: number;
thickness: number;
point: Vector3;
surfaceNormal: Vector3;
status: 'blocked' | 'penetration' | 'ricochet';
}
interface ShotLayerExternal extends ShotLayerBase {
type: ArmorType.External;
variant: ExternalModuleVariant;
}
export interface ShotLayerNonExternal extends ShotLayerBase {
type: Exclude<ArmorType, ArmorType.External>;
angle: number;
thicknessAngled: number;
}
export interface ShotLayerGap {
type: null;
status: 'penetration' | 'blocked';
distance: number;
}
export type ShotLayer = ShotLayerExternal | ShotLayerNonExternal | ShotLayerGap;
export type Shot = {
containsGaps: boolean;
damage: number;
in: {
surfaceNormal: Vector3;
status: ShotStatus;
layers: ShotLayer[];
};
out?: {
surfaceNormal: Vector3;
status: ShotStatus;
layers: ShotLayer[];
};
};
export type ShotStatus = 'penetration' | 'blocked' | 'ricochet' | 'splash';
export type ArmorPiercingLayer =
| {
distance: number;
nominal: number;
angled: number;
ricochet: boolean;
type: 'core' | 'spaced' | 'external';
}
| {
type: 'gap';
gap: number;
};
export const { Provider, use, useMutation, useStore } = createNextSafeStore(
() =>
create<TankopediaEphemeral>()(
subscribeWithSelector<TankopediaEphemeral>(() => ({
skills: {},
controlsEnabled: true,
})),
),
);
@@ -0,0 +1,60 @@
import { TankopediaSortBy } from '.';
export const SORT_UNITS: Record<TankopediaSortBy, string | undefined> = {
'meta.none': undefined,
'survivability.health': 'hp',
'fire.aimTime': 's',
'fire.caliber': 'mm',
'fire.damage': 'hp',
'fire.dispersionMoving': 'm',
'fire.dispersionStill': 'm',
'fire.dpm': undefined,
'fire.dpmPremium': undefined,
'fire.gunDepression': '°',
'fire.gunElevation': '°',
'fire.premiumPenetration': 'mm',
'fire.reload': 's',
'fire.shellVelocity': 'm/s',
'fire.standardPenetration': 'mm',
'maneuverability.backwardsSpeed': 'kph',
'maneuverability.forwardsSpeed': 'kph',
'maneuverability.power': 'hp',
'maneuverability.powerToWeight': 'hp/tn',
'maneuverability.traverseSpeed': '°/s',
'maneuverability.weight': 'tn',
'survivability.camouflageMoving': '%',
'survivability.camouflageShooting': '%',
'survivability.camouflageStill': '%',
'survivability.length': 'm',
'survivability.viewRange': 'm',
'survivability.volume': 'm^3',
};
export const SORT_NAMES = {
'meta.none': 'none',
'survivability.health': 'health',
'survivability.viewRange': 'view range',
'survivability.camouflageStill': 'camouflage still',
'survivability.camouflageMoving': 'camouflage moving',
'survivability.camouflageShooting': 'camouflage shooting',
'survivability.volume': 'volume',
'survivability.length': 'length',
'fire.dpm': 'standard DPM',
'fire.dpmPremium': 'premium DPM',
'fire.reload': 'reload',
'fire.caliber': 'caliber',
'fire.standardPenetration': 'standard penetration',
'fire.premiumPenetration': 'premium penetration',
'fire.damage': 'damage',
'fire.shellVelocity': 'shell velocity',
'fire.aimTime': 'aim time',
'fire.dispersionStill': 'dispersion still',
'fire.dispersionMoving': 'dispersion moving',
'fire.gunDepression': 'gun depression',
'fire.gunElevation': 'gun elevation',
'maneuverability.forwardsSpeed': 'forwards speed',
'maneuverability.backwardsSpeed': 'backwards speed',
'maneuverability.power': 'power',
'maneuverability.powerToWeight': 'power to weight',
'maneuverability.weight': 'weight',
'maneuverability.traverseSpeed': 'traverse speed',
} as const;
+75
View File
@@ -0,0 +1,75 @@
import { merge } from 'lodash';
import { create } from 'zustand';
import { persist, subscribeWithSelector } from 'zustand/middleware';
import { ENVIRONMENTS } from '../../app/tools/tankopedia/[id]/components/Lighting';
import { TankClass, TreeType } from '../../components/Tanks';
import { Tier } from '../../core/blitzkit/tankDefinitions';
import { createNextSafeStore } from '../../core/zustand/createNextSafeStore';
import { SORT_NAMES } from './constants';
export type TankopediaSortBy = keyof typeof SORT_NAMES;
export type TankopediaSortDirection = 'ascending' | 'descending';
export type TankopediaTestTankDisplay = 'include' | 'exclude' | 'only';
export type TankopediaMode = 'model' | 'armor';
export interface TankopediaPersistent {
model: {
visual: {
wireframe: boolean;
opaque: boolean;
environment: (typeof ENVIRONMENTS)[number];
showGrid: boolean;
greenPenetration: boolean;
showEnvironment: boolean;
showSpacedArmor: boolean;
};
};
sort: {
by: TankopediaSortBy;
direction: TankopediaSortDirection;
};
filters: {
tiers: Tier[];
types: TankClass[];
treeTypes: TreeType[];
nations: string[];
test: TankopediaTestTankDisplay;
page: number;
};
mode: TankopediaMode;
}
export const { Provider, use, useMutation, useStore } = createNextSafeStore(
() =>
create<TankopediaPersistent>()(
persist(
subscribeWithSelector<TankopediaPersistent>(() => ({
model: {
visual: {
showSpacedArmor: true,
wireframe: false,
opaque: false,
environment: ENVIRONMENTS[0],
showGrid: true,
greenPenetration: false,
showEnvironment: false,
},
},
sort: {
by: 'meta.none',
direction: 'descending',
},
filters: {
tiers: [],
types: [],
treeTypes: [],
nations: [],
test: 'include',
page: 0,
},
mode: 'model',
})),
{ name: 'tankopedia', merge: (a, b) => merge(b, a) },
),
),
);
+12 -6
View File
@@ -1,15 +1,21 @@
'use client';
import { create } from 'zustand';
import { createNextSafeStore } from '../core/zustand/createNextSafeStore';
import { TankopediaSortBy, TankopediaSortDirection } from './tankopedia';
import {
TankopediaSortBy,
TankopediaSortDirection,
} from './tankopediaPersistent';
export interface TankopediaSort {
by: TankopediaSortBy;
direction: TankopediaSortDirection;
}
export const { Provider, use, useMutation, useStore } =
createNextSafeStore<TankopediaSort>({
by: 'meta.none',
direction: 'descending',
});
export const { Provider, use, useMutation, useStore } = createNextSafeStore(
() =>
create<TankopediaSort>()(() => ({
by: 'meta.none',
direction: 'descending',
})),
);