Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions memory/build_and_verification.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,11 @@ Chinese numeric-format follow-up: GetCurrentGameLanguage() values schinese/tchin
- Validation: four new tag-parser regression tests first reproduced rejection in the index and all manifest version conditions; all 11 Python tests passed after the change. Verified the official release archive SHA-256, validated all 27 upstream snapshots, then supplied its immutable index and verified cache to the real synchronizer entry point. All 23 pruned snapshots passed standalone manifest validation and CLI validate-only; Decay retained exactly client/g_iVisibleMouse and client CRC64 8a933c53ba9f3979. The original 22 snapshots remained byte-identical when pruned with the old versus new manifest.
- Publication dependency: at verification time Pages still had 26 upstream snapshots and no decay. A real default online-sync attempt failed with `gameVersion(s) absent from the index: decay`; the release archive being available does not publish the Pages index. Default online builds require the upstream Pages deployment before they can consume this manifest.
- Scope/evidence: Python/catalog changes only; no native rebuild, deployment or Decay in-game test. Temporary release and verification output: C:/Users/HZDEV/AppData/Local/Temp/vgui2extension-release-check-163b7a2af3ae46419e53b07bdac2423c. This verifies catalog compatibility, not host/runtime compatibility.


## Issue 951: Career confirmation localization (2026-10-25)

- Trigger/root cause: the rewritten Career storage confirmation uses wide English literals for both QueryBox title and body. DeleteProfile is intercepted before the native CareerBoxDelete resource path; adding the official token again cannot localize those literals. Issue attachment 1 shows this English dialog, while attachment 2 is a Chinese reference; neither shows a bare token. Official czero_schinese/resource/czero_schinese.txt already contains Career_DeleteProfileTitle/Text.
- Fix: ConfirmOperation reuses the existing delete and overwrite title/text tokens, converts the complete identity.rawUtf8 with ConvertCareerPlayerNameToUnicode, and formats the delete body with ILocalize::ConstructString. Allocate from the format and complete Unicode name lengths; use readable English title/body fallbacks for missing tokens. Prepare display text before issuing the sidecar confirmation; preserve existing confirmation-token commands, cancel handling and verified deletion ownership. No language-file override or gamedata change.
- Verification: MSVC x86 Release DLL build, all 8 existing CTests, pinned format-check (66 files) passed. Existing ClientVGUI.cpp C4018 warning remains. Windows czero engine 10210, schinese, 1280x720 live: delete title/body localized and displayed the complete Issue951_123456789012345678901234中文Z name beyond the native 31-byte limit. Delete cancel and overwrite cancel preserved the task profile SHA-256; overwrite title/body localized. ENTER confirmed deletion of the task profile, while pre-existing profile hashes were unchanged.
- Scope/cleanup: game PID 67992 quit normally with exit code 0. Original 21 backed-up DLL/PDB/config/profile/list/appid files were restored and SHA-256 verified. Five task screenshots moved to build/issue951-runtime/screenshots (HalfLife47.tga deletion; HalfLife48.tga overwrite). English language, forced missing-token fallback, other builds and extreme-length layout were not tested in-game. This fixes localization, not the separate native difficulty-label ellipsis.
32 changes: 27 additions & 5 deletions src/CareerProfileStorageHooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <vgui/IClientPanel.h>
#include <vgui/IPanel.h>
#include <vgui/IVGui.h>
#include <vgui/ILocalize.h>
#include <vgui_controls/Controls.h>
#include <vgui_controls/MessageBox.h>
#include <vgui_controls/QueryBox.h>
Expand Down Expand Up @@ -1226,17 +1227,38 @@ void __fastcall ProfileCommand(void* self, int, const char* command);

void ConfirmOperation(void* frame, Operation operation, const Identity& identity)
{
auto token = sidecars.Confirm(Handle(frame), operation, operation == Operation::Create ? identity.rawUtf8 : std::string_view{});
const bool create = operation == Operation::Create;
auto* localization = vgui::localize();
const auto title = localization->Find(create ? "#Career_OverwriteConfirmationTitle" : "#Career_DeleteProfileTitle");
const auto format = localization->Find(create ? "#Career_OverwriteConfirmationText" : "#Career_DeleteProfileText");
std::wstring text;
if (create)
{
text = format ? format : L"This will overwrite a saved profile.\nContinue anyway?";
}
else
{
std::wstring name;
if (!ConvertCareerPlayerNameToUnicode(identity.rawUtf8.c_str(), name))
{
ShowError(StorageError::InvalidUtf8);
return;
}

const auto query = format ? format : L"Are you sure you want to delete %s1?";
text.resize(wcslen(query) + name.size() + 1, L'\0');
localization->ConstructString(text.data(), static_cast<int>(text.size() * sizeof(wchar_t)), query, 1, name.c_str());
}

auto token = sidecars.Confirm(Handle(frame), operation, create ? identity.rawUtf8 : std::string_view{});
if (!token)
{
ShowError(token.error);
return;
}

const auto command = std::string(operation == Operation::Create ? "CareerStorageCreate " : "CareerStorageDelete ") + token.value;
auto* box = new vgui::QueryBox(L"Career profile",
operation == Operation::Create ? L"Overwrite the existing profile with this complete player name?" : L"Delete this profile and its verified legacy copies?",
nullptr);
const auto command = std::string(create ? "CareerStorageCreate " : "CareerStorageDelete ") + token.value;
auto* box = new vgui::QueryBox(title ? title : (create ? L"Overwrite profile" : L"Delete profile"), text.c_str(), nullptr);
box->SetParent(VPanel(frame));
box->AddActionSignalTarget(static_cast<vgui::Panel*>(frame));
box->SetOKCommand(new KeyValues("Command", "command", command.c_str()));
Expand Down
Loading