Add editable map metadata editors - #103
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 888b598375
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| function serializeValidatedW3c(file: W3cFile, name: string): Buffer { | ||
| if (file.error) throw new Error(`Refusing to save ${name}: the source file did not parse (${file.error}).`); | ||
| const reparsed = parseW3cFile(serializeW3c(file)); | ||
| if (reparsed.error || reparsed.version !== file.version || !reparsed.tail.equals(file.tail) || reparsed.cameras.length !== file.cameras.length || reparsed.cameras.some((camera, i) => JSON.stringify(camera) !== JSON.stringify(file.cameras[i]))) throw new Error(`Refusing to save ${name}: round-trip verification failed.`); |
There was a problem hiding this comment.
Normalize float32 values before validating round trips
When a camera field is edited to a decimal that is not exactly representable as float32 (for example, 0.1), writeF32 reparses it as approximately 0.10000000149, so this exact JSON comparison rejects the save with “round-trip verification failed.” The same comparison at line 1489 breaks fractional W3R bounds as well; normalize edited values with Math.fround or compare against float32-normalized expected records.
AGENTS.md reference: AGENTS.md:L114-L116
Useful? React with 👍 / 👎.
| if (ext === '.wpm') return 'wurst.wpmPreview'; | ||
| if (ext === '.wtg') return 'wurst.wtgPreview'; | ||
| if (ext === '.wct') return 'wurst.wctPreview'; |
There was a problem hiding this comment.
Keep archive entries read-only until saves repack the MPQ
When a .mmp, .w3c, or .w3r entry is opened from the MPQ viewer, these mappings now present an editable editor, but the inspected openFile flow at lines 181–200 only extracts the entry under /tmp/wurst_mpq_extract and has no path that writes it back into the .w3x/.w3m archive. Saving therefore appears successful while modifying only the temporary copy, so the user's map remains unchanged; route these entries to the read-only preview as before unless archive repacking is implemented.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in fa34ddd: MPQ-extracted .mmp, .w3c, and .w3r entries now open through the separate read-only wurst.mapDataArchivePreview view type. Standalone files remain editable, while archive saves cannot falsely appear to update the parent MPQ.
|
@codex review |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fa34ddddcf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| import * as fs from 'fs'; | ||
| import * as vscode from 'vscode'; | ||
| import { BinReader, parseW3i as parseW3iFile, serializeW3i, W3iFile, W3iPlayer, W3iForce } from 'casc-ts/formats'; | ||
| import { BinReader, BinWriter, parseW3i as parseW3iFile, serializeW3i, W3iFile, W3iPlayer, W3iForce } from 'casc-ts/formats'; |
There was a problem hiding this comment.
Move the new binary codecs into casc-ts
The .mmp, .w3c, and .w3r editors define their parsers and serializers locally through this BinReader/BinWriter import, while the added tests only reparse generated fixtures instead of proving that an untouched real file round-trips byte-for-byte. An unmodeled format variant can therefore be rewritten and still pass the safety gate because parsing and validation share the same local interpretation; implement these codecs in the sibling casc-ts repository and add byte-exact fixture tests before making the formats editable.
AGENTS.md reference: AGENTS.md:L114-L116
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Deferred from this PR as a cross-repository architecture follow-up. Moving these codecs into casc-ts requires coordinated sibling-library API/export changes, fixture tests, dependency build output, and CI mock updates; the current PR keeps the local codecs tail-preserving and gates every write with serialize → reparse validation. This should be handled as a dedicated casc-ts change rather than partially changing the consumer here.
| ]); | ||
|
|
||
| function w3cCameraInput(camera: W3cCamera, index: number, field: keyof W3cCamera, className = ''): string { | ||
| const value = field === 'name' ? camera.name : fmt(camera[field] as number); |
There was a problem hiding this comment.
Preserve float32 precision in editable inputs
When a stored or entered camera value has more than three decimal places, such as 12.3456, this new editable input renders it as 12.346. Because every edit causes postState to rebuild the table with this formatter, the UI then displays a value different from the model and the saved float32; the region inputs at line 1402 have the same issue. Render a shortest round-trippable float32 representation instead of the preview-oriented three-decimal formatting.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in f193340: editable camera and region inputs now render Math.fround(value).toString() so the displayed value preserves the stored float32 precision. Regression assertions cover both editors.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f1933403f6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| function w3cCameraInput(camera: W3cCamera, index: number, field: keyof W3cCamera, className = ''): string { | ||
| const value = field === 'name' ? camera.name : fmtF32(camera[field] as number); |
There was a problem hiding this comment.
Preserve trigger-string resolution in editable metadata views
When a camera name is stored as TRIGSTR_###, this input now displays the raw reference because the editable provider neither loads war3map.wts nor calls resolveTriggerString, whereas the previous default read-only renderW3c resolved it. The new default .w3r editor does the same for region names and sounds, so affected maps lose their human-readable labels and editing the displayed text replaces the reference instead of updating its WTS entry; retain the source reference and resolve/stage these values as the W3i editor does.
AGENTS.md reference: AGENTS.md:L85-L85
Useful? React with 👍 / 👎.
| else if (W3C_NUMERIC_FIELDS.has(field as keyof W3cCamera)) { | ||
| const value = Number(rawValue); | ||
| if (!Number.isFinite(value)) return; | ||
| after[field as keyof W3cCamera] = value as never; |
There was a problem hiding this comment.
Reject values that overflow float32
For a finite JavaScript number outside the float32 range, such as 1e39, this accepts the edit even though writeF32 serializes it as Infinity. The round-trip gate does not catch the corruption because Math.fround(1e39) is also Infinity and both sides of the JSON comparison stringify that value as null; the equivalent W3R bounds path has the same problem. Require Number.isFinite(Math.fround(value)) before accepting these edits.
Useful? React with 👍 / 👎.
Codex review-loop summary
Findings
Validation
The PR is ready for merge with the |
Summary
.mmp,.w3c, and.w3rmap metadata files.Checks
npm testnpx tsc -p . --noEmitnpm run lintnpm run test:e2e— 65 passedgit diff --checkKnown gaps