Repository navigation
feat(text): Load extra string files next to the string table - #3460
tintinhamans wants to merge 4 commits into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
WalkthroughThe text manager merges ChangesText file loading
Directory search behavior
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Feature · Severity of issue fixed: Medium Suggested reviewers: Merge Risk: 🔵 Low · up to
|
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
32e49e1c-a26d-4c7c-847c-55d9760cf9b9
📥 Commits
Reviewing files that changed from the base of the PR and between ab568af and ad6030d777a2481e46b3391196ae93290a264740.
📒 Files selected for processing (2)
Core/GameEngine/Source/Common/System/ArchiveFile.cppCore/GameEngine/Source/GameClient/GameText.cpp
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.
7ea64ce to
a93f4a7
Compare
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to GitHub limitations.
🟠 Major · Validate the CSF label count before allocation. · GameText.cpp:443
Core/GameEngine/Source/GameClient/GameText.cpp:443
🩺 Stability & Availability | 🟠 Major | ⚡ Quick winValidate the CSF label count before allocation.
getCSFInfoaccepts a signednum_labelsafter checking only the header ID.mergeStringFilethen passes that value toNEW StringInfo[capacity]beforeparseCSFcan reject excess records. A negative or file-inconsistent count can request an invalid or excessive allocation and prevent text initialization.Reject negative counts and counts larger than the remaining file bytes divided by the minimum label-record size.
🐛 Suggested fix
if ( header.id == CSF_ID ) { - textCount = header.num_labels; + const Int remainingBytes = file->size() - file->position(); + const Int minLabelBytes = sizeof(Int) * 3; + + if ( remainingBytes < 0 || header.num_labels < 0 || + header.num_labels > remainingBytes / minLabelBytes ) + { + break; + } + + textCount = header.num_labels; if ( header.version >= 2 ) { language = (LanguageID) header.langid;
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
b595e7f8-c6f3-4828-a350-957039cab174
📥 Commits
Reviewing files that changed from the base of the PR and between 3f9d3b223c006b417f36b2578d2a2cc06866c578 and a93f4a701dc2205c49476af57d0e2cbe38b70f0f.
📒 Files selected for processing (1)
Core/GameEngine/Source/GameClient/GameText.cpp
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 0 remain after this review.
01f10f4 to
c79f7c4
Compare
[Medium impact] The PR appears safe to merge; no new actionable issues were found.
|
99ffeae to
b754b90
Compare
b754b90 to
01eb4bd
Compare
01eb4bd to
bd77ebd
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
bb49ef62-8a47-4902-a46f-615802606014
📥 Commits
Reviewing files that changed from the base of the PR and between 01eb4bdf89e1ee6525cd9960426607fd64820146 and bd77ebda75252bd4c709d4d909399387473d7ab1.
📒 Files selected for processing (1)
Core/GameEngine/Source/GameClient/GameText.cpp
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review.
d03882c to
a835031
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
8daf08b2-bd6d-478d-91d3-dd2b5548bd16
📥 Commits
Reviewing files that changed from the base of the PR and between bd77ebda75252bd4c709d4d909399387473d7ab1 and a835031c34c22081a2bbbca1c0fc02af7420b792.
📒 Files selected for processing (1)
Core/GameEngine/Source/GameClient/GameText.cpp
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review.
a835031 to
224c143
Compare
224c143 to
b7b7332
Compare
b7b7332 to
c32efb6
Compare
c32efb6 to
325ee93
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
81013c44-3693-435c-b2d5-0e1a9cafa01f
📥 Commits
Reviewing files that changed from the base of the PR and between 224c143b40a86db74753171cc439ad0d2f8db4cd and 325ee9304a88be7dcae745dacb52c54915d3f893.
📒 Files selected for processing: 2
Core/GameEngine/Source/Common/System/ArchiveFile.cppCore/GameEngine/Source/GameClient/GameText.cpp
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review.
325ee93 to
3fcdd09
Compare
3fcdd09 to
4e268ac
Compare
Merge after #3458. Closes #255
Right now the game reads one string file per language, so changing two labels means shipping a full
generals.csf.With this, every other
.strand.csfindata\<Language>\anddata\loads too, loose or in a big. A file only needs the labels it changes.Precedence is the rule modders already know from bigs: whatever sorts first wins. Language folder before
data\, files in name order,.strbefore.csfof the same name, and the game's own string file last so it only fills in what nothing else set.000_mymod.strbeatszz_other.strthe same way000_mymod.bigbeatszz_other.big.Retail 1.04 has nothing extra to load. Steam 1.05 has
Data\Patch.strinPatchData.big(the two Custom Mission labels) which the 1.05 exe reads and this code never did. That gets picked up now.data\<Language>\vsdata\.strbeats.csfof the same namegenerals.csfThe first two rows are just how the file system already works.
map.strstays a separate table that is only checked for labels the main one doesn't have. If parsing fails, the whole map string file is discarded rather than keeping a partial result.Three commits: the parsers first push into a vector instead of a pre-sized array, then the parsers get bounds, then the layering. The vector drops the second pass over every str file that only counted END lines, the 500 entry slack, and the separate map.str parser, which was a copy of the str parser with a language filter. Malformed files get dropped instead of corrupting memory. For a csf that is oversized labels or text, a header count the file can't hold, a truncated file (including a partial record ID), or label and string counts that don't match the header. For a str it is a line, string or speech name longer than the buffer, a label with no quoted text, or a quote that never closes, which hangs startup on main. Explicit empty strings (
"") remain valid. Every read is checked, so a bogus string count no longer spins. AGenerals.strthat fails to parse falls back togenerals.csf.Tested: INI CRC unchanged (
FEAAE3F3on main, with this, and with extra str files around). Same 11 labels out of LF, CRLF and mixed, loose and in a big, so #255's line ending concern doesn't apply. 22 scenarios in game, sheet below.