From cb03a86cce1aaee061effbc5ee5d74bbaffc3280 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Mar 2025 21:15:55 -0500 Subject: [PATCH] feat: proper assembly --- .vscode/settings.json | 1 + packages/core/src/protos/tank.proto | 2 + packages/core/src/protos/tank.ts | 56 +++++++-- .../Armor/components/StaticArmor.tsx | 18 ++- .../components/StaticArmorSceneComponent.tsx | 6 + .../src/core/blitzkit/tankToDuelMember.ts | 8 +- packages/website/src/core/three/arrayfy.ts | 5 + .../pages/[...locale]/tanks/[slug]/_index.tsx | 9 +- .../[...locale]/tanks/[slug]/index.astro | 7 +- packages/website/src/stores/duel/index.ts | 6 +- .../website/src/stores/tankopediaEphemeral.ts | 13 ++- src/BlitzKit.CLI/Functions/Mangler.cs | 4 +- src/BlitzKit.CLI/Protos/Tank.cs | 108 +++++++++++++++++- 13 files changed, 208 insertions(+), 35 deletions(-) create mode 100644 packages/website/src/core/three/arrayfy.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 76c939025..19956ba29 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,6 +12,7 @@ "APAC", "apcr", "applypatches", + "arrayfy", "artefacts", "astrojs", "atgm", diff --git a/packages/core/src/protos/tank.proto b/packages/core/src/protos/tank.proto index 63d8c82a2..4c1cbebce 100644 --- a/packages/core/src/protos/tank.proto +++ b/packages/core/src/protos/tank.proto @@ -13,7 +13,9 @@ message Tank { } message Turret { + required string id = 1; } message Gun { + required string id = 1; } diff --git a/packages/core/src/protos/tank.ts b/packages/core/src/protos/tank.ts index 7d56b621e..c7311acd8 100644 --- a/packages/core/src/protos/tank.ts +++ b/packages/core/src/protos/tank.ts @@ -29,9 +29,11 @@ export interface Tank_GunsEntry { } export interface Turret { + id: string; } export interface Gun { + id: string; } function createBaseTank(): Tank { @@ -353,11 +355,14 @@ export const Tank_GunsEntry: MessageFns = { }; function createBaseTurret(): Turret { - return {}; + return { id: "" }; } export const Turret: MessageFns = { - encode(_: Turret, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode(message: Turret, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.id !== "") { + writer.uint32(10).string(message.id); + } return writer; }, @@ -368,6 +373,14 @@ export const Turret: MessageFns = { while (reader.pos < end) { const tag = reader.uint32(); switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.id = reader.string(); + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -377,30 +390,37 @@ export const Turret: MessageFns = { return message; }, - fromJSON(_: any): Turret { - return {}; + fromJSON(object: any): Turret { + return { id: globalThis.String(assertSet("Turret.id", object.id)) }; }, - toJSON(_: Turret): unknown { + toJSON(message: Turret): unknown { const obj: any = {}; + if (message.id !== "") { + obj.id = message.id; + } return obj; }, create, I>>(base?: I): Turret { return Turret.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(_: I): Turret { + fromPartial, I>>(object: I): Turret { const message = createBaseTurret(); + message.id = object.id ?? ""; return message; }, }; function createBaseGun(): Gun { - return {}; + return { id: "" }; } export const Gun: MessageFns = { - encode(_: Gun, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode(message: Gun, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.id !== "") { + writer.uint32(10).string(message.id); + } return writer; }, @@ -411,6 +431,14 @@ export const Gun: MessageFns = { while (reader.pos < end) { const tag = reader.uint32(); switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.id = reader.string(); + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -420,20 +448,24 @@ export const Gun: MessageFns = { return message; }, - fromJSON(_: any): Gun { - return {}; + fromJSON(object: any): Gun { + return { id: globalThis.String(assertSet("Gun.id", object.id)) }; }, - toJSON(_: Gun): unknown { + toJSON(message: Gun): unknown { const obj: any = {}; + if (message.id !== "") { + obj.id = message.id; + } return obj; }, create, I>>(base?: I): Gun { return Gun.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(_: I): Gun { + fromPartial, I>>(object: I): Gun { const message = createBaseGun(); + message.id = object.id ?? ""; return message; }, }; diff --git a/packages/website/src/components/Armor/components/StaticArmor.tsx b/packages/website/src/components/Armor/components/StaticArmor.tsx index 983d2db6d..7a82ed179 100644 --- a/packages/website/src/components/Armor/components/StaticArmor.tsx +++ b/packages/website/src/components/Armor/components/StaticArmor.tsx @@ -1,4 +1,7 @@ import { memo } from 'react'; +import { arrayfy } from '../../../core/three/arrayfy'; +import { Duel } from '../../../stores/duel'; +import { TankopediaEphemeral } from '../../../stores/tankopediaEphemeral'; import { StaticArmorSceneComponent } from './StaticArmorSceneComponent'; export interface ThicknessRange { @@ -6,17 +9,24 @@ export interface ThicknessRange { } export const StaticArmor = memo(() => { + const tank = Duel.use((state) => state.protagonist); + const model = TankopediaEphemeral.use((state) => state.model); + const turret = Duel.use((state) => state.protagonist.turret); + const gun = Duel.use((state) => state.protagonist.gun); + const turretTranslation = arrayfy(model.modules[turret.id].translation); + const gunTranslation = arrayfy(model.modules[gun.id].translation); + return ( - - + + - - + + ); diff --git a/packages/website/src/components/Armor/components/StaticArmorSceneComponent.tsx b/packages/website/src/components/Armor/components/StaticArmorSceneComponent.tsx index 69c2857b3..d838b3797 100644 --- a/packages/website/src/components/Armor/components/StaticArmorSceneComponent.tsx +++ b/packages/website/src/components/Armor/components/StaticArmorSceneComponent.tsx @@ -44,6 +44,12 @@ export function StaticArmorSceneComponent({ const armorName = mesh.material.name; const armorPlate = groupArmor.armors[armorName]; + + if (armorPlate === undefined) { + console.warn(`Missing armor: ${armorName}`); + return null; + } + const x = armorPlate.thickness / thicknessRange; const xClamped = clamp(x, 0, 1); const material = new MeshStandardMaterial(); diff --git a/packages/website/src/core/blitzkit/tankToDuelMember.ts b/packages/website/src/core/blitzkit/tankToDuelMember.ts index bf11d9f4d..69e980252 100644 --- a/packages/website/src/core/blitzkit/tankToDuelMember.ts +++ b/packages/website/src/core/blitzkit/tankToDuelMember.ts @@ -5,8 +5,8 @@ export function tankToDuelMember( tank: Tank, // provisionDefinitions: ProvisionDefinitions, ) { - // const turret = tank.turrets.at(-1)!; - // const gun = turret.guns.at(-1)!; + const turret = Object.values(tank.turrets).at(-1)!; + const gun = Object.values(tank.guns).at(-1)!; return { // camouflage: true, @@ -15,12 +15,12 @@ export function tankToDuelMember( // cooldownBooster: 0, // provisions: createDefaultProvisions(tank, gun, provisionDefinitions), // engine: tank.engines.at(-1)!, - // gun, + gun, // shell: tank.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0], tank, // track: tank.tracks.at(-1)!, // yaw: 0, // pitch: 0, - // turret, + turret, } satisfies DuelMember; } diff --git a/packages/website/src/core/three/arrayfy.ts b/packages/website/src/core/three/arrayfy.ts new file mode 100644 index 000000000..fa42bae84 --- /dev/null +++ b/packages/website/src/core/three/arrayfy.ts @@ -0,0 +1,5 @@ +import type { Vector3 } from '@blitzkit/core'; + +export function arrayfy(vector: Vector3) { + return [vector.x, vector.y, vector.z] as const; +} diff --git a/packages/website/src/pages/[...locale]/tanks/[slug]/_index.tsx b/packages/website/src/pages/[...locale]/tanks/[slug]/_index.tsx index abaaf8dd2..9edee1970 100644 --- a/packages/website/src/pages/[...locale]/tanks/[slug]/_index.tsx +++ b/packages/website/src/pages/[...locale]/tanks/[slug]/_index.tsx @@ -1,4 +1,4 @@ -import { Tank, TankArmor } from '@blitzkit/core'; +import { Tank, TankArmor, TankModel } from '@blitzkit/core'; import { PageWrapper } from '../../../../components/PageWrapper'; import { HeroSection } from '../../../../components/Tankopedia/HeroSection'; import { @@ -15,12 +15,15 @@ type PageProps = MaybeSkeletonComponentProps & LocaleAcceptorProps & { tank: Tank; armor: TankArmor; + model: TankModel; }; -export function Page({ tank, armor, skeleton, locale }: PageProps) { +export function Page({ tank, armor, skeleton, locale, model }: PageProps) { return ( - + --> - - + + diff --git a/packages/website/src/stores/duel/index.ts b/packages/website/src/stores/duel/index.ts index 34f4ebf58..3e4e9f811 100644 --- a/packages/website/src/stores/duel/index.ts +++ b/packages/website/src/stores/duel/index.ts @@ -1,4 +1,4 @@ -import { Tank } from '@blitzkit/core'; +import { Gun, Tank, Turret } from '@blitzkit/core'; import { create } from 'zustand'; import { subscribeWithSelector } from 'zustand/middleware'; import { tankToDuelMember } from '../../core/blitzkit/tankToDuelMember'; @@ -19,8 +19,8 @@ export type EquipmentMatrix = [ export interface DuelMember { tank: Tank; // engine: EngineDefinition; - // turret: TurretDefinition; - // gun: GunDefinition; + turret: Turret; + gun: Gun; // shell: ShellDefinition; // track: TrackDefinition; // equipmentMatrix: EquipmentMatrix; diff --git a/packages/website/src/stores/tankopediaEphemeral.ts b/packages/website/src/stores/tankopediaEphemeral.ts index 671301f0e..cac8ee59d 100644 --- a/packages/website/src/stores/tankopediaEphemeral.ts +++ b/packages/website/src/stores/tankopediaEphemeral.ts @@ -2,6 +2,7 @@ import { createDefaultSkills, ShellDefinition, TankArmor, + TankModel, } from '@blitzkit/core'; import type { Vector3 } from 'three'; import { create } from 'zustand'; @@ -103,6 +104,7 @@ interface TankopediaEphemeral { relativeAgainst: TankopediaRelativeAgainst; controlsEnabled: boolean; armor: TankArmor; + model: TankModel; editStatic: boolean; highlightArmor?: { editingPlate: boolean; @@ -126,7 +128,15 @@ interface TankopediaEphemeral { const skillDefinitions = await awaitableSkillDefinitions; export const TankopediaEphemeral = createContextualStore( - ({ armor, thicknessRange }: { armor: TankArmor; thicknessRange: number }) => { + ({ + armor, + thicknessRange, + model, + }: { + armor: TankArmor; + thicknessRange: number; + model: TankModel; + }) => { return create()( subscribeWithSelector(() => ({ thicknessRange, @@ -135,6 +145,7 @@ export const TankopediaEphemeral = createContextualStore( editStatic: false, skills: createDefaultSkills(skillDefinitions), armor, + model, controlsEnabled: true, xpMultiplier: 1, display: TankopediaDisplay.StaticArmor, diff --git a/src/BlitzKit.CLI/Functions/Mangler.cs b/src/BlitzKit.CLI/Functions/Mangler.cs index b0e0f73f0..de8c583e7 100644 --- a/src/BlitzKit.CLI/Functions/Mangler.cs +++ b/src/BlitzKit.CLI/Functions/Mangler.cs @@ -330,14 +330,14 @@ namespace BlitzKit.CLI.Functions { case "DT_Turrets": { - Turret turret = new(); + Turret turret = new() { Id = moduleName }; tank.Turrets[moduleName] = turret; break; } case "DT_Guns": { - Gun gun = new(); + Gun gun = new() { Id = moduleName }; tank.Guns[moduleName] = gun; break; } diff --git a/src/BlitzKit.CLI/Protos/Tank.cs b/src/BlitzKit.CLI/Protos/Tank.cs index 3c00f2f3a..6fd15123d 100644 --- a/src/BlitzKit.CLI/Protos/Tank.cs +++ b/src/BlitzKit.CLI/Protos/Tank.cs @@ -32,13 +32,13 @@ namespace Blitzkit { "ay5HdW5zRW50cnkaQAoMVHVycmV0c0VudHJ5EgsKA2tleRgBIAEoCRIfCgV2", "YWx1ZRgCIAEoCzIQLmJsaXR6a2l0LlR1cnJldDoCOAEaOgoJR3Vuc0VudHJ5", "EgsKA2tleRgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmJsaXR6a2l0Lkd1bjoC", - "OAEiCAoGVHVycmV0IgUKA0d1bg==")); + "OAEiFAoGVHVycmV0EgoKAmlkGAEgAigJIhEKA0d1bhIKCgJpZBgBIAIoCQ==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Blitzkit.UtilsReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Blitzkit.Tank), global::Blitzkit.Tank.Parser, new[]{ "Id", "Slug", "Name", "Turrets", "Guns" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, }), - new pbr::GeneratedClrTypeInfo(typeof(global::Blitzkit.Turret), global::Blitzkit.Turret.Parser, null, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Blitzkit.Gun), global::Blitzkit.Gun.Parser, null, null, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::Blitzkit.Turret), global::Blitzkit.Turret.Parser, new[]{ "Id" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Blitzkit.Gun), global::Blitzkit.Gun.Parser, new[]{ "Id" }, null, null, null, null) })); } #endregion @@ -441,6 +441,7 @@ namespace Blitzkit { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public Turret(Turret other) : this() { + id_ = other.id_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -450,6 +451,32 @@ namespace Blitzkit { return new Turret(this); } + /// Field number for the "id" field. + public const int IdFieldNumber = 1; + private readonly static string IdDefaultValue = ""; + + private string id_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Id { + get { return id_ ?? IdDefaultValue; } + set { + id_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "id" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool HasId { + get { return id_ != null; } + } + /// Clears the value of the "id" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearId() { + id_ = null; + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { @@ -465,6 +492,7 @@ namespace Blitzkit { if (ReferenceEquals(other, this)) { return true; } + if (Id != other.Id) return false; return Equals(_unknownFields, other._unknownFields); } @@ -472,6 +500,7 @@ namespace Blitzkit { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override int GetHashCode() { int hash = 1; + if (HasId) hash ^= Id.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -490,6 +519,10 @@ namespace Blitzkit { #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); #else + if (HasId) { + output.WriteRawTag(10); + output.WriteString(Id); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -500,6 +533,10 @@ namespace Blitzkit { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasId) { + output.WriteRawTag(10); + output.WriteString(Id); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -510,6 +547,9 @@ namespace Blitzkit { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public int CalculateSize() { int size = 0; + if (HasId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Id); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -522,6 +562,9 @@ namespace Blitzkit { if (other == null) { return; } + if (other.HasId) { + Id = other.Id; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -541,6 +584,10 @@ namespace Blitzkit { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; + case 10: { + Id = input.ReadString(); + break; + } } } #endif @@ -560,6 +607,10 @@ namespace Blitzkit { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; + case 10: { + Id = input.ReadString(); + break; + } } } } @@ -602,6 +653,7 @@ namespace Blitzkit { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public Gun(Gun other) : this() { + id_ = other.id_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -611,6 +663,32 @@ namespace Blitzkit { return new Gun(this); } + /// Field number for the "id" field. + public const int IdFieldNumber = 1; + private readonly static string IdDefaultValue = ""; + + private string id_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Id { + get { return id_ ?? IdDefaultValue; } + set { + id_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "id" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool HasId { + get { return id_ != null; } + } + /// Clears the value of the "id" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearId() { + id_ = null; + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { @@ -626,6 +704,7 @@ namespace Blitzkit { if (ReferenceEquals(other, this)) { return true; } + if (Id != other.Id) return false; return Equals(_unknownFields, other._unknownFields); } @@ -633,6 +712,7 @@ namespace Blitzkit { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override int GetHashCode() { int hash = 1; + if (HasId) hash ^= Id.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -651,6 +731,10 @@ namespace Blitzkit { #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); #else + if (HasId) { + output.WriteRawTag(10); + output.WriteString(Id); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -661,6 +745,10 @@ namespace Blitzkit { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasId) { + output.WriteRawTag(10); + output.WriteString(Id); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -671,6 +759,9 @@ namespace Blitzkit { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public int CalculateSize() { int size = 0; + if (HasId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Id); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -683,6 +774,9 @@ namespace Blitzkit { if (other == null) { return; } + if (other.HasId) { + Id = other.Id; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -702,6 +796,10 @@ namespace Blitzkit { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; + case 10: { + Id = input.ReadString(); + break; + } } } #endif @@ -721,6 +819,10 @@ namespace Blitzkit { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; + case 10: { + Id = input.ReadString(); + break; + } } } }