diff --git a/packages/core/src/blitzkit/index.ts b/packages/core/src/blitzkit/index.ts index 3c687f118..b0a422e32 100644 --- a/packages/core/src/blitzkit/index.ts +++ b/packages/core/src/blitzkit/index.ts @@ -1,6 +1,6 @@ export * from './assertSecret'; export * from './asset'; -// export * from './availableProvisions'; +export * from './availableProvisions'; // export * from './averageDefinitions'; // export * from './camouflageDefinitions'; // export * from './checkConsumableProvisionInclusivity'; @@ -11,7 +11,7 @@ export * from './asset'; // export * from './degressiveStat'; // export * from './discoveredIdDefinitions'; // export * from './emblemURL'; -// export * from './equipmentDefinitions'; +export * from './equipmentDefinitions'; export * from './eventManager'; // export * from './fetchCdonLz4'; // export * from './flagUserActivity'; @@ -21,7 +21,7 @@ export * from './gameDefinitions'; // export * from './getArchivedRatingLeaderboard'; // export * from './getArchivedRatingMidnightLeaderboard'; // export * from './getTimeDaysAgo'; -// export * from './isExplosive'; +export * from './isExplosive'; // export * from './linkBlitzAndDiscord'; // export * from './mapDefinitions'; export * from './modelDefinitions'; @@ -42,7 +42,7 @@ export * from './tankDefinitions'; export * from './tankIcon'; export * from './tankNames'; export * from './unionBoundingBox'; -// export * from './uniqueGuns'; +export * from './uniqueGuns'; // export * from './unwrapBlitzkitResponse'; // export * from './votes'; // export * from './withCORSProxy'; diff --git a/packages/website-legacy/package.json b/packages/website-legacy/package.json index 3e4104ec2..dd0e5952d 100644 --- a/packages/website-legacy/package.json +++ b/packages/website-legacy/package.json @@ -13,7 +13,6 @@ "@blitzkit/core": "workspace:*", "fuzzysort": "^2.0.4", "@nivo/bar": "^0.87.0", - "three": "0.159.0", "lodash": "^4.17.21", "next": "^14.2.7", "three-stdlib": "^2.32.2", @@ -26,13 +25,10 @@ "react-dom": "^18.3.1", "react-fuzzysort": "^1.0.1", "immer": "^10.1.1", - "@vanilla-extract/dynamic": "^2.1.2", + "@vanilla-extract/dynamic": "^2.1.2" }, "devDependencies": { - "@types/react-dom": "^18", "@types/lodash": "^4.17.7", - "@types/three": "^0.160.0", - "@vanilla-extract/next-plugin": "^2.4.5", - "@types/react": "^18.3.5" + "@vanilla-extract/next-plugin": "^2.4.5" } } diff --git a/packages/website/package.json b/packages/website/package.json index db5bdeb2c..4f2353317 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -18,6 +18,7 @@ "@radix-ui/themes": "^3.1.3", "@vanilla-extract/css": "^1.15.5", "astro": "^4.15.6", + "three": "0.159.0", "@react-three/drei": "^9.111.5", "@react-three/fiber": "^8.17.6", "astro-purgecss": "^4.6.0", @@ -29,6 +30,9 @@ "react-promise-suspense": "^0.3.4" }, "devDependencies": { - "@vanilla-extract/vite-plugin": "^4.0.15" + "@types/three": "^0.160.0", + "@vanilla-extract/vite-plugin": "^4.0.15", + "@types/react-dom": "^18", + "@types/react": "^18.3.5" } } diff --git a/packages/website/src/components/Armor/components/ArmorPlateDisplay.tsx b/packages/website/src/components/Armor/components/ArmorPlateDisplay.tsx index 77ad279c1..029278723 100644 --- a/packages/website/src/components/Armor/components/ArmorPlateDisplay.tsx +++ b/packages/website/src/components/Armor/components/ArmorPlateDisplay.tsx @@ -9,6 +9,10 @@ import { } from '@radix-ui/themes'; import { Html } from '@react-three/drei'; import { useRef } from 'react'; +import { radToDeg } from 'three/src/math/MathUtils.js'; +import { resolveArmorIndex } from '../../../core/blitzkit/resolveArmorIndex'; +import { App } from '../../../stores/app'; +import { Duel } from '../../../stores/duel'; import { TankopediaEphemeral } from '../../../stores/tankopediaEphemeral'; import { layerTypeNames } from './ShotDisplayCard'; import { ArmorType } from './SpacedArmorScene'; diff --git a/packages/website/src/components/Armor/components/PrimaryArmorScene.tsx b/packages/website/src/components/Armor/components/PrimaryArmorScene.tsx index bffdeebe6..4e7acaf9c 100644 --- a/packages/website/src/components/Armor/components/PrimaryArmorScene.tsx +++ b/packages/website/src/components/Armor/components/PrimaryArmorScene.tsx @@ -6,6 +6,7 @@ import { resolveArmor } from '../../../core/blitzkit/resolveThickness'; import { useArmor } from '../../../hooks/useArmor'; import { useTankModelDefinition } from '../../../hooks/useTankModelDefinition'; import { useTankTransform } from '../../../hooks/useTankTransform'; +import { Duel } from '../../../stores/duel'; import { ModelTankWrapper } from './ModelTankWrapper'; import { PrimaryArmorSceneComponent } from './PrimaryArmorSceneComponent'; diff --git a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx index 51ad3a6e9..a396c737f 100644 --- a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx +++ b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx @@ -1,5 +1,5 @@ import { - ShellDefinition, + type ShellDefinition, canSplash, isExplosive, resolveNearPenetration, @@ -8,13 +8,13 @@ import { import { useFrame } from '@react-three/fiber'; import { useEffect } from 'react'; import { MeshBasicMaterial, Object3D, ShaderMaterial, Vector2 } from 'three'; -import { degToRad } from 'three/src/math/MathUtils'; -import { hasEquipment } from '../../../../../../website-legacy/src/core/blitzkit/hasEquipment'; -import { jsxTree } from '../../../../../../website-legacy/src/core/blitzkit/jsxTree'; -import * as Duel from '../../../../../../website-legacy/src/stores/duel'; -import * as TankopediaPersistent from '../../../../../../website-legacy/src/stores/tankopediaPersistent'; -import fragmentShader from './shaders/fragment.glsl'; -import vertexShader from './shaders/vertex.glsl'; +import { degToRad } from 'three/src/math/MathUtils.js'; +import { hasEquipment } from '../../../../core/blitzkit/hasEquipment'; +import { jsxTree } from '../../../../core/blitzkit/jsxTree'; +import { Duel, type EquipmentMatrix } from '../../../../stores/duel'; +import { TankopediaPersistent } from '../../../../stores/tankopediaPersistent'; +import fragmentShader from './shaders/fragment.glsl?raw'; +import vertexShader from './shaders/vertex.glsl?raw'; import { spacedArmorRenderTarget } from './target'; interface PrimaryArmorSceneComponentProps { @@ -76,15 +76,17 @@ export function PrimaryArmorSceneComponent({ await handleProtagonistEquipmentChange(duel.protagonist.equipmentMatrix); await handleAntagonistEquipmentChange(duel.antagonist.equipmentMatrix); } - function handleVisualChange( - visual: TankopediaPersistent.TankopediaPersistent['model']['visual'], - ) { - material.uniforms.greenPenetration.value = visual.greenPenetration; - material.uniforms.opaque.value = visual.opaque || visual.wireframe; - material.wireframe = visual.wireframe; + function handleGreenPenetrationChange(greenPenetration: boolean) { + material.uniforms.greenPenetration.value = greenPenetration; + } + function handleOpaqueChange(opaque: boolean) { + material.uniforms.opaque.value = opaque; + } + function handleWireframeChange(wireframe: boolean) { + material.wireframe = wireframe; } async function handleProtagonistEquipmentChange( - equipment: Duel.EquipmentMatrix, + equipment: EquipmentMatrix, ) { const duel = duelStore.getState(); const hasEnhancedArmor = await hasEquipment( @@ -96,9 +98,7 @@ export function PrimaryArmorSceneComponent({ ? thickness * 1.03 : thickness; } - async function handleAntagonistEquipmentChange( - equipment: Duel.EquipmentMatrix, - ) { + async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) { const duel = duelStore.getState(); const shell = duel.antagonist.shell; const penetration = resolveNearPenetration(shell.penetration); @@ -114,7 +114,11 @@ export function PrimaryArmorSceneComponent({ } handleShellChange(duelStore.getState().antagonist.shell); - handleVisualChange(tankopediaPersistentStore.getState().model.visual); + handleGreenPenetrationChange( + tankopediaPersistentStore.getState().greenPenetration, + ); + handleOpaqueChange(tankopediaPersistentStore.getState().opaque); + handleWireframeChange(tankopediaPersistentStore.getState().wireframe); handleProtagonistEquipmentChange( duelStore.getState().protagonist.equipmentMatrix, ); @@ -125,9 +129,10 @@ export function PrimaryArmorSceneComponent({ const unsubscribes = [ duelStore.subscribe((state) => state.antagonist.shell, handleShellChange), tankopediaPersistentStore.subscribe( - (state) => state.model.visual, - handleVisualChange, + (state) => state.greenPenetration, + handleGreenPenetrationChange, ), + duelStore.subscribe( (state) => state.protagonist.equipmentMatrix, handleProtagonistEquipmentChange, diff --git a/packages/website/src/components/Armor/components/ShotDisplay.tsx b/packages/website/src/components/Armor/components/ShotDisplay.tsx index 2c7e7c92b..53bc3a1ba 100644 --- a/packages/website/src/components/Armor/components/ShotDisplay.tsx +++ b/packages/website/src/components/Armor/components/ShotDisplay.tsx @@ -1,9 +1,9 @@ -import { J_HAT, K_HAT } from '@blitzkit/core'; -import { Box, Flex, Text } from '@radix-ui/themes'; +import { K_HAT } from '@blitzkit/core'; +import { Box, Text } from '@radix-ui/themes'; import { Html } from '@react-three/drei'; import { useFrame } from '@react-three/fiber'; import { clamp } from 'lodash-es'; -import { type ComponentProps, useEffect, useRef } from 'react'; +import { useEffect, useRef, type ComponentProps } from 'react'; import { BufferGeometry, DoubleSide, @@ -16,12 +16,16 @@ import { Path, Quaternion, } from 'three'; -import { useFullScreen } from '../../../../../website-legacy/src/hooks/useFullScreen'; -import * as TankopediaEphemeral from '../../../../../website-legacy/src/stores/tankopediaEphemeral'; +import { useFullScreen } from '../../../hooks/useFullScreen'; +import { + TankopediaEphemeral, + type ShotLayerNonExternal, + type ShotStatus, +} from '../../../stores/tankopediaEphemeral'; import { ShotDisplayCard } from './ShotDisplayCard'; export const shotStatusColors: Record< - TankopediaEphemeral.ShotStatus, + ShotStatus, ComponentProps['color'] > = { blocked: 'red', @@ -127,16 +131,13 @@ export function ShotDisplay() { }, 0) + SHOT_DISPLAY_LENGTH_INFINITY; const outLength = shot.out && shot.out.layers.length > 0 - ? ( - shot.in.layers.at(-1) as TankopediaEphemeral.ShotLayerNonExternal - ).point.distanceTo( - (shot.out.layers.at(-1) as TankopediaEphemeral.ShotLayerNonExternal) - .point, + ? (shot.in.layers.at(-1) as ShotLayerNonExternal).point.distanceTo( + (shot.out.layers.at(-1) as ShotLayerNonExternal).point, ) : SHOT_DISPLAY_LENGTH_INFINITY; const inLast = shot.in.layers.findLast( (layer) => layer.type !== null, - ) as TankopediaEphemeral.ShotLayerNonExternal; + ) as ShotLayerNonExternal; const outTitleColor = shot.out ? shotStatusColors[shot.out.status] : undefined; @@ -182,7 +183,7 @@ export function ShotDisplay() { - {[...shot.in.layers, ...(shot.out?.layers ?? [])].map((layer, index) => { + {/* {[...shot.in.layers, ...(shot.out?.layers ?? [])].map((layer, index) => { if (layer.type === null) return null; const shotStatusColor = @@ -275,7 +276,7 @@ export function ShotDisplay() { /> - )} + )} */} ); } diff --git a/packages/website/src/components/Armor/components/ShotDisplayCard.tsx b/packages/website/src/components/Armor/components/ShotDisplayCard.tsx index 544d97d6e..50bb50ea3 100644 --- a/packages/website/src/components/Armor/components/ShotDisplayCard.tsx +++ b/packages/website/src/components/Armor/components/ShotDisplayCard.tsx @@ -1,17 +1,11 @@ -import { - Card, - CardProps, - Flex, - Inset, - Separator, - Text, -} from '@radix-ui/themes'; +import { Flex, Text } from '@radix-ui/themes'; import type { ComponentProps } from 'react'; -import { radToDeg } from 'three/src/math/MathUtils'; -import * as TankopediaEphemeral from '../../../../../website-legacy/src/stores/tankopediaEphemeral'; -import { shotStatusColors } from './ShotDisplay'; +import type { + ShotLayer, + ShotStatus, +} from '../../../stores/tankopediaEphemeral'; import { ArmorType } from './SpacedArmorScene'; -import { ExternalModuleVariant } from './SpacedArmorSceneComponent'; +import type { ExternalModuleVariant } from './SpacedArmorSceneComponent'; export const layerTypeNames: Record = { [ArmorType.Primary]: 'Primary', @@ -25,7 +19,7 @@ const externalLayerNames: Record = { track: 'Tracks', }; -const shotStatusNames: Record = { +const shotStatusNames: Record = { blocked: 'Blocked', ricochet: 'Ricochet', penetration: 'penetration', @@ -42,7 +36,7 @@ function LayerEntry({ layerIndex?: string; shotStatusColor: ComponentProps['color']; layerName: string; - layer: TankopediaEphemeral.ShotLayer; + layer: ShotLayer; angle?: number; }) { return ( @@ -95,7 +89,7 @@ function LayerEntry({ } interface ShotDisplayCardProps extends CardProps { - shot: TankopediaEphemeral.Shot; + shot: Shot; } export function ShotDisplayCard({ shot, ...props }: ShotDisplayCardProps) { diff --git a/packages/website/src/components/Armor/components/SpacedArmorScene.tsx b/packages/website/src/components/Armor/components/SpacedArmorScene.tsx index 6b3482211..8e354c36a 100644 --- a/packages/website/src/components/Armor/components/SpacedArmorScene.tsx +++ b/packages/website/src/components/Armor/components/SpacedArmorScene.tsx @@ -7,6 +7,7 @@ import { useArmor } from '../../../hooks/useArmor'; import { useModel } from '../../../hooks/useModel'; import { useTankModelDefinition } from '../../../hooks/useTankModelDefinition'; import { useTankTransform } from '../../../hooks/useTankTransform'; +import { Duel } from '../../../stores/duel'; import { ModelTankWrapper } from './ModelTankWrapper'; import { SpacedArmorSceneComponent } from './SpacedArmorSceneComponent'; diff --git a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/index.tsx b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/index.tsx index 075eb8658..938054342 100644 --- a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/index.tsx +++ b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/index.tsx @@ -16,8 +16,8 @@ import { hasEquipment } from '../../../../../../core/blitzkit/hasEquipment'; import { jsxTree } from '../../../../../../core/blitzkit/jsxTree'; import { Duel, type EquipmentMatrix } from '../../../../../../stores/duel'; import { ArmorType } from '../../../SpacedArmorScene'; -import fragmentShader from './shaders/fragment.glsl'; -import vertexShader from './shaders/vertex.glsl'; +import fragmentShader from './shaders/fragment.glsl?raw'; +import vertexShader from './shaders/vertex.glsl?raw'; interface SpacedArmorSubExternalProps { node: Object3D; diff --git a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/index.tsx b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/index.tsx index 85064ce16..c2123624d 100644 --- a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/index.tsx +++ b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/index.tsx @@ -1,24 +1,24 @@ import { - ShellDefinition, isExplosive, resolveNearPenetration, resolvePenetrationCoefficient, + type ShellDefinition, } from '@blitzkit/core'; import { useEffect } from 'react'; import { AdditiveBlending, MeshBasicMaterial, - Object3D, ShaderMaterial, + type Object3D, } from 'three'; -import { degToRad } from 'three/src/math/MathUtils'; -import { ArmorUserData } from '../..'; -import { hasEquipment } from '../../../../../../../../website-legacy/src/core/blitzkit/hasEquipment'; -import { jsxTree } from '../../../../../../../../website-legacy/src/core/blitzkit/jsxTree'; -import * as Duel from '../../../../../../../../website-legacy/src/stores/duel'; +import { degToRad } from 'three/src/math/MathUtils.js'; +import type { ArmorUserData } from '../..'; +import { hasEquipment } from '../../../../../../core/blitzkit/hasEquipment'; +import { jsxTree } from '../../../../../../core/blitzkit/jsxTree'; +import { Duel, type EquipmentMatrix } from '../../../../../../stores/duel'; import { ArmorType } from '../../../SpacedArmorScene'; -import fragmentShader from './shaders/fragment.glsl'; -import vertexShader from './shaders/vertex.glsl'; +import fragmentShader from './shaders/fragment.glsl?raw'; +import vertexShader from './shaders/vertex.glsl?raw'; interface SpacedArmorSubSpacedProps { node: Object3D; @@ -66,7 +66,7 @@ export function SpacedArmorSubSpaced({ ); } async function handleProtagonistEquipmentChange( - equipment: Duel.EquipmentMatrix, + equipment: EquipmentMatrix, ) { const duel = duelStore.getState(); const hasEnhancedArmor = await hasEquipment( @@ -78,9 +78,7 @@ export function SpacedArmorSubSpaced({ ? thickness * 1.03 : thickness; } - async function handleAntagonistEquipmentChange( - equipment: Duel.EquipmentMatrix, - ) { + async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) { const duel = duelStore.getState(); const shell = duelStore.getState().antagonist.shell; const penetration = resolveNearPenetration(shell.penetration); diff --git a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx index 79b549ef9..dbf378374 100644 --- a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx +++ b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx @@ -1,5 +1,5 @@ import { - type ShellType, + ShellType, isExplosive, resolveNearPenetration, resolvePenetrationCoefficient, @@ -16,9 +16,17 @@ import { Scene, Vector3, } from 'three'; -import { degToRad } from 'three/src/math/MathUtils'; -import * as Duel from '../../../../stores/duel'; -import * as TankopediaEphemeral from '../../../../stores/tankopediaEphemeral'; +import { degToRad } from 'three/src/math/MathUtils.js'; +import { hasEquipment } from '../../../../core/blitzkit/hasEquipment'; +import { jsxTree } from '../../../../core/blitzkit/jsxTree'; +import { discardClippingPlane } from '../../../../core/three/discardClippingPlane'; +import { Duel } from '../../../../stores/duel'; +import { + type Shot, + type ShotLayerBase, + type ShotLayerNonExternal, + TankopediaEphemeral, +} from '../../../../stores/tankopediaEphemeral'; import { ArmorType } from '../SpacedArmorScene'; import { SpacedArmorSubExternal } from './components/SpacedArmorSubExternal'; import { SpacedArmorSubSpaced } from './components/SpacedArmorSubSpaced'; @@ -83,7 +91,7 @@ export function SpacedArmorSceneComponent({ const { antagonist, protagonist } = duelStore.getState(); const shell = antagonist.shell; const cameraNormal = camera.position.clone().sub(point).normalize(); - const shot: TankopediaEphemeral.Shot = { + const shot: Shot = { splashRadius: shell.explosionRadius, damage: -1, containsGaps: shell.type === ShellType.HEAT, @@ -157,9 +165,7 @@ export function SpacedArmorSceneComponent({ ); if (shell.type === ShellType.HEAT && index > 0) { - const lastLayer = shot.in.layers.at( - -1, - ) as TankopediaEphemeral.ShotLayerBase; + const lastLayer = shot.in.layers.at(-1) as ShotLayerBase; const distance = lastLayer.point.distanceTo(intersection.point); remainingPenetration -= 0.5 * remainingPenetration * distance; const blocked = remainingPenetration <= 0; @@ -255,11 +261,9 @@ export function SpacedArmorSceneComponent({ } const lastLayer = shot.in.layers.at(-1) as - | TankopediaEphemeral.ShotLayerNonExternal - | undefined; - const firstLayer = shot.in.layers[0] as - | TankopediaEphemeral.ShotLayerBase + | ShotLayerNonExternal | undefined; + const firstLayer = shot.in.layers[0] as ShotLayerBase | undefined; if (!lastLayer || !firstLayer) { return null; diff --git a/packages/website/src/components/Armor/components/StaticArmor.tsx b/packages/website/src/components/Armor/components/StaticArmor.tsx index 007c3d39c..5055cad74 100644 --- a/packages/website/src/components/Armor/components/StaticArmor.tsx +++ b/packages/website/src/components/Armor/components/StaticArmor.tsx @@ -12,6 +12,7 @@ import { useArmor } from '../../../hooks/useArmor'; import { useModel } from '../../../hooks/useModel'; import { useTankModelDefinition } from '../../../hooks/useTankModelDefinition'; import { useTankTransform } from '../../../hooks/useTankTransform'; +import { Duel } from '../../../stores/duel'; import { TankopediaEphemeral } from '../../../stores/tankopediaEphemeral'; import { TankopediaPersistent } from '../../../stores/tankopediaPersistent'; import { ModelTankWrapper } from './ModelTankWrapper'; diff --git a/packages/website/src/components/Armor/components/StaticArmorSceneComponent.tsx b/packages/website/src/components/Armor/components/StaticArmorSceneComponent.tsx index 6466ee9cf..53f6a4ad5 100644 --- a/packages/website/src/components/Armor/components/StaticArmorSceneComponent.tsx +++ b/packages/website/src/components/Armor/components/StaticArmorSceneComponent.tsx @@ -1,5 +1,5 @@ import { I_HAT, J_HAT } from '@blitzkit/core'; -import { MeshProps, useThree } from '@react-three/fiber'; +import { type MeshProps, useThree } from '@react-three/fiber'; import { clamp } from 'lodash-es'; import { useEffect, useMemo } from 'react'; import { @@ -15,20 +15,20 @@ import { Quaternion, Vector3, } from 'three'; -import { unrotateDavaVector } from '../../../../../website-legacy/src/core/blitz/unrotateDavaVector'; -import { jsxTree } from '../../../../../website-legacy/src/core/blitzkit/jsxTree'; +import { unrotateDavaVector } from '../../../core/blitz/unrotateDavaVector'; +import { jsxTree } from '../../../core/blitzkit/jsxTree'; import { - ModelTransformEventData, + type ModelTransformEventData, modelTransformEvent, -} from '../../../../../website-legacy/src/core/blitzkit/modelTransform'; -import { discardClippingPlane } from '../../../../../website-legacy/src/core/three/discardClippingPlane'; -import * as TankopediaEphemeral from '../../../../../website-legacy/src/stores/tankopediaEphemeral'; +} from '../../../core/blitzkit/modelTransform'; +import { discardClippingPlane } from '../../../core/three/discardClippingPlane'; +import { TankopediaEphemeral } from '../../../stores/tankopediaEphemeral'; import { ArmorType } from './SpacedArmorScene'; -import { +import type { ArmorUserData, ExternalModuleVariant, } from './SpacedArmorSceneComponent'; -import { ThicknessRange } from './StaticArmor'; +import type { ThicknessRange } from './StaticArmor'; type StaticArmorSceneComponentProps = { name: string; diff --git a/packages/website/src/components/ModuleButtons/GenericTankComponentButton.tsx b/packages/website/src/components/ModuleButtons/GenericTankComponentButton.tsx index 9637e88f4..2ca36cd35 100644 --- a/packages/website/src/components/ModuleButtons/GenericTankComponentButton.tsx +++ b/packages/website/src/components/ModuleButtons/GenericTankComponentButton.tsx @@ -1,7 +1,7 @@ import type { HTMLAttributes } from 'react'; import { TankComponentButton, - TankComponentButtonProps, + type TankComponentButtonProps, } from './TankComponentButton'; interface GenericTankComponentButtonProps extends TankComponentButtonProps { diff --git a/packages/website/src/components/ModuleButtons/ModuleButton.tsx b/packages/website/src/components/ModuleButtons/ModuleButton.tsx index c6de2bfff..663293425 100644 --- a/packages/website/src/components/ModuleButtons/ModuleButton.tsx +++ b/packages/website/src/components/ModuleButtons/ModuleButton.tsx @@ -1,6 +1,6 @@ import { asset } from '@blitzkit/core'; import { GenericTankComponentButton } from './GenericTankComponentButton'; -import { TankComponentButtonProps } from './TankComponentButton'; +import type { TankComponentButtonProps } from './TankComponentButton'; interface ModuleProps extends TankComponentButtonProps { module: string; diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/DynamicArmorSwitcher.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/DynamicArmorSwitcher.tsx index b1fe8426d..996a96687 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/DynamicArmorSwitcher.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/DynamicArmorSwitcher.tsx @@ -2,6 +2,7 @@ import { asset } from '@blitzkit/core'; import { IconButton } from '@radix-ui/themes'; import { invalidate } from '@react-three/fiber'; import { useArmor } from '../../../../../../hooks/useArmor'; +import { Duel } from '../../../../../../stores/duel'; import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral'; export function DynamicArmorSwitcher() { diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/QuickInputs/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/QuickInputs/index.tsx index f981bbcd0..e7137a321 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/QuickInputs/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/QuickInputs/index.tsx @@ -1,12 +1,15 @@ import { HeightIcon, WidthIcon } from '@radix-ui/react-icons'; import { Flex, TextField } from '@radix-ui/themes'; import { useEffect, useRef } from 'react'; -import { degToRad, radToDeg } from 'three/src/math/MathUtils'; -import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits'; -import { modelTransformEvent, ModelTransformEventData } from '../../../../../../core/blitzkit/modelTransform'; -import { useEquipment } from '../../../../../../hooks/useEquipment'; -import { useTankModelDefinition } from '../../../../../../hooks/useTankModelDefinition'; -import * as Duel from '../../../../../../stores/duel'; +import { degToRad, radToDeg } from 'three/src/math/MathUtils.js'; +import { applyPitchYawLimits } from '../../../../../../../core/blitz/applyPitchYawLimits'; +import { + type ModelTransformEventData, + modelTransformEvent, +} from '../../../../../../../core/blitzkit/modelTransform'; +import { useEquipment } from '../../../../../../../hooks/useEquipment'; +import { useTankModelDefinition } from '../../../../../../../hooks/useTankModelDefinition'; +import { Duel } from '../../../../../../../stores/duel'; import * as styles from './index.css'; export function QuickInputs() { @@ -22,13 +25,19 @@ export function QuickInputs() { const hasImprovedVerticalStabilizer = useEquipment(122); useEffect(() => { - yawInput.current!.value = radToDeg(protagonist.yaw).toFixed(1); + if (!yawInput.current) return; + + yawInput.current.value = radToDeg(protagonist.yaw).toFixed(1); }, [protagonist.yaw]); + useEffect(() => { - pitchInput.current!.value = ( + if (!pitchInput.current) return; + + pitchInput.current.value = ( -radToDeg(protagonist.pitch) + initialGunPitch ).toFixed(1); }, [protagonist.pitch]); + useEffect(() => { function handleTransformEvent({ pitch, yaw }: ModelTransformEventData) { if (!pitchInput.current || !yawInput.current) return; @@ -66,10 +75,8 @@ export function QuickInputs() { { const value = Number(yawInput.current!.value); if (isNaN(value)) { @@ -98,23 +105,17 @@ export function QuickInputs() { onFocus={() => yawInput.current?.focus()} ref={yawInput} > - + - ° + { const value = Number(pitchInput.current!.value); if (isNaN(value)) { @@ -154,13 +155,7 @@ export function QuickInputs() { > - - ° - + ); diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Thicknesses.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/Thicknesses.tsx similarity index 83% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Thicknesses.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/Options/components/Thicknesses.tsx index 58d170de4..53bc48db6 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Thicknesses.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/Thicknesses.tsx @@ -1,11 +1,11 @@ import { EyeClosedIcon, EyeOpenIcon, ReloadIcon } from '@radix-ui/react-icons'; import { Box, Button, Checkbox, Flex, Text } from '@radix-ui/themes'; -import { ThicknessRange } from '../../../../../components/Armor/components/StaticArmor'; -import { useArmor } from '../../../../../hooks/useArmor'; -import * as Duel from '../../../../../stores/duel'; -import * as TankopediaEphemeral from '../../../../../stores/tankopediaEphemeral'; -import * as TankopediaPersistent from '../../../../../stores/tankopediaPersistent'; -import { DynamicArmorSwitcher } from './Model/components/Options/components/DynamicArmorSwitcher'; +import { useArmor } from '../../../../../../hooks/useArmor'; +import { Duel } from '../../../../../../stores/duel'; +import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral'; +import { TankopediaPersistent } from '../../../../../../stores/tankopediaPersistent'; +import type { ThicknessRange } from '../../../../../Armor/components/StaticArmor'; +import { DynamicArmorSwitcher } from './DynamicArmorSwitcher'; interface ThicknessesProps { thicknessRange: ThicknessRange; @@ -13,13 +13,13 @@ interface ThicknessesProps { export function Thicknesses({ thicknessRange }: ThicknessesProps) { const showExternalModules = TankopediaPersistent.use( - (state) => state.model.visual.showExternalModules, + (state) => state.showExternalModules, ); const showSpacedArmor = TankopediaPersistent.use( - (state) => state.model.visual.showSpacedArmor, + (state) => state.showSpacedArmor, ); const showPrimaryArmor = TankopediaPersistent.use( - (state) => state.model.visual.showPrimaryArmor, + (state) => state.showPrimaryArmor, ); const mutateDuel = Duel.useMutation(); const mutateTankopediaPersistent = TankopediaPersistent.useMutation(); @@ -46,8 +46,7 @@ export function Thicknesses({ thicknessRange }: ThicknessesProps) { style={{ opacity: showPrimaryArmor ? 1 : 0.5, cursor: 'pointer' }} onClick={() => { mutateTankopediaPersistent((draft) => { - draft.model.visual.showPrimaryArmor = - !draft.model.visual.showPrimaryArmor; + draft.showPrimaryArmor = !draft.showPrimaryArmor; }); mutateTankopediaEphemeral((draft) => { draft.highlightArmor = undefined; @@ -83,8 +82,7 @@ export function Thicknesses({ thicknessRange }: ThicknessesProps) { style={{ opacity: showSpacedArmor ? 1 : 0.5, cursor: 'pointer' }} onClick={() => { mutateTankopediaPersistent((draft) => { - draft.model.visual.showSpacedArmor = - !draft.model.visual.showSpacedArmor; + draft.showSpacedArmor = !draft.showSpacedArmor; }); mutateTankopediaEphemeral((draft) => { draft.highlightArmor = undefined; @@ -119,8 +117,7 @@ export function Thicknesses({ thicknessRange }: ThicknessesProps) { style={{ opacity: showExternalModules ? 1 : 0.5, cursor: 'pointer' }} onClick={() => { mutateTankopediaPersistent((draft) => { - draft.model.visual.showExternalModules = - !draft.model.visual.showExternalModules; + draft.showExternalModules = !draft.showExternalModules; }); mutateTankopediaEphemeral((draft) => { draft.highlightArmor = undefined; diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx index 4a05c40f2..f116c99de 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx @@ -28,22 +28,24 @@ import { Tooltip, } from '@radix-ui/themes'; import { invalidate } from '@react-three/fiber'; -import { type RefObject, useState } from 'react'; +import { useState, type RefObject } from 'react'; import { ENVIRONMENTS } from '../../../../../constants/lightingEnvironments'; import { Pose, poseEvent } from '../../../../../core/blitzkit/pose'; import { useEquipment } from '../../../../../hooks/useEquipment'; import { useFullScreen } from '../../../../../hooks/useFullScreen'; import { useFullscreenAvailability } from '../../../../../hooks/useFullscreenAvailability'; -import { useStoreBoolean } from '../../../../../hooks/useStoreBoolean'; -import { useStoreKey } from '../../../../../hooks/useStoreKey'; -import { $app } from '../../../../../stores/app'; -import { $tankopediaPersistent } from '../../../../../stores/tankopediaPersistent'; +import { App } from '../../../../../stores/app'; +import { Duel } from '../../../../../stores/duel'; +import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral'; +import { TankopediaPersistent } from '../../../../../stores/tankopediaPersistent'; import { TankopediaDisplay } from '../../../../../stores/tankopediaPersistent/constants'; import type { ThicknessRange } from '../../../../Armor/components/StaticArmor'; import { ModuleButton } from '../../../../ModuleButtons/ModuleButton'; import { SmallTankIcon } from '../../../../SmallTankIcon'; import { TankSearch } from '../../../../TankSearch'; import { DynamicArmorSwitcher } from './components/DynamicArmorSwitcher'; +import { QuickInputs } from './components/QuickInputs'; +import { Thicknesses } from './components/Thicknesses'; interface OptionsProps { thicknessRange: ThicknessRange; @@ -51,23 +53,20 @@ interface OptionsProps { } export function Options({ thicknessRange, canvas }: OptionsProps) { - // const { display } = useStore($tankopediaPersistent, { keys: ['display'] }); - const display = useStoreKey($tankopediaPersistent, 'display'); + const display = TankopediaPersistent.use((state) => state.display); const isFullScreen = useFullScreen(); - const showGrid = useStoreBoolean($tankopediaPersistent, 'showGrid'); - const showEnvironment = useStoreBoolean( - $tankopediaPersistent, - 'showEnvironment', + const showGrid = TankopediaPersistent.use((state) => state.showGrid); + const showEnvironment = TankopediaPersistent.use( + (state) => state.showEnvironment, ); - const greenPenetration = useStoreBoolean( - $tankopediaPersistent, - 'greenPenetration', + const greenPenetration = TankopediaPersistent.use( + (state) => state.greenPenetration, ); - const wireframe = useStoreBoolean($tankopediaPersistent, 'wireframe'); - const opaque = useStoreBoolean($tankopediaPersistent, 'opaque'); + const wireframe = TankopediaPersistent.use((state) => state.wireframe); + const opaque = TankopediaPersistent.use((state) => state.opaque); const fullScreenAvailable = useFullscreenAvailability(); - const environment = useStoreKey($tankopediaPersistent, 'environment'); - const developerMode = useStoreBoolean($app, 'developerMode'); + const environment = TankopediaPersistent.use((state) => state.environment); + const developerMode = App.use((state) => state.developerMode); const protagonistTank = Duel.use((state) => state.protagonist.tank); const antagonistGun = Duel.use((state) => state.antagonist.gun); const antagonistShell = Duel.use((state) => state.antagonist.shell); @@ -78,6 +77,8 @@ export function Options({ thicknessRange, canvas }: OptionsProps) { const mutateDuel = Duel.useMutation(); const hasEnhancedArmor = useEquipment(110); const antagonistUniqueGuns = uniqueGuns(antagonistTank.turrets); + const mutateTankopediaPersistent = TankopediaPersistent.useMutation(); + const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); return ( <> @@ -395,7 +396,7 @@ export function Options({ thicknessRange, canvas }: OptionsProps) { checked={greenPenetration} onCheckedChange={(checked) => { mutateTankopediaPersistent((draft) => { - draft.model.visual.greenPenetration = checked; + draft.greenPenetration = checked; }); }} > @@ -406,7 +407,7 @@ export function Options({ thicknessRange, canvas }: OptionsProps) { checked={opaque} onCheckedChange={(checked) => { mutateTankopediaPersistent((draft) => { - draft.model.visual.opaque = checked; + draft.opaque = checked; }); }} > @@ -418,7 +419,7 @@ export function Options({ thicknessRange, canvas }: OptionsProps) { checked={wireframe} onCheckedChange={(checked) => { mutateTankopediaPersistent((draft) => { - draft.model.visual.wireframe = checked; + draft.wireframe = checked; }); }} > @@ -434,7 +435,7 @@ export function Options({ thicknessRange, canvas }: OptionsProps) { checked={showGrid} onCheckedChange={(checked) => { mutateTankopediaPersistent((draft) => { - draft.model.visual.showGrid = checked; + draft.showGrid = checked; }); }} > @@ -445,7 +446,7 @@ export function Options({ thicknessRange, canvas }: OptionsProps) { checked={showEnvironment} onCheckedChange={(checked) => { mutateTankopediaPersistent((draft) => { - draft.model.visual.showEnvironment = checked; + draft.showEnvironment = checked; }); }} > @@ -463,7 +464,7 @@ export function Options({ thicknessRange, canvas }: OptionsProps) { value={environment} onClick={() => { mutateTankopediaPersistent((draft) => { - draft.model.visual.environment = environment; + draft.environment = environment; }); }} > diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/AutoClear.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/AutoClear.tsx similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/AutoClear.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/AutoClear.tsx diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Control.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx similarity index 93% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Control.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx index 1e28018a1..5dea05f7e 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Control.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx @@ -4,12 +4,12 @@ import { useThree } from '@react-three/fiber'; import { useEffect, useRef, useState } from 'react'; import { Vector3 } from 'three'; import { OrbitControls as OrbitControlsClass } from 'three-stdlib'; -import { applyPitchYawLimits } from '../../../../../core/blitz/applyPitchYawLimits'; -import { hasEquipment } from '../../../../../core/blitzkit/hasEquipment'; -import { Pose, poseEvent } from '../../../../../core/blitzkit/pose'; -import { useAwait } from '../../../../../hooks/useAwait'; -import * as Duel from '../../../../../stores/duel'; -import * as TankopediaEphemeral from '../../../../../stores/tankopediaEphemeral'; +import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits'; +import { hasEquipment } from '../../../../../../core/blitzkit/hasEquipment'; +import { Pose, poseEvent } from '../../../../../../core/blitzkit/pose'; +import { useAwait } from '../../../../../../hooks/useAwait'; +import { Duel } from '../../../../../../stores/duel'; +import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral'; const initialPosition = [0, 4, -18] as const; const poseDistances: Record = { diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Lighting.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Lighting.tsx similarity index 66% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Lighting.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Lighting.tsx index 077a7e628..eb0024360 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Lighting.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Lighting.tsx @@ -1,17 +1,15 @@ import { Environment } from '@react-three/drei'; -import { useModel } from '../../../../../hooks/useModel'; -import * as Duel from '../../../../../stores/duel'; -import * as TankopediaPersistent from '../../../../../stores/tankopediaPersistent'; +import { useModel } from '../../../../../../hooks/useModel'; +import { Duel } from '../../../../../../stores/duel'; +import { TankopediaPersistent } from '../../../../../../stores/tankopediaPersistent'; export function Lighting() { const protagonist = Duel.use((state) => state.protagonist); const { hasPbr } = useModel(protagonist.tank.id); const showEnvironment = TankopediaPersistent.use( - (state) => state.model.visual.showEnvironment, - ); - const environment = TankopediaPersistent.use( - (state) => state.model.visual.environment, + (state) => state.showEnvironment, ); + const environment = TankopediaPersistent.use((state) => state.environment); return ( <> diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/ModelLoader.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/ModelLoader.tsx similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/ModelLoader.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/ModelLoader.tsx diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/SceneProps.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/SceneProps.tsx similarity index 81% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/SceneProps.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/SceneProps.tsx index 9a6a3ed32..8a38c24d1 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/SceneProps.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/SceneProps.tsx @@ -2,12 +2,11 @@ import { useFrame, useLoader } from '@react-three/fiber'; import { clamp } from 'lodash-es'; import { useRef } from 'react'; import { MeshStandardMaterial, TextureLoader } from 'three'; -import * as TankopediaPersistent from '../../../../../stores/tankopediaPersistent'; +import { TankopediaPersistent } from '../../../../../../stores/tankopediaPersistent'; export function SceneProps() { const show = TankopediaPersistent.use( - (state) => - state.model.visual.showGrid && !state.model.visual.showEnvironment, + (state) => state.showGrid && !state.showEnvironment, ); const texture = useLoader(TextureLoader, 'https://i.imgur.com/C28Z8nU.png'); const material = useRef(null); diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TankModel.tsx similarity index 91% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TankModel.tsx index e2a108bd7..72b334383 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TankModel.tsx @@ -1,19 +1,19 @@ import { normalizeAngleRad } from '@blitzkit/core'; -import { invalidate, ThreeEvent, useThree } from '@react-three/fiber'; +import { invalidate, useThree, type ThreeEvent } from '@react-three/fiber'; import { memo, useRef } from 'react'; import { Group, Mesh, MeshStandardMaterial, Vector2 } from 'three'; -import { ModelTankWrapper } from '../../../../../../../components/Armor/components/ModelTankWrapper'; -import { applyPitchYawLimits } from '../../../../../../../core/blitz/applyPitchYawLimits'; -import { hasEquipment } from '../../../../../../../core/blitzkit/hasEquipment'; -import { jsxTree } from '../../../../../../../core/blitzkit/jsxTree'; -import { modelTransformEvent } from '../../../../../../../core/blitzkit/modelTransform'; -import { useModel } from '../../../../../../../hooks/useModel'; -import { useTankModelDefinition } from '../../../../../../../hooks/useTankModelDefinition'; -import { useTankTransform } from '../../../../../../../hooks/useTankTransform'; -import * as Duel from '../../../../../../../stores/duel'; -import * as TankopediaEphemeral from '../../../../../../../stores/tankopediaEphemeral'; -import * as TankopediaPersistent from '../../../../../../../stores/tankopediaPersistent'; -import { TankopediaDisplay } from '../../../../../../../stores/tankopediaPersistent/constants'; +import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits'; +import { hasEquipment } from '../../../../../../core/blitzkit/hasEquipment'; +import { jsxTree } from '../../../../../../core/blitzkit/jsxTree'; +import { modelTransformEvent } from '../../../../../../core/blitzkit/modelTransform'; +import { useModel } from '../../../../../../hooks/useModel'; +import { useTankModelDefinition } from '../../../../../../hooks/useTankModelDefinition'; +import { useTankTransform } from '../../../../../../hooks/useTankTransform'; +import { Duel } from '../../../../../../stores/duel'; +import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral'; +import { TankopediaPersistent } from '../../../../../../stores/tankopediaPersistent'; +import { TankopediaDisplay } from '../../../../../../stores/tankopediaPersistent/constants'; +import { ModelTankWrapper } from '../../../../../Armor/components/ModelTankWrapper'; export const TankModel = memo(() => { const mutateDuel = Duel.useMutation(); diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/index.tsx similarity index 73% rename from packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/index.tsx index e53c0ce45..9d8253d4b 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/index.tsx @@ -6,29 +6,29 @@ import { useImperativeHandle, useRef, } from 'react'; -import { Armor } from '../../../../../../components/Armor'; -import { ArmorPlateDisplay } from '../../../../../../components/Armor/components/ArmorPlateDisplay'; -import { ShotDisplay } from '../../../../../../components/Armor/components/ShotDisplay'; +import { applyPitchYawLimits } from '../../../../../core/blitz/applyPitchYawLimits'; +import { modelTransformEvent } from '../../../../../core/blitzkit/modelTransform'; +import { Pose, poseEvent } from '../../../../../core/blitzkit/pose'; +import { useEquipment } from '../../../../../hooks/useEquipment'; +import { useOnScreen } from '../../../../../hooks/useOnScreen'; +import { useTankModelDefinition } from '../../../../../hooks/useTankModelDefinition'; +import { Duel } from '../../../../../stores/duel'; +import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral'; +import { TankopediaPersistent } from '../../../../../stores/tankopediaPersistent'; +import { TankopediaDisplay } from '../../../../../stores/tankopediaPersistent/constants'; +import { Armor } from '../../../../Armor'; +import { ArmorPlateDisplay } from '../../../../Armor/components/ArmorPlateDisplay'; +import { ShotDisplay } from '../../../../Armor/components/ShotDisplay'; import { StaticArmor, - ThicknessRange, -} from '../../../../../../components/Armor/components/StaticArmor'; -import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits'; -import { modelTransformEvent } from '../../../../../../core/blitzkit/modelTransform'; -import { Pose, poseEvent } from '../../../../../../core/blitzkit/pose'; -import { useEquipment } from '../../../../../../hooks/useEquipment'; -import { useOnScreen } from '../../../../../../hooks/useOnScreen'; -import { useTankModelDefinition } from '../../../../../../hooks/useTankModelDefinition'; -import * as Duel from '../../../../../../stores/duel'; -import * as TankopediaEphemeral from '../../../../../../stores/tankopediaEphemeral'; -import * as TankopediaPersistent from '../../../../../../stores/tankopediaPersistent'; -import { TankopediaDisplay } from '../../../../../../stores/tankopediaPersistent/constants'; -import { Controls } from '../../../../../../website-legacy/src/app/tools/tankopedia/[id]/components/Control'; -import { Lighting } from '../../../../../../website-legacy/src/app/tools/tankopedia/[id]/components/Lighting'; -import { SceneProps } from '../../../../../../website-legacy/src/app/tools/tankopedia/[id]/components/SceneProps'; -import { AutoClear } from '../../../../../../website-legacy/src/app/tools/tankopedia/[id]/components/Model/AutoClear'; -import { ModelLoader } from '../../../../../../website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/ModelLoader'; -import { TankModel } from '../../../../../../website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/TankModel'; + type ThicknessRange, +} from '../../../../Armor/components/StaticArmor'; +import { AutoClear } from './components/AutoClear'; +import { Controls } from './components/Control'; +import { Lighting } from './components/Lighting'; +import { ModelLoader } from './components/ModelLoader'; +import { SceneProps } from './components/SceneProps'; +import { TankModel } from './components/TankModel'; interface TankSandboxProps { thicknessRange: ThicknessRange; @@ -178,7 +178,6 @@ export const TankSandbox = forwardRef( {display !== TankopediaDisplay.StaticArmor && } - diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandboxLoader.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandboxLoader.tsx index 87849429f..6d11c0043 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandboxLoader.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandboxLoader.tsx @@ -1,5 +1,5 @@ import { tankIcon } from '@blitzkit/core'; -import { Flex, FlexProps, Progress } from '@radix-ui/themes'; +import { Flex, type FlexProps, Progress } from '@radix-ui/themes'; import { useProgress } from '@react-three/drei'; type TankSandboxLoaderProps = Omit & { diff --git a/packages/website/src/components/Tankopedia/HeroSection/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/index.tsx index 1f6855e99..c7df95417 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/index.tsx @@ -4,6 +4,7 @@ import { Suspense, useEffect, useMemo, useRef, useState } from 'react'; import { NAVBAR_HEIGHT } from '../../../constants/navbar'; import { Var } from '../../../core/radix/var'; import { useFullScreen } from '../../../hooks/useFullScreen'; +import { Duel } from '../../../stores/duel'; import type { ThicknessRange } from '../../Armor/components/StaticArmor'; import { classIcons } from '../../ClassIcon'; import { Options } from './components/Options'; @@ -12,14 +13,10 @@ import { TankSandboxLoader } from './components/TankSandboxLoader'; const awaitedTankDefinitions = await tankDefinitions; -interface HeroSectionProps { - id: number; -} - -export function HeroSection({ id }: HeroSectionProps) { +export function HeroSection() { const canvas = useRef(null); const isFullScreen = useFullScreen(); - const protagonist = awaitedTankDefinitions[id]; + const protagonist = Duel.use((state) => state.protagonist.tank); const Icon = classIcons[protagonist.class]; const [dummyLoader, setDummyLoader] = useState(true); const treeColor = diff --git a/packages/website/src/core/blitz/applyPitchYawLimits.ts b/packages/website/src/core/blitz/applyPitchYawLimits.ts index 838e988e0..0bfc6c3c2 100644 --- a/packages/website/src/core/blitz/applyPitchYawLimits.ts +++ b/packages/website/src/core/blitz/applyPitchYawLimits.ts @@ -1,6 +1,10 @@ -import { normalizeAngleRad, PitchLimits, YawLimits } from '@blitzkit/core'; +import { + normalizeAngleRad, + type PitchLimits, + type YawLimits, +} from '@blitzkit/core'; import { clamp } from 'lodash-es'; -import { degToRad } from 'three/src/math/MathUtils'; +import { degToRad } from 'three/src/math/MathUtils.js'; export function applyPitchYawLimits( pitch: number, // rad diff --git a/packages/website/src/core/blitzkit/hasEquipment.ts b/packages/website/src/core/blitzkit/hasEquipment.ts index 0cbb492ff..5d96c3b77 100644 --- a/packages/website/src/core/blitzkit/hasEquipment.ts +++ b/packages/website/src/core/blitzkit/hasEquipment.ts @@ -1,5 +1,5 @@ import { equipmentDefinitions } from '@blitzkit/core'; -import { EquipmentMatrix } from '../../stores/duel'; +import type { EquipmentMatrix } from '../../stores/duel'; export async function hasEquipment( id: number, diff --git a/packages/website/src/core/blitzkit/resolveThickness.ts b/packages/website/src/core/blitzkit/resolveThickness.ts index ec1d3a675..0487ec622 100644 --- a/packages/website/src/core/blitzkit/resolveThickness.ts +++ b/packages/website/src/core/blitzkit/resolveThickness.ts @@ -1,4 +1,4 @@ -import { ModelArmor } from '@blitzkit/core'; +import type { ModelArmor } from '@blitzkit/core'; export function resolveArmor(armor: ModelArmor, index: number) { const spaced = armor.spaced?.includes(index) ?? false; diff --git a/packages/website/src/core/blitzkit/tankToDuelMember.ts b/packages/website/src/core/blitzkit/tankToDuelMember.ts index 9f2022e4b..7b8043a09 100644 --- a/packages/website/src/core/blitzkit/tankToDuelMember.ts +++ b/packages/website/src/core/blitzkit/tankToDuelMember.ts @@ -1,9 +1,9 @@ import { availableProvisions, - ProvisionDefinitions, - TankDefinition, + type ProvisionDefinitions, + type TankDefinition, } from '@blitzkit/core'; -import { DuelMember } from '../../stores/duel'; +import type { DuelMember } from '../../stores/duel'; import { genericDefaultEquipmentMatrix } from '../../stores/duel/constants'; const PROVISION_PREFERENCES = [ diff --git a/packages/website/src/hooks/useEquipment.ts b/packages/website/src/hooks/useEquipment.ts index f27a4748b..4e4ee9f2d 100644 --- a/packages/website/src/hooks/useEquipment.ts +++ b/packages/website/src/hooks/useEquipment.ts @@ -1,6 +1,6 @@ import { equipmentDefinitions } from '@blitzkit/core'; import { useMemo } from 'react'; -import * as Duel from '../stores/duel'; +import { Duel } from '../stores/duel'; const awaitedEquipmentDefinitions = await equipmentDefinitions; diff --git a/packages/website/src/hooks/useTankModelDefinition.ts b/packages/website/src/hooks/useTankModelDefinition.ts index 144858de4..b61b2fa58 100644 --- a/packages/website/src/hooks/useTankModelDefinition.ts +++ b/packages/website/src/hooks/useTankModelDefinition.ts @@ -1,4 +1,4 @@ -import * as TankopediaEphemeral from '../stores/tankopediaEphemeral'; +import { TankopediaEphemeral } from '../stores/tankopediaEphemeral'; export function useTankModelDefinition() { return TankopediaEphemeral.use((state) => state.model); diff --git a/packages/website/src/hooks/useTankTransform.ts b/packages/website/src/hooks/useTankTransform.ts index 1469dcb61..2f718eecc 100644 --- a/packages/website/src/hooks/useTankTransform.ts +++ b/packages/website/src/hooks/useTankTransform.ts @@ -1,13 +1,13 @@ import { I_HAT, J_HAT, K_HAT } from '@blitzkit/core'; import { type RefObject, useEffect } from 'react'; import { Euler, Group, Vector3 } from 'three'; -import { degToRad } from 'three/src/math/MathUtils'; +import { degToRad } from 'three/src/math/MathUtils.js'; import { correctZYTuple } from '../core/blitz/correctZYTuple'; import { - ModelTransformEventData, + type ModelTransformEventData, modelTransformEvent, } from '../core/blitzkit/modelTransform'; -import { DuelMember } from '../stores/duel'; +import type { DuelMember } from '../stores/duel'; import { useTankModelDefinition } from './useTankModelDefinition'; export function useTankTransform( diff --git a/packages/website/src/pages/tools/tankopedia/[id]/index.astro b/packages/website/src/pages/tools/tankopedia/[id]/index.astro index 02104e96b..b09d49ccd 100644 --- a/packages/website/src/pages/tools/tankopedia/[id]/index.astro +++ b/packages/website/src/pages/tools/tankopedia/[id]/index.astro @@ -1,6 +1,7 @@ --- import { tankDefinitions } from '@blitzkit/core'; import type { GetStaticPaths } from 'astro'; +import ToolLayout from '../../../../layouts/ToolLayout.astro'; import { Page } from './index'; export const getStaticPaths = (async () => { @@ -14,4 +15,6 @@ export const getStaticPaths = (async () => { const { id } = Astro.params; --- - + + + diff --git a/packages/website/src/pages/tools/tankopedia/[id]/index.tsx b/packages/website/src/pages/tools/tankopedia/[id]/index.tsx index 7ff7bac9a..2c453f3dd 100644 --- a/packages/website/src/pages/tools/tankopedia/[id]/index.tsx +++ b/packages/website/src/pages/tools/tankopedia/[id]/index.tsx @@ -1,15 +1,37 @@ +import { + modelDefinitions, + provisionDefinitions, + tankDefinitions, +} from '@blitzkit/core'; import { PageWrapper } from '../../../../components/PageWrapper'; import { HeroSection } from '../../../../components/Tankopedia/HeroSection'; +import { App } from '../../../../stores/app'; +import { Duel } from '../../../../stores/duel'; +import { TankopediaEphemeral } from '../../../../stores/tankopediaEphemeral'; +import { TankopediaPersistent } from '../../../../stores/tankopediaPersistent'; interface PageProps { id: number; } +const awaitedTankDefinitions = await tankDefinitions; +const awaitedProvisionDefinitions = await provisionDefinitions; +const awaitedModelDefinitions = await modelDefinitions; + export function Page({ id }: PageProps) { + const tank = awaitedTankDefinitions[id]; + const model = awaitedModelDefinitions[id]; + return ( - - - {/* + + + + + + + {/* {!exempt && } @@ -20,6 +42,10 @@ export function Page({ id }: PageProps) { {!exempt && } */} - + + + + + ); } diff --git a/packages/website/src/stores/duel/constants.ts b/packages/website/src/stores/duel/constants.ts index 24cc39aea..40355db2e 100644 --- a/packages/website/src/stores/duel/constants.ts +++ b/packages/website/src/stores/duel/constants.ts @@ -1,4 +1,4 @@ -import { EquipmentMatrix } from '.'; +import type { EquipmentMatrix } from '.'; export const genericDefaultEquipmentMatrix: EquipmentMatrix = [ [-1, 1, -1], diff --git a/packages/website/src/stores/tankPerformancePersistent/index.ts b/packages/website/src/stores/tankPerformancePersistent/index.ts index 6efe22227..d0b061c3f 100644 --- a/packages/website/src/stores/tankPerformancePersistent/index.ts +++ b/packages/website/src/stores/tankPerformancePersistent/index.ts @@ -1,4 +1,4 @@ -import lodash from 'lodash-es'; +import * as lodash from 'lodash-es'; import { create } from 'zustand'; import { persist, subscribeWithSelector } from 'zustand/middleware'; import { createContextualStore } from '../../core/zustand/createContextualStore'; diff --git a/packages/website/src/stores/tankopediaEphemeral.ts b/packages/website/src/stores/tankopediaEphemeral.ts index d4ea624c0..baab208f1 100644 --- a/packages/website/src/stores/tankopediaEphemeral.ts +++ b/packages/website/src/stores/tankopediaEphemeral.ts @@ -1,8 +1,8 @@ import type { ModelDefinition } from '@blitzkit/core'; -import { Vector3 } from 'three'; +import type { Vector3 } from 'three'; import { create } from 'zustand'; import { subscribeWithSelector } from 'zustand/middleware'; -import { ArmorType } from '../components/Armor/components/SpacedArmorScene'; +import type { ArmorType } from '../components/Armor/components/SpacedArmorScene'; import type { ExternalModuleVariant } from '../components/Armor/components/SpacedArmorSceneComponent'; import type { XP_MULTIPLIERS } from '../components/Tankopedia/TechTreeSection'; import { createContextualStore } from '../core/zustand/createContextualStore'; @@ -66,19 +66,6 @@ export type ArmorPiercingLayer = gap: number; }; -export const TankopediaEphemeral = createContextualStore( - (model: ModelDefinition) => - create()( - subscribeWithSelector(() => ({ - editStatic: false, - skills: {}, - model, - controlsEnabled: true, - xpMultiplier: 1, - })), - ), -); - interface TankopediaEphemeral { shot?: Shot; skills: Record; @@ -101,3 +88,16 @@ interface TankopediaEphemeral { ); xpMultiplier: (typeof XP_MULTIPLIERS)[number]; } + +export const TankopediaEphemeral = createContextualStore( + (model: ModelDefinition) => + create()( + subscribeWithSelector(() => ({ + editStatic: false, + skills: {}, + model, + controlsEnabled: true, + xpMultiplier: 1, + })), + ), +); diff --git a/packages/website/src/stores/tankopediaPersistent/index.ts b/packages/website/src/stores/tankopediaPersistent/index.ts index 1b60b4ab7..032a135d7 100644 --- a/packages/website/src/stores/tankopediaPersistent/index.ts +++ b/packages/website/src/stores/tankopediaPersistent/index.ts @@ -1,6 +1,6 @@ import * as lodash from 'lodash-es'; import { create } from 'zustand'; -import { persist } from 'zustand/middleware'; +import { persist, subscribeWithSelector } from 'zustand/middleware'; import { ENVIRONMENTS } from '../../constants/lightingEnvironments'; import { createContextualStore } from '../../core/zustand/createContextualStore'; import { SORT_NAMES, TankopediaDisplay } from './constants'; @@ -31,13 +31,13 @@ export interface TankopediaPersistentStore { export const TankopediaPersistent = createContextualStore(() => create()( persist( - (set) => ({ + subscribeWithSelector(() => ({ wireframe: false, opaque: false, environment: ENVIRONMENTS[0], showGrid: true, - greenPenetration: true, - showEnvironment: true, + greenPenetration: false, + showEnvironment: false, showSpacedArmor: true, showExternalModules: true, showPrimaryArmor: true, @@ -46,7 +46,7 @@ export const TankopediaPersistent = createContextualStore(() => direction: 'ascending', }, display: TankopediaDisplay.Model, - }), + })), { name: 'tankopedia', merge: (a, b) => lodash.merge(b, a) }, ), ),