parent
e0ba3e7f2c
commit
3ebb120dd2
20 changed files with 700 additions and 100 deletions
|
|
@ -39,10 +39,56 @@ confirmed closed by the owner, 11 need a focused live gate, and 43 are safe to
|
|||
remain closed. See
|
||||
[`docs/research/2026-08-28-owner-closed-issue-validity-audit.md`](research/2026-08-28-owner-closed-issue-validity-audit.md).
|
||||
|
||||
## #484 — Distant mountain silhouettes flicker and change with viewpoint
|
||||
|
||||
**Status:** OPEN — OWNER-DEFERRED, 2026-09-06, after report on #483 candidate.
|
||||
Flicker continues while still; camera movement reveals more mountain at some
|
||||
spots. Exact pose/consecutive-frame reproduction still needed; no fix/PASS.
|
||||
Read-only investigation found complete terrain index coverage and no obvious
|
||||
stale-list accumulation. Finite GPU far clipping is a candidate explanation,
|
||||
not a confirmed cause: the named and paired retail also use finite far clipping.
|
||||
See `research/2026-09-01-overhaul/484-distant-terrain-flicker-investigation.md`.
|
||||
The owner explicitly directed deferral and campaign closeout/merge. Exact
|
||||
viewpoint and /loc remain future investigation work. Retail was untouched.
|
||||
No speculative projection/fog or FPS change made; no fix/PASS claimed.
|
||||
|
||||
## #483 — Far terrain loads but disappears at the near-tier boundary
|
||||
|
||||
**Status:** DONE — repair accepted in owner-directed campaign closeout,
|
||||
2026-09-06. Release build (0 warnings/errors), 106 narrow tests and the final
|
||||
7,161-test App lane pass. Initial 105/1 narrow run selected the stale default
|
||||
package and remains recorded. Both post-owner reviews PASS with no blocking
|
||||
findings. The owner's subsequent silhouette-flicker report is separately
|
||||
deferred as #484; no visual PASS for that symptom is claimed.
|
||||
|
||||
Original owner G4 regression: owner reports a hard
|
||||
terrain cutoff and reduced visible distance in `logs/owner-g4-20260906-r1/`.
|
||||
The launch and later settings-reapply log both show NearRadius4/FarRadius25;
|
||||
the saved landscape setting is25, so this is not a reduced preference.
|
||||
No screenshot or exact cutoff-distance measurement was supplied for this row.
|
||||
|
||||
Static cause: LoadFar has no EnvCells, while the sole landscape registration
|
||||
in LandblockRenderPublisher.AdvanceCompleteOne is gated on EnvCells. Far GPU
|
||||
terrain meshes consequently have no landscape slot/draw turn. Near-to-far
|
||||
retirement independently removes the whole landscape slot with the building
|
||||
registry, although it retains terrain. The production walk grid is51x51;
|
||||
the standalone WalkLandscape11x11 default is not the production limit.
|
||||
|
||||
Repair: terrain bounds/population now travel independently of buildings,
|
||||
including the worker's Far stripping and both accepted-as-Far conversions.
|
||||
Demotion retains terrain; full removal retires it. No larger near window, fog
|
||||
change or second pass. Six production/two test files; AP-149 remains open.
|
||||
The repaired build was launched for the owner in logs/owner-g4-20260906-r2/
|
||||
and r3. Retail was untouched; its presence no longer blocks builds by explicit
|
||||
owner override. Exact hashes, review scope and proof limits:
|
||||
`research/2026-09-01-overhaul/483-far-terrain-registration-contract.md` and
|
||||
`research/2026-09-01-overhaul/2026-09-06-campaign-closeout.md`.
|
||||
|
||||
## #482 — Some exterior cathedral walls do not stop the player
|
||||
|
||||
**Status:** IN-PROGRESS — scoped repair, automated gates and lead graphical
|
||||
wall gate PASS/provisional; owner acceptance pending. At F4180012 [48.002960,39.257545,160.004990],
|
||||
**Status:** DONE — repair accepted in owner-directed campaign closeout,
|
||||
2026-09-06. Automated gates and lead graphical wall gate PASS/provisional
|
||||
remain the recorded proof, not newly executed tests. At F4180012 [48.002960,39.257545,160.004990],
|
||||
AcDream can remain halfway through the wall. Retail teleported to that position
|
||||
pushes out to x48.480000. Read-only retail capture identifies the neighboring
|
||||
F418000A building Gfx01001FB3;0012 has no building pointer. Paired native code
|
||||
|
|
|
|||
|
|
@ -1190,6 +1190,20 @@ cross-source tie ordinal), and AP-243 (retail's >50 m shared-cell-key
|
|||
optimization). They are bounded residuals, not a second visibility or ordering
|
||||
model.
|
||||
|
||||
**Terrain population ownership (#483 closed, 2026-09-06).**
|
||||
`LandblockBuild.TerrainBounds` carries the existing authored height-table bounds
|
||||
for both Near and Far loads, independently of EnvCells. The worker's Far payload
|
||||
stripping and both accepted-as-Far conversions preserve this metadata.
|
||||
`LandblockRenderPublisher` registers terrain in the sole `WalkLandscapeAssembler`
|
||||
even when the build contains no buildings; terrain draws still come exclusively
|
||||
from the retail walk's land-cell turns. Demotion clears the entry's building
|
||||
references but retains terrain; full terrain removal retires the entry. This
|
||||
restores missing population without changing the walk, view distance or Far-tier
|
||||
content policy. AP-149's missing distant static/building closure remains open.
|
||||
Release build, 106 narrow tests and the final 7,161-test App lane pass; both
|
||||
post-owner review lenses PASS. Owner-directed campaign closeout accepts this
|
||||
repair with separate silhouette-flicker issue #484 deferred.
|
||||
|
||||
The exact target and evidence are recorded in
|
||||
`docs/research/2026-09-01-overhaul/oh1-retail-world-contract.md`; OH5, OH6, and
|
||||
OH7 own these cutovers.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
# Retail Divergence Register — current through 2026-08-28
|
||||
|
||||
**OVERHAUL closeout, 2026-09-06:** owner-directed acceptance carries all
|
||||
remaining register rows, including AP-149; it is not blanket retirement.
|
||||
#483 restores missing terrain registration with the existing retail bounds
|
||||
and walk, introducing no intentional deviation. #484 is an owner-deferred
|
||||
symptom with unconfirmed cause, tracked in ISSUES rather than misclassified
|
||||
as a proven retail deviation. See the
|
||||
[closeout](../research/2026-09-01-overhaul/2026-09-06-campaign-closeout.md).
|
||||
|
||||
**What this is.** The single auditable register of every known place acdream's
|
||||
runtime behavior can deviate from the retail client (Sept 2013 EoR build,
|
||||
`docs/research/named-retail/`). It was triggered by a week of "small things"
|
||||
|
|
|
|||
|
|
@ -461,6 +461,17 @@ rendering and landblock mesh pins while retaining the terrain slot. Core's
|
|||
matching physics demotion preserves the terrain surface but removes indoor
|
||||
cells, portals, buildings, and static shadow registrations.
|
||||
|
||||
**Far-terrain draw registration (#483 closed, 2026-09-06).**
|
||||
The existing `CLandBlock::get_land_limits` height-table bounds (+200/-1) are
|
||||
carried independently of EnvCells by `LandblockBuild.TerrainBounds`, including
|
||||
worker and accepted-as-Far conversions. Terrain publication registers both tiers
|
||||
with the single walk landscape owner. Demotion retains that terrain entry while
|
||||
clearing buildings; full terrain removal retires it. No new terrain algorithm,
|
||||
second draw pass, larger Near window or Far static/building hydration is added.
|
||||
AP-149 remains open. Release build, 106 narrow tests and the final 7,161-test
|
||||
App lane pass; both post-owner review lenses PASS. Owner-directed campaign
|
||||
closeout accepts the repair, with separate flicker issue #484 deferred.
|
||||
|
||||
**Cost-budgeted publication seam (2026-07-24).** WorldBuilder's editor path
|
||||
publishes a complete manager-owned scene; acdream's live streamer instead
|
||||
advances prepared render, physics, static, building, EnvCell, and spatial
|
||||
|
|
|
|||
|
|
@ -518,19 +518,19 @@ Plus polish that doesn't get its own phase number:
|
|||
|
||||
## Phases ahead — agreed order
|
||||
|
||||
### Campaign OVERHAUL v2 — world solidity (ACTIVE, G4 unpassed, 2026-09-05)
|
||||
### Campaign OVERHAUL v2 — world solidity (CLOSED, owner accepted with carried issues, 2026-09-06)
|
||||
|
||||
The five-slice successor owns geometry, cross-cell membership, retail walk,
|
||||
depth/alpha ordering and consumer/material closeout. S1-S5 implementations and
|
||||
the gate-found repairs are landed; final Release candidate `eea83ac88` has
|
||||
17,094 hermetic passes and passing lifecycle/reconnect/R6 checks. Canonical
|
||||
InstalledDat is not wholly green (eight unchanged failures/one skip), and one
|
||||
final visual control failed at native shutdown (#422 symptom recurrence).
|
||||
Owner G4, explicit carried-result disposition and final documentation closeout
|
||||
remain; no main merge or CLOSED claim. FPS/C2 is owner-deferred and the known
|
||||
retail cathedral slab leak is unchanged. The current ledger is
|
||||
The five-slice successor shipped geometry, cross-cell membership, retail walk,
|
||||
depth/alpha ordering and consumer/material closeout, plus gate-found repairs.
|
||||
The final #483 Far-terrain repair passes Release, 106 narrow and 7,161 App tests;
|
||||
both post-owner review lenses PASS. The owner directed closeout/integration
|
||||
with #484 silhouette flicker deferred. Earlier integrated evidence retains
|
||||
17,094 hermetic passes and lifecycle/reconnect/R6. InstalledDat's eight known
|
||||
failures/one skip and the native shutdown failure remain failures; AMD cause
|
||||
uncertainty, FPS/C2, AP-149 and the known retail cathedral slab leak are carried.
|
||||
Remaining unreported owner matrix rows are not fabricated PASS rows. The ledger is
|
||||
[`2026-09-01-campaign-overhaul-world-solidity.md`](2026-09-01-campaign-overhaul-world-solidity.md),
|
||||
with the [owner checklist](../research/2026-09-01-overhaul/g4-owner-checklist.md).
|
||||
with the [owner-directed closeout](../research/2026-09-01-overhaul/2026-09-06-campaign-closeout.md).
|
||||
|
||||
### Campaign FW — the retail frame walk (execution superseded by OVERHAUL)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,20 +12,19 @@ world-lifecycle automation protects fresh login, outdoor/world-edge/dungeon
|
|||
travel, same-location revisit, exact graceful disconnect, and uncapped
|
||||
fresh-process reconnect with canonical JSON/PNG evidence.
|
||||
|
||||
**Active render prerequisite (2026-09-05): Campaign OVERHAUL v2 — G4 unpassed.**
|
||||
The five-slice successor to FW has landed the geometry, membership, retail
|
||||
walk, depth/alpha and consumer/material cutovers, plus the gate-found exterior,
|
||||
portal-reveal, lighting, equipped-item and cathedral-wall repairs. The final
|
||||
candidate is Release `eea83ac88`; hermetic17,094/17,094 and the final lifecycle,
|
||||
reconnect and R6 checks pass. Canonical InstalledDat retains eight documented
|
||||
failures/one skip; a final visual-control run also failed at native shutdown
|
||||
despite graceful network logout. Neither is silently counted as PASS.
|
||||
The final owner matrix and explicit carried-result disposition remain, followed
|
||||
by documentation closeout; no main merge before G4. FPS/C2 is owner-deferred,
|
||||
and retail's known cathedral slab leak is unchanged. FW's old ordinary-mesh
|
||||
clip model is historical, not the current architecture. Plan/ledger:
|
||||
**Render prerequisite CLOSED — owner accepted with carried issues, 2026-09-06.**
|
||||
Campaign OVERHAUL v2 shipped the five geometry, membership, retail-walk,
|
||||
depth/alpha and consumer/material slices, plus gate-found exterior, reveal,
|
||||
lighting, held-item, cathedral-wall and Far-terrain registration repairs.
|
||||
The owner directed closeout and integration with #484 mountain flicker deferred.
|
||||
The last repair passes Release, 106 narrow tests and 7,161 App tests, with
|
||||
both post-owner review lenses PASS. Earlier integrated evidence includes
|
||||
17,094 hermetic passes and lifecycle/reconnect/R6. Known InstalledDat failures,
|
||||
native shutdown failure, AMD cause uncertainty, FPS/C2 and the retail cathedral
|
||||
slab leak remain carried; unreported matrix rows are not invented PASS rows.
|
||||
M4 itself remains active. FW's old mesh clip model is historical. Plan/ledger:
|
||||
[`2026-09-01-campaign-overhaul-world-solidity.md`](2026-09-01-campaign-overhaul-world-solidity.md);
|
||||
[remaining owner checklist](../research/2026-09-01-overhaul/g4-owner-checklist.md).
|
||||
[owner-directed closeout](../research/2026-09-01-overhaul/2026-09-06-campaign-closeout.md).
|
||||
|
||||
Before new M4 quest/emote/character-creation subsystem bodies enter the App
|
||||
layer, the active structural prerequisite is the behavior-preserving
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
**Status:** EXECUTION SUPERSEDED by Campaign OVERHAUL (opened 2026-08-30;
|
||||
spec approved by owner 2026-08-30). Historical stages and evidence are retained;
|
||||
this status is not a new user-acceptance or merge claim.
|
||||
this status does not independently assert acceptance of the successor.
|
||||
**Successor closeout, 2026-09-06:** OVERHAUL is owner-accepted with carried
|
||||
issues (#484 deferred) and integration authorized. See its
|
||||
[closeout report](../research/2026-09-01-overhaul/2026-09-06-campaign-closeout.md).
|
||||
**Successor execution ledger (owner-requested 2026-09-01):**
|
||||
[`docs/plans/2026-09-01-campaign-overhaul-world-solidity.md`](2026-09-01-campaign-overhaul-world-solidity.md).
|
||||
Campaign OVERHAUL preserves FW as evidence/history but owns all further
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
# Campaign OVERHAUL — retail world construction and render solidity
|
||||
|
||||
**Status:** ACTIVE — **v2 rescope 2026-09-02.** Five production slices replace
|
||||
the twelve-stage v1 plan. S1 is the current slice. See §13 for the ledger and
|
||||
§15 for what v2 changed and why.
|
||||
**Status:** CLOSED — OWNER ACCEPTED WITH CARRIED ISSUES, 2026-09-06.
|
||||
The owner directed campaign closeout, commit, merge to main and push to Gitea,
|
||||
with mountain flicker #484 deferred. This resolves the merge gate by owner
|
||||
direction; it does not turn unreported matrix rows or known failures into PASS.
|
||||
See the [closeout](../research/2026-09-01-overhaul/2026-09-06-campaign-closeout.md),
|
||||
§13 for retained history and §15 for the v2 rescope.
|
||||
|
||||
**Campaign code:** `OH`.
|
||||
|
||||
|
|
@ -11,9 +14,9 @@ the twelve-stage v1 plan. S1 is the current slice. See §13 for the ledger and
|
|||
|
||||
**Branch (binding):** `claude/campaign-w-retail-frame-walk`. This is the
|
||||
long-lived renderer integration branch. It carries all of Campaign FW (101
|
||||
commits over `origin/main` at `e102fb36`). **Nothing merges to `main` until
|
||||
the final gate passes**; `origin/main` is merged INTO this branch at every
|
||||
slice boundary so it never drifts.
|
||||
commits over `origin/main` at `e102fb36` at that checkpoint). The original
|
||||
no-merge-before-final-gate rule held during implementation; the owner's
|
||||
2026-09-06 closeout with carried issues now explicitly authorizes integration.
|
||||
|
||||
**v2 base:** `5d907ae9` (`docs(render): define OH1 retail world contract`),
|
||||
tree clean. The uncommitted OH1/T3 evidence grammar (~32K lines) is parked
|
||||
|
|
@ -602,6 +605,7 @@ code.
|
|||
| Cathedral stairwell, camera zoomed out (owner, 2026-09-03 night, #464) | `0xF4180113 [39.502899 19.589222 181.119247]` (also `0xF4180112 [39.070965 22.549135 178.781418]`, `0xF4180113 [39.364658 21.293159 179.773422]`), third-person camera zoomed fully out and tilted slightly up | Root `0xF4180114` with `0x113`/`0x112` flooded draws the stairwell solid, and from an eye beyond the open y=24 face (root `0xF4180109`, which retail's swept 0.3 m viewer sphere also reaches) the stairwell cells seen through the building's exterior portals draw with their walls — no vaulted hall, archway sky, balcony or floating stair slabs through the stairwell walls | S4 (owner gate G3 names zoom) |
|
||||
|
||||
| Adjacent outdoor portal reveal (#474, owner 2026-09-05) | 3032FFFF → destination30310005, same-window hop184.5m; near4/far25, reveal6 in owner-regate-20260905-bf23673f3-r1 | Destination publication and exact placement acknowledgements converge; no circular wait, no forced/partial world reveal. Include repeated adjacent and long-distance portal controls; record latency rather than presuming all slow holds share this cause | S5 / G4 |
|
||||
| Distant terrain cutoff (#483, owner 2026-09-06) | Owner G4 run owner-g4-20260906-r1, near4/far25; exact standing pose/cutoff distance not captured | Every resident far-terrain block has a landscape entry and an eligible terrain draw turn; near-to-far demotion retains terrain while removing buildings. Preserve the selected far distance and retail ordering; do not hide the missing population with fog or a second terrain pass | S5 / G4 |
|
||||
|
||||
Append-only; a new symptom gets a row and an existing invariant before any fix.
|
||||
|
||||
|
|
@ -678,6 +682,13 @@ exact commit, recipe, and log path; the owner closes the client.
|
|||
|
||||
## 13. Execution ledger
|
||||
|
||||
**Final disposition — 2026-09-06:** S1-S5 and #483 are closed by owner-directed
|
||||
acceptance with carried issues. #483 Release/106 narrow tests and the final
|
||||
7,161-test App lane pass; both post-owner review lenses PASS. #484 is OPEN,
|
||||
owner-deferred, not fixed. Earlier pending/FAIL snapshots below are historical;
|
||||
recorded failures remain failures. The [closeout report](../research/2026-09-01-overhaul/2026-09-06-campaign-closeout.md)
|
||||
owns current status, exact candidate hashes, review scope and remaining work.
|
||||
|
||||
Update immediately when a slice changes state. Chat is not the ledger.
|
||||
|
||||
| Slice | Status | Spec | Implementation | Reviews | Automated gate | Owner gate | Notes |
|
||||
|
|
@ -719,6 +730,32 @@ The remaining owner session and explicit carried-result boundaries are in
|
|||
`docs/research/2026-09-01-overhaul/g4-owner-checklist.md`; no row is pre-passed.
|
||||
Known retail leak unchanged, FPS/C2 deferred, no main merge.
|
||||
|
||||
**2026-09-06 owner G4 update:** maximum-distance terrain cutoff is a new FAIL,
|
||||
with a fixed candidate now launched for owner re-test: PID17856,
|
||||
logs/owner-g4-20260906-r2/,07:37:36UTC; entered world07:37:40UTC. Release build
|
||||
0 warnings/errors; narrow tests106/106 with explicit current package (initial
|
||||
105/1 stale-default-package failure retained). Owner explicitly removed the
|
||||
retail-absence restriction for builds/tests/launch; retail remains untouched.
|
||||
Owner test then review are pending, no visual/G4 PASS. The following handoff
|
||||
status is historical and superseded by this execution update:
|
||||
#483. Source confirms missing Far landscape registration plus demotion removing
|
||||
terrain's walk entry with the building registry. Bounded contract
|
||||
`483-far-terrain-registration-contract.md` at e0ba3e7f2 now has a written,
|
||||
uncommitted candidate and regression tests (six production/two test files).
|
||||
The worker Far-payload metadata forwarding is an explicitly authorized contract
|
||||
amendment. Only whitespace validation ran: UNBUILT/UNTESTED/UNREVIEWED;
|
||||
the previously tested eea83ac88 binary is unchanged.
|
||||
Owner's explicit order is fix -> owner test -> review; no pre-owner review.
|
||||
Retail PID25988 is owner-held: do not touch it or build/test/launch beside it.
|
||||
No repaired-build or G4 PASS yet. This is correctness, not deferred FPS/C2 work.
|
||||
|
||||
**Additional owner finding #484 (2026-09-06):** distant mountain silhouettes
|
||||
flicker even while still and change coverage with viewpoint on the #483 candidate.
|
||||
Read-only investigation is documented in `484-distant-terrain-flicker-investigation.md`.
|
||||
No cause/fix/PASS established; exact affected viewpoint requested. The .1/5000
|
||||
projection versus radius25 square is not itself proof: paired retail also clips
|
||||
terrain at finite far. No speculative projection/fog change. G4 remains unpassed.
|
||||
|
||||
### Rollback ledger
|
||||
|
||||
| Slice | Commits | Last accepted gate | Revert |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
# Campaign OVERHAUL v2 — owner-directed closeout, 2026-09-06
|
||||
|
||||
**CLOSED — OWNER ACCEPTED WITH CARRIED ISSUES.** After the connected testing
|
||||
and the #483 distance repair, the owner directed: "Ok defer that as an issue.
|
||||
I want to close out the campain, commit and merge this worktree with main and
|
||||
then push main to remote gita". This is the final merge-gate disposition:
|
||||
accept the campaign with #484 deferred, not a claim that every remaining G4
|
||||
checklist row was individually run or passed. Unreported rows remain
|
||||
unreported; known failed evidence remains FAIL.
|
||||
|
||||
## Shipped scope
|
||||
|
||||
S1-S5 provide the geometry and cross-cell membership products, single retail
|
||||
frame walk, depth/alpha ordering, and consumer/material cutovers. Gate-found
|
||||
repairs cover outdoor buildings, portal reveal, dungeon lighting, held items,
|
||||
cathedral exterior collision and finally missing Far-terrain registration.
|
||||
FW's predecessor ledger remains historical; its old clip model is not the
|
||||
shipping architecture. M4 as a whole is not declared complete.
|
||||
|
||||
The last bounded fix, #483, carries the existing height-table terrain bounds
|
||||
through Near/Far construction and all Far conversions, registers terrain
|
||||
independently of buildings, retains it during demotion and removes it during
|
||||
full retirement. It changes no radius, fog, LOD or retail walk algorithm.
|
||||
The owner used the repaired build; the subsequently reported mountain flicker
|
||||
is separately retained as #484, with no confirmed cause or speculative fix.
|
||||
|
||||
## Final candidate verification
|
||||
|
||||
- Release App/test build: PASS, zero warnings/errors.
|
||||
- Narrow production-path regression suite: 106 passed / 0 failed / 0 skipped,
|
||||
using the explicit recipe10 package. The initial 105/1 run selected the
|
||||
obsolete default recipe8 package; both reports are retained under
|
||||
`artifacts/483-far-terrain/`. No source change masked that mismatch.
|
||||
- Final no-build App hermetic-filter regression: **7,161 passed / 0 failed /
|
||||
0 skipped**. Report:
|
||||
`artifacts/483-closeout-app-hermetic/483-closeout-app-hermetic.trx`.
|
||||
Filter excludes Lane InstalledDat, Linux, Manual, Timing, Live and
|
||||
PreparedPackage. This is an App result, not a new complete-solution run.
|
||||
- Post-owner independent retail review: **PASS**, no blocking finding.
|
||||
Independent architecture/lifetime review: **PASS**, no blocking finding.
|
||||
Both reviewed the six production/two test files; no further fix round.
|
||||
Review scope and named/paired retail evidence are in
|
||||
`483-far-terrain-registration-contract.md`; neither review certifies #484.
|
||||
- App SHA256:
|
||||
`869BA14CB2C610E006C80BDFFCBD75629339A3486B8B98D7708B23050700FF34`.
|
||||
Core SHA256:
|
||||
`B0E676482A45ED77C2AB050BBBC988139D1BF6D99308C42ABB0CFF440D39A0BC`.
|
||||
Package `acdream-v10-s5-c5.pak` SHA256:
|
||||
`4E0FA6C589ECE12E13099A56385077964961EC52F888BC9161C6F5D34829B59B`.
|
||||
- Owner launches: `logs/owner-g4-20260906-r2/` (PID17856) and
|
||||
`logs/owner-g4-20260906-r3/` (PID24476), same repaired build.
|
||||
No new automated visual/PNG PASS is invented for this closeout.
|
||||
|
||||
## Preserved evidence and carried work
|
||||
|
||||
The previous integrated source `eea83ac884d0b0fd74d86a17a16d7d5d93f64d94`
|
||||
passed Release, 17,094 complete-solution hermetic tests, repeated unchanged
|
||||
geometry/membership and Signature8 checks, lifecycle/reconnect and R6.
|
||||
Those results are historical integrated evidence, not a full-suite run on
|
||||
the final #483 delta.
|
||||
|
||||
Canonical InstalledDat remains **376 pass / 8 known failures / 1 known skip**.
|
||||
The five final visual controls retain 51 inspected PNGs and their narrow,
|
||||
provisional verdicts. Four controls exited0; the wall control exited
|
||||
**0xC0000374 (process FAIL)** despite graceful network logout. No native stack
|
||||
establishes its cause or equates it with the AMD notice. See
|
||||
`c1c-integrated-verification.md`,
|
||||
`s5-final-lifecycle-stability-verification.md` and
|
||||
`s5-final-visual-controls.md` for exact limitations, paths and sealed manifests.
|
||||
|
||||
Carried without claiming repair: **#484** distant silhouette flicker (explicit
|
||||
owner deferral); **#422** native shutdown symptom; **#477** AMD crash notice /
|
||||
unconfirmed initiating cause; the known InstalledDat failures/skip; the known
|
||||
retail cathedral exterior-slab leak; owner-deferred FPS/C2; and the existing
|
||||
divergence-register residuals including **AP-149** (Far static/building
|
||||
closure). #483 adds no intentional retail deviation and retires none of
|
||||
those residuals. Remaining unreported G4 matrix rows are not fabricated PASS
|
||||
rows; the owner's closeout instruction supersedes waiting for that session.
|
||||
|
||||
## Integration authorization
|
||||
|
||||
Commit the owned candidate and documentation, merge the campaign branch into
|
||||
main, then push **origin/main** to Gitea
|
||||
`https://git.snakedesert.se/erik/acdream.git`. Do not push the GitHub remote.
|
||||
Preserve main's unrelated untracked files and WorldBuilder submodule checkout;
|
||||
no reset, clean, stash, history rewrite or force push. Actual Git completion
|
||||
is reported after the operations succeed, not asserted by this pre-commit note.
|
||||
Retail is untouched. Its presence does not block a build by the owner's
|
||||
explicit override; a running ACDream still must not have its binaries replaced.
|
||||
|
|
@ -5,6 +5,50 @@ Owner order: **implement, owner tests, then review**. This overrides the normal
|
|||
pre-owner review order for this bounded fix; no claim of review closure follows
|
||||
from implementation or successful compilation.
|
||||
|
||||
**Latest owner safety correction (2026-09-06):** retail being open does NOT
|
||||
block building/testing/launching ACDream. The owner explicitly directed
|
||||
"Just ignore if retail is up or not, does not affect our building. Now build
|
||||
and launch." Leave retail untouched. Only a running ACDream blocks overwriting
|
||||
its build or launching a duplicate. This supersedes all older both-client
|
||||
absence requirements below; those describe the earlier handoff, not current
|
||||
permission. The requested launch is manual, with review after the owner's test.
|
||||
|
||||
## Final disposition — CLOSED, 2026-09-06
|
||||
|
||||
The owner directed campaign closeout and integration, with subsequent mountain
|
||||
flicker deferred as #484. After the owner session, independent retail and
|
||||
architecture/lifetime reviews both **PASS**, no blocking findings and no new
|
||||
fix round. Retail review verified unchanged get_land_limits bounds, independent
|
||||
Far terrain admission, all three metadata-preserving conversion paths and
|
||||
unchanged walk/LOD policy against named retail and the paired evidence below.
|
||||
Lifetime review verified the sole owner, retained publication receipt,
|
||||
demotion/full-removal split, late-clear non-resurrection and production-route
|
||||
regressions. Neither review certifies #484 or closes AP-149.
|
||||
|
||||
Final no-build App hermetic-filter regression: **7,161/0/0**; report
|
||||
`artifacts/483-closeout-app-hermetic/483-closeout-app-hermetic.trx`.
|
||||
The Release build and 106 narrow passes below cover the same product candidate.
|
||||
See `2026-09-06-campaign-closeout.md` for the owner's merge-gate disposition
|
||||
and retained failures. No new individual visual PASS is asserted.
|
||||
|
||||
## Historical execution — owner client launched
|
||||
|
||||
After the explicit owner override, Release App/test build passed with zero
|
||||
warnings/errors. Initial narrow run: 105 pass / 1 fail because it selected the
|
||||
old default acdream.pak (recipe 8, expected 10). No product change was made for
|
||||
that environment failure. Rerun with ACDREAM_PAK_PATH explicitly selecting the
|
||||
same acdream-v10-s5-c5.pak as the client: **106 pass / 0 fail / 0 skip**.
|
||||
Both TRX reports remain under artifacts/483-far-terrain/.
|
||||
|
||||
The fixed uncommitted candidate launched once: PID17856 at
|
||||
2026-09-06T07:37:36.5010165Z, enteredWorld07:37:40.5272305Z; logs are
|
||||
logs/owner-g4-20260906-r2/. App SHA256
|
||||
869BA14CB2C610E006C80BDFFCBD75629339A3486B8B98D7708B23050700FF34;
|
||||
Core B0E676482A45ED77C2AB050BBBC988139D1BF6D99308C42ABB0CFF440D39A0BC.
|
||||
Retail untouched, no automated route or automatic close. Owner testing and
|
||||
post-owner review were pending at this launch checkpoint; the final disposition
|
||||
above supersedes it and the earlier unbuilt handoff statements below.
|
||||
|
||||
## Confirmed cause
|
||||
|
||||
Owner-g4-20260906-r1 logged NearRadius4/FarRadius25, unchanged maximum preference.
|
||||
|
|
@ -29,7 +73,8 @@ preserves this known gap instead of asserting a usable far draw product.
|
|||
both tiers. Keep exactly one landscape owner and existing walk ordering/LOD.
|
||||
Near publication supplies buildings separately; far entries have no buildings.
|
||||
3. Forward the terrain metadata through both PublishAsFar conversions and all
|
||||
normal load/promotion routes. No extra DAT or collision/static read for Far.
|
||||
normal load/promotion routes, including LandblockStreamer's unconditional
|
||||
LoadFar near-payload stripping. No extra DAT or collision/static read for Far.
|
||||
Respect the retained publication receipt and existing retry/budget semantics.
|
||||
4. Near-to-far retirement clears building references but retains the terrain
|
||||
entry/bounds. Full terrain removal removes its landscape entry. Repeated
|
||||
|
|
@ -50,7 +95,8 @@ do not claim it retired because distant terrain now draws.
|
|||
|
||||
- Far build keeps EnvCells null and performs only its existing heightmap read,
|
||||
but carries exact non-flat authored vertical bounds.
|
||||
- Production publisher + real landscape/walk product produces a nonempty
|
||||
- Actual LoadFar worker -> DrainCompletions -> production publisher + real
|
||||
landscape/walk product preserves the bounds and produces a nonempty
|
||||
terrain turn for an in-view far-only block beyond near radius4, with no
|
||||
building/object population. The old missing-registration implementation must
|
||||
fail this assertion; a renderer-slot count alone is insufficient.
|
||||
|
|
@ -64,11 +110,17 @@ do not claim it retired because distant terrain now draws.
|
|||
## Ownership, safety and handoff
|
||||
|
||||
One OpenAI implementer owns only LandblockBuild.cs, LandblockBuildFactory.cs,
|
||||
LandblockRenderPublisher.cs, LandblockPresentationPipeline.cs,
|
||||
LandblockRenderPublisher.cs, LandblockPresentationPipeline.cs, LandblockStreamer.cs,
|
||||
Rendering/Walk/WalkLandscapeAssembler.cs and their directly affected tests.
|
||||
Small related declaration/comment edits may be proposed, not broadened silently.
|
||||
Lead owns issue/ledger/architecture/register and this contract. No shader/PAK edit.
|
||||
|
||||
Scope amendment: the implementer found that the real LoadFar worker reconstructs
|
||||
LandblockBuild while stripping near payload, losing separately carried terrain
|
||||
bounds. The lead authorized only that metadata forwarding in the sixth production
|
||||
file and an actual worker-to-walk regression. This implements requirement 3;
|
||||
no scheduling, loading policy or new retail deviation is authorized.
|
||||
|
||||
**Retail PID25988 is owner-held: DO NOT TOUCH.** No close, input, debugger attach,
|
||||
build, tests or launch while either client is running. Code edits may proceed.
|
||||
Do not invoke Claude or start review agents. Return the uncommitted scoped diff
|
||||
|
|
@ -76,3 +128,47 @@ and exact unrun test commands; implementation is NOT yet built or tested.
|
|||
After the owner closes retail, lead does the green Release build and narrow
|
||||
regression run, launches one manual client, and leaves review until after the
|
||||
owner's test. No main merge and no G4 acceptance are implied.
|
||||
|
||||
## Lead static retail check — 2026-09-06
|
||||
|
||||
Named pseudo-C identifies the exact helper as
|
||||
`CLandBlock::get_land_limits0052F1D0`, not calc_lighting. The existing local
|
||||
Ghidra endpoint8081 is offline; no new tool or retail process was launched.
|
||||
Instead the lead read the paired file `C:\Turbine\Asheron's Call\acclient.exe`
|
||||
as data: timestamp2013-09-06, PDB GUID9e847e2f-777c-4bd9-886c-22256bb87f32,
|
||||
age1, SHA256006ffeadc5d679c871497112a5bd1f87714d0e273e2166bae5052dde369297b1.
|
||||
The separately named acclient_codex_oracle.exe is2015 and was excluded.
|
||||
|
||||
Direct PE byte inspection agrees with the named source:
|
||||
|
||||
- 0050634F onward loads mid_width from this+4, squares it, and walks the
|
||||
complete block_draw_list backwards. Non-null and block+FC in-view tests
|
||||
precede the virtual DrawBlock call. There is no building-presence gate.
|
||||
- 0052F281 onward loads the maximum byte's height-table value, adds
|
||||
float[007C8F1C]=200.0 (bytes00004843) and stores this+E0; the minimum-byte
|
||||
value subtracts float[007928B0]=1.0 (bytes0000803F), stored at this+E4.
|
||||
The existing compute helper's formula is therefore preserved, not replaced
|
||||
by the GPU AABB's different margins.
|
||||
|
||||
This is factual input verification for the repair, not the postponed code
|
||||
review or a test PASS. Retail remained open and untouched throughout.
|
||||
|
||||
## Candidate handoff — 2026-09-06
|
||||
|
||||
The implementer returned the six production files plus
|
||||
LandblockBuildFactoryTests.cs and LandblockConcretePresentationPipelineTests.cs
|
||||
uncommitted. The candidate and regression tests are written; ownership is back
|
||||
with the lead. No implementation agent remains active on this repair.
|
||||
Only whitespace validation (`git diff --check`) ran. The candidate is
|
||||
**UNBUILT, UNTESTED and UNREVIEWED**; the previous eea83ac88 binary is unchanged.
|
||||
Retail PID25988 remains owner-held, ACDream is absent, ACE UDP9000/PID2296 is up.
|
||||
No build, test, client launch, debugger attach or client close was performed.
|
||||
|
||||
When both clients are absent, build the App test project in Release (which
|
||||
builds its App dependencies) and run the narrow lane below before owner launch.
|
||||
The test run must not be reported as a visual gate or the deferred review.
|
||||
|
||||
```powershell
|
||||
dotnet build tests/AcDream.App.Tests/AcDream.App.Tests.csproj -c Release --no-restore -m:1 -p:UseSharedCompilation=false
|
||||
dotnet test tests/AcDream.App.Tests/AcDream.App.Tests.csproj -c Release --no-build --no-restore --filter "FullyQualifiedName~LandblockBuildFactoryTests|FullyQualifiedName~LandblockConcretePresentationPipelineTests|FullyQualifiedName~LandblockPresentationPipelineTests|FullyQualifiedName~LandblockRenderPublisherTests|FullyQualifiedName~WalkLandscapeAssemblerTests|FullyQualifiedName~RetailFrameWalkTests|FullyQualifiedName~WalkLandCellOrderTests" --logger "trx;LogFileName=483-terrain-regression.trx" --results-directory artifacts/483-far-terrain
|
||||
```
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
# #484 — distant mountain silhouette flicker
|
||||
|
||||
**OPEN — OWNER-DEFERRED, 2026-09-06.** The owner explicitly requested filing
|
||||
this issue and closing/merging the campaign. Investigation stops here; exact
|
||||
pose and consecutive-frame reproduction are future issue work, not a pending
|
||||
campaign gate. Cause remains unconfirmed. No production fix or PASS claimed.
|
||||
|
||||
2026-09-06; owner report on the uncommitted #483 candidate based on e0ba3e7f2.
|
||||
Owner says flicker continues with character/camera still; turning reveals more
|
||||
mountain at affected spots. User image:
|
||||
`C:/Users/erikn/AppData/Local/Temp/codex-clipboard-d6976e08-527f-47b9-8f00-79429065ea13.png`.
|
||||
A still does not establish the temporal mechanism. No fix or visual PASS yet.
|
||||
|
||||
## Read-only findings
|
||||
|
||||
- #483's launched App hash remains
|
||||
869BA14CB2C610E006C80BDFFCBD75629339A3486B8B98D7708B23050700FF34;
|
||||
PID17856, logs/owner-g4-20260906-r2/. Retail was untouched.
|
||||
- `TerrainModernRenderer.AppendCellIndexRuns` covers all 384 mesh indices for
|
||||
side1/cell0; other LOD cell grids expand disjoint complete row ranges. This
|
||||
is draw granularity, not a changing geometry LOD. No obvious stale terrain
|
||||
list accumulation found in driver/renderer clear paths.
|
||||
- Terrain indirect commands use a per-frame upload-ring allocation. Fog only
|
||||
blends colour; the terrain shader does not discard fogged fragments.
|
||||
- CPU walk uses CY/near and view-edge planes, while the world camera projection
|
||||
has .1 m near / 5000 m far. A radius25 square can reach roughly 6.8 km
|
||||
diagonally. This permits hardware clipping of CPU-admitted blocks, but that
|
||||
is NOT sufficient evidence of this fault or justification for extending far.
|
||||
- Named retail also uses finite far clipping: zfar0081EC88 defaults to4000;
|
||||
PrimD3DRender::SetFOVInternal0059AB40 builds the projection from znear/zfar;
|
||||
SetDefaultD3DStates sets clipping state0x88 to1 at005A3B30. Terrain submits
|
||||
XYZ through DrawPrimitiveUP, not a projected-Z clamp/far bypass. Only sky
|
||||
temporarily multiplies zfar by4, then restores it.
|
||||
- Lead verified those three load-bearing facts from the matching 2013 PE as
|
||||
file data (no attach): SHA256
|
||||
006ffeadc5d679c871497112a5bd1f87714d0e273e2166bae5052dde369297b1.
|
||||
VA0081EC88 bytes00007A45 encode4000; 0059AB40 body loads globals81EC88/81EC84
|
||||
before the perspective call; 005A3B32 has push1/push88 before SetRenderState.
|
||||
The far-clipping hypothesis remains unproven; no projection change was made.
|
||||
|
||||
## Next discriminating observation
|
||||
|
||||
Owner was asked to leave the client at an affected viewpoint and provide /loc.
|
||||
The one window observation instead caught arrival in Neftet, not the reported
|
||||
mountain silhouette. No input was sent to either client. Need that pose before
|
||||
capturing consecutive stable frames and camera/terrain admission/clip facts.
|
||||
Distinguish disappearing block/triangle coverage from changing shaded pixels;
|
||||
then write the bounded fix contract, add a discriminating regression, verify
|
||||
and gate the actual repair. Do not turn an unproven far-plane theory into a fix.
|
||||
No new code, build, test, client close/launch, review, or G4 acceptance this turn.
|
||||
|
||||
Current safety: retail remaining open does not block build/test/launch (explicit
|
||||
owner override). Leave retail untouched; do not overwrite a running ACDream.
|
||||
|
|
@ -1,11 +1,14 @@
|
|||
# G4 owner checklist — final candidate, 2026-09-05
|
||||
# G4 owner checklist — retained matrix; closeout 2026-09-06
|
||||
|
||||
Status: **NOT RUN / NOT ACCEPTED**. This is the remaining owner session,
|
||||
not another implementation or review round. Binding scope is the campaign
|
||||
plan's S5 gate and section10 scene matrix. The automatic checks do not replace
|
||||
the owner's judgment. Do not merge or mark the campaign closed from this card.
|
||||
Status: **OWNER-DIRECTED CLOSEOUT ACCEPTED WITH CARRIED ISSUES.** On 2026-09-06
|
||||
the owner directed deferral of #484, campaign closeout, commit, merge to main
|
||||
and push to Gitea. This supersedes waiting for the remaining matrix session;
|
||||
it does not assert individual PASS results for unreported rows or erase FAILs.
|
||||
See `2026-09-06-campaign-closeout.md` for the merge-gate disposition and exact
|
||||
final #483 candidate. The earlier checklist and evidence below are retained
|
||||
history, not a new launch request.
|
||||
|
||||
## Candidate and launch
|
||||
## Historical candidate and launch (2026-09-05)
|
||||
|
||||
Use the existing Release binaries built at
|
||||
`eea83ac884d0b0fd74d86a17a16d7d5d93f64d94`; documentation checkpoint
|
||||
|
|
@ -17,7 +20,9 @@ Exact App/Core/package hashes and green build evidence are in
|
|||
Before launch, recheck binary/package hashes, both client processes and ACE
|
||||
UDP9000; record the launch commit, flags, profile, process and log directory.
|
||||
Keep the saved High/MSAA4, near4/far25 profile for the normal candidate run.
|
||||
No rebuild beside either client; no code change after the accepted binary.
|
||||
The original no-rebuild-beside-either-client rule was superseded on 2026-09-06:
|
||||
retail stays untouched but does not block building. Do not overwrite running
|
||||
ACDream binaries or launch duplicates.
|
||||
Owner session has no automatic route or automatic close. A retail comparator
|
||||
is needed for the two-client row and known cathedral slab comparison; launch
|
||||
each client in its own command. Close owned clients gracefully when agreed.
|
||||
|
|
@ -42,7 +47,8 @@ each client in its own command. Close owned clients gracefully when agreed.
|
|||
## Owner session
|
||||
|
||||
For every row retain PASS/FAIL, actual `/loc`, symptom if any, and PNG/log
|
||||
paths. All rows below remain **PENDING** on this final binary. The starting
|
||||
paths. Rows without a reported individual verdict remain **UNREPORTED**, not
|
||||
new PASS results; waiting for them was superseded by owner closeout. The starting
|
||||
locations are navigation aids, not a substitute for movement or camera work.
|
||||
|
||||
| Row | Check | Start / navigation |
|
||||
|
|
@ -60,13 +66,14 @@ network logout or a client-authored code0 does not override the OS exit.
|
|||
Do not retry just to replace a failed record. The lead reads local crash
|
||||
reports/Windows evidence without changing registry, driver or dump settings.
|
||||
|
||||
## Acceptance and remaining closeout
|
||||
## Historical acceptance requirements and final disposition
|
||||
|
||||
Owner PASS must identify the tested rows and any explicit carried exception.
|
||||
The historical acceptance of#422 in Campaign VM is not automatically a new
|
||||
OVERHAUL acceptance. A good visual session does not prove the original AMD
|
||||
reset's initiating cause, remove the installed-data failures, or convert
|
||||
the recorded shutdown failure to PASS. Their disposition remains explicit.
|
||||
the recorded shutdown failure to PASS. Their failures remain explicit in the
|
||||
closeout report.
|
||||
|
||||
FPS/C2 performance work is owner-deferred. Retail's known cathedral leak is
|
||||
unchanged; its proposed post-campaign improvement is not part of this gate.
|
||||
|
|
@ -74,7 +81,7 @@ unchanged; its proposed post-campaign improvement is not part of this gate.
|
|||
After the owner results, reconcile the shipping documentation before closure:
|
||||
architecture, WorldBuilder inventory, divergence register, launch options,
|
||||
FW ledger (superseded, not deleted), roadmap/milestones and campaign memory.
|
||||
Keep the existing failure records. Only when G4 and that closeout actually
|
||||
agree with the code can the campaign be marked CLOSED — USER ACCEPTED and
|
||||
the authorized merge considered. Do not rebuild the accepted product for
|
||||
documentation-only changes.
|
||||
Keep the existing failure records. The owner's 2026-09-06 closeout instruction
|
||||
now authorizes integration with carried issues, rather than requiring another
|
||||
matrix session. Documentation records that disposition without inventing
|
||||
per-row passes. Do not rebuild the accepted product for documentation-only changes.
|
||||
|
|
|
|||
|
|
@ -75,8 +75,19 @@ public sealed class WalkLandscapeAssembler
|
|||
RefreshSlotIfWindowed(bx, by);
|
||||
}
|
||||
|
||||
/// <summary>Near-tier retirement retains terrain and its authored bounds.
|
||||
/// A late building cleanup must not recreate a fully retired block.</summary>
|
||||
public void ClearBuildings(uint landblockId)
|
||||
{
|
||||
(int bx, int by) = BlockCoords(landblockId);
|
||||
if (!_blocks.TryGetValue((bx, by), out BlockData? data))
|
||||
return;
|
||||
data.Buildings = Array.Empty<WalkBuildingFactory.Entry>();
|
||||
RefreshSlotIfWindowed(bx, by);
|
||||
}
|
||||
|
||||
/// <summary>Landblock retirement (<c>LandblockRenderPublisher
|
||||
/// .RemoveBuildingRegistry</c>): drop this landblock's data. Safe to call
|
||||
/// .RemoveTerrain</c>): drop this landblock's data. Safe to call
|
||||
/// on a landblock that never published (no-op).</summary>
|
||||
public void RetireLandblock(uint landblockId)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ using AcDream.Core.World;
|
|||
|
||||
namespace AcDream.App.Streaming;
|
||||
|
||||
/// <summary>Authored terrain z-slab, independent of near-tier cell/building data.</summary>
|
||||
public readonly record struct LandblockTerrainBounds(float MaxZ, float MinZ);
|
||||
|
||||
/// <summary>
|
||||
/// Complete CPU-side output of one streaming job. The worker owns this object
|
||||
/// until it posts the corresponding completion; the render thread then applies
|
||||
|
|
@ -12,7 +15,8 @@ public sealed record LandblockBuild(
|
|||
LoadedLandblock Landblock,
|
||||
EnvCellLandblockBuild? EnvCells = null,
|
||||
LandblockBuildOrigin Origin = default,
|
||||
LandblockCollisionBuild? Collisions = null)
|
||||
LandblockCollisionBuild? Collisions = null,
|
||||
LandblockTerrainBounds TerrainBounds = default)
|
||||
{
|
||||
public uint LandblockId => Landblock.LandblockId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,13 +132,15 @@ public sealed class LandblockBuildFactory
|
|||
{
|
||||
var heightmapOnly = _dats.Get<DatReaderWriter.DBObjs.LandBlock>(landblockId);
|
||||
if (heightmapOnly is null) return null;
|
||||
(float maxZ, float minZ) = ComputeWalkZSlab(heightmapOnly.Height);
|
||||
return new AcDream.App.Streaming.LandblockBuild(
|
||||
new AcDream.Core.World.LoadedLandblock(
|
||||
landblockId,
|
||||
heightmapOnly,
|
||||
System.Array.Empty<AcDream.Core.World.WorldEntity>(),
|
||||
AcDream.Core.World.PhysicsDatBundle.Empty),
|
||||
Origin: request.Origin); // far tier: no cells/buildings/entities
|
||||
Origin: request.Origin,
|
||||
TerrainBounds: new(maxZ, minZ)); // far tier: no cells/buildings/entities
|
||||
}
|
||||
|
||||
var baseLoaded = AcDream.Core.World.LandblockLoader.Load(_dats, landblockId);
|
||||
|
|
@ -179,7 +181,7 @@ public sealed class LandblockBuildFactory
|
|||
_heightTable));
|
||||
var envCellBuild = new AcDream.App.Rendering.Wb.EnvCellLandblockBuildBuilder(landblockId);
|
||||
// Campaign FW3.1: the walk landscape's per-block z-slab
|
||||
// (CLandBlock::calc_lighting-adjacent unpack @0x0052f1d0). Every
|
||||
// (CLandBlock::get_land_limits @0x0052f1d0). Every
|
||||
// near-tier landblock has outdoor terrain heights regardless of
|
||||
// whether it has interior cells or buildings, so this is
|
||||
// unconditional — unlike WalkBuildings (added below, inside
|
||||
|
|
@ -208,7 +210,8 @@ public sealed class LandblockBuildFactory
|
|||
merged,
|
||||
physicsDats),
|
||||
completedEnvCells,
|
||||
request.Origin);
|
||||
request.Origin,
|
||||
TerrainBounds: new(walkMaxZ, walkMinZ));
|
||||
}
|
||||
/// <summary>
|
||||
/// Phase A.1 Task 8: generate scenery (trees, rocks, bushes) for a single
|
||||
|
|
@ -673,7 +676,7 @@ public sealed class LandblockBuildFactory
|
|||
|
||||
/// <summary>Campaign FW3.1: retail's per-block z-slab
|
||||
/// (<c>WalkLandscapeDatBuilder</c>'s port target —
|
||||
/// <c>CLandBlock::calc_lighting</c>-adjacent unpack @0x0052f1d0):
|
||||
/// <c>CLandBlock::get_land_limits</c> @0x0052f1d0):
|
||||
/// <c>max_zval = heightTable[maxByte] + 200</c>,
|
||||
/// <c>min_zval = heightTable[minByte] - 1</c>, over the landblock's own
|
||||
/// 81-byte heightmap. Uses <see cref="_heightTable"/> — already a
|
||||
|
|
|
|||
|
|
@ -479,18 +479,18 @@ public sealed class LandblockPresentationPipeline
|
|||
completed.Heightmap,
|
||||
Array.Empty<WorldEntity>(),
|
||||
PhysicsDatBundle.Empty);
|
||||
LandblockBuild farBuild = new(
|
||||
farLandblock,
|
||||
Origin: completedBuild.Origin,
|
||||
TerrainBounds: completedBuild.TerrainBounds);
|
||||
transaction = new PublicationTransaction
|
||||
{
|
||||
Kind = PublicationKind.Far,
|
||||
Build = new LandblockBuild(
|
||||
farLandblock,
|
||||
Origin: completedBuild.Origin),
|
||||
Build = farBuild,
|
||||
MeshData = meshData,
|
||||
LandblockId = farLandblock.LandblockId,
|
||||
Cost = LandblockStreamResultCost.Estimate(
|
||||
new LandblockBuild(
|
||||
farLandblock,
|
||||
Origin: completedBuild.Origin),
|
||||
farBuild,
|
||||
meshData),
|
||||
Tier = LandblockStreamTier.Far,
|
||||
Timing = PublicationTimingProbe.CreateTimings(),
|
||||
|
|
@ -534,7 +534,8 @@ public sealed class LandblockPresentationPipeline
|
|||
PhysicsDatBundle.Empty);
|
||||
LandblockBuild farBuild = new(
|
||||
farLandblock,
|
||||
Origin: completedBuild.Origin);
|
||||
Origin: completedBuild.Origin,
|
||||
TerrainBounds: completedBuild.TerrainBounds);
|
||||
transaction = new PublicationTransaction
|
||||
{
|
||||
Kind = PublicationKind.Far,
|
||||
|
|
|
|||
|
|
@ -103,15 +103,9 @@ public sealed class LandblockRenderPublisher
|
|||
private readonly Action<EnvCellLandblockBuild>? _prepareEnvCells;
|
||||
private readonly Action<uint>? _removeEnvCells;
|
||||
private readonly Dictionary<uint, BuildingRegistry> _buildingRegistries = new();
|
||||
// Campaign FW3.1: the walk's production world-data siblings of
|
||||
// _buildingRegistries. Owned here (not injected) exactly like
|
||||
// _buildingRegistries — no caller constructs a LandblockRenderPublisher
|
||||
// with pre-existing walk state. Committed/retired at the same points as
|
||||
// the building registry (see AdvanceCompleteOne / RemoveBuildingRegistry
|
||||
// below) because both come from the same landblock's BuildingInfo array
|
||||
// at the same commit. No frame reads these yet (FW3.2 wires the walk
|
||||
// into the render loop) — publication happens now so FW3.1's
|
||||
// conformance gate exercises the production commit path.
|
||||
// The frame walk's sole terrain/building owners. Both publish in the
|
||||
// retained render suffix; near-layer retirement clears only buildings,
|
||||
// while full terrain retirement removes the landscape entry as well.
|
||||
private readonly WalkBuildingRegistry _walkBuildingRegistry = new();
|
||||
private readonly WalkLandscapeAssembler _walkLandscape = new();
|
||||
|
||||
|
|
@ -360,21 +354,19 @@ public sealed class LandblockRenderPublisher
|
|||
_buildingRegistries[registryKey] =
|
||||
completedBuildings.Registry;
|
||||
}
|
||||
// Campaign FW3.1: publish this landblock's walk world data in
|
||||
// the same step — build.EnvCells carries WalkBuildings/WalkMaxZ
|
||||
// /WalkMinZ (computed worker-side by LandblockBuildFactory) for
|
||||
// every near-tier build, even one with zero interior cells
|
||||
// (the z-slab is unconditional; WalkBuildings is naturally empty
|
||||
// when LandBlockInfo has none).
|
||||
// Terrain exists at both tiers; only near builds supply buildings.
|
||||
// Keep both publications in this retained receipt's existing step.
|
||||
if (build.EnvCells is { } walkEnvCells)
|
||||
{
|
||||
_walkBuildingRegistry.Publish(landblockId, walkEnvCells.WalkBuildings);
|
||||
_walkLandscape.PublishLandblock(
|
||||
landblockId,
|
||||
walkEnvCells.WalkMaxZ,
|
||||
walkEnvCells.WalkMinZ,
|
||||
walkEnvCells.WalkBuildings);
|
||||
}
|
||||
else
|
||||
_walkBuildingRegistry.Retire(landblockId);
|
||||
_walkLandscape.PublishLandblock(
|
||||
landblockId,
|
||||
build.TerrainBounds.MaxZ,
|
||||
build.TerrainBounds.MinZ,
|
||||
build.EnvCells is { } cells
|
||||
? cells.WalkBuildings
|
||||
: Array.Empty<WalkBuildingFactory.Entry>());
|
||||
publication.BuildingRegistryCommitted = true;
|
||||
}
|
||||
else if (publication.EnvCellPublication is { } envCellPublication
|
||||
|
|
@ -421,6 +413,7 @@ public sealed class LandblockRenderPublisher
|
|||
public void RemoveTerrain(uint landblockId)
|
||||
{
|
||||
_removeTerrain(landblockId);
|
||||
_walkLandscape.RetireLandblock(landblockId);
|
||||
_terrainRemovalCount++;
|
||||
}
|
||||
|
||||
|
|
@ -433,14 +426,9 @@ public sealed class LandblockRenderPublisher
|
|||
public void RemoveBuildingRegistry(uint landblockId)
|
||||
{
|
||||
_buildingRegistries.Remove(landblockId & 0xFFFF0000u);
|
||||
// Campaign FW3.1: retire the walk's siblings at the SAME retirement
|
||||
// stage — they were committed together above, so they retire
|
||||
// together (no new LandblockRetirementStage; folding into the
|
||||
// existing BuildingRegistry stage keeps the retirement ticket state
|
||||
// machine unchanged, which is the minimal/additive choice for a
|
||||
// slice that does no frame wiring yet).
|
||||
// Demotion retires buildings, not the retained far-tier terrain.
|
||||
_walkBuildingRegistry.Retire(landblockId);
|
||||
_walkLandscape.RetireLandblock(landblockId);
|
||||
_walkLandscape.ClearBuildings(landblockId);
|
||||
_buildingRegistryRemovalCount++;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -615,7 +615,10 @@ public sealed class LandblockStreamer : IDisposable, ILandblockCompletionSource
|
|||
lb.Heightmap,
|
||||
System.Array.Empty<AcDream.Core.World.WorldEntity>(),
|
||||
PhysicsDatBundle.Empty);
|
||||
build = new LandblockBuild(lb, Origin: build.Origin);
|
||||
build = new LandblockBuild(
|
||||
lb,
|
||||
Origin: build.Origin,
|
||||
TerrainBounds: build.TerrainBounds);
|
||||
}
|
||||
PublishResult(new LandblockStreamResult.Loaded(
|
||||
load.LandblockId, tier, build, mesh, load.Generation));
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ public sealed class LandblockBuildFactoryTests
|
|||
result.EnvCells);
|
||||
Assert.Equal(240f, envCells.WalkMaxZ); // heightTable[200] + 200
|
||||
Assert.Equal(4f, envCells.WalkMinZ); // heightTable[10] - 1
|
||||
Assert.Equal(new LandblockTerrainBounds(240f, 4f), result.TerrainBounds);
|
||||
AcDream.App.Rendering.Walk.WalkBuildingFactory.Entry buildingEntry =
|
||||
Assert.Single(envCells.WalkBuildings);
|
||||
// origin (12,12) -> cellX=cellY=0 -> low word 0*8+0+1 = 1.
|
||||
|
|
@ -189,20 +190,28 @@ public sealed class LandblockBuildFactoryTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildFar_NeverPopulatesWalkDataBecauseEnvCellsIsNull()
|
||||
public void BuildFar_CarriesNonFlatAuthoredBoundsWithoutNearDataOrExtraReads()
|
||||
{
|
||||
// Documents the known FW3.1 scope gap: far-tier (LoadFar) landblocks
|
||||
// carry no EnvCellLandblockBuild transaction at all (terrain-only),
|
||||
// so their z-slab/buildings never reach WalkLandscapeAssembler until
|
||||
// a follow-up wires the far-tier path too.
|
||||
var dat = CreateDat(out RecordingDatProxy proxy);
|
||||
proxy.Add(LandblockId, new LandBlock { Id = LandblockId });
|
||||
var factory = Factory(dat, new object());
|
||||
var heights = Enumerable.Repeat((byte)10, 81).ToArray();
|
||||
heights[80] = 200;
|
||||
proxy.Add(LandblockId, new LandBlock { Id = LandblockId, Height = heights });
|
||||
var heightTable = new float[256];
|
||||
heightTable[10] = 5.25f;
|
||||
heightTable[200] = 40.5f;
|
||||
var source = new TestPreparedCollisionSource(PreparedAssetReadStatus.Missing);
|
||||
var factory = new LandblockBuildFactory(dat, source, new object(), heightTable);
|
||||
|
||||
LandblockBuild? result = factory.Build(Request(LandblockStreamJobKind.LoadFar));
|
||||
|
||||
Assert.NotNull(result);
|
||||
Assert.Null(result.EnvCells);
|
||||
Assert.Equal(new LandblockTerrainBounds(240.5f, 4.25f), result.TerrainBounds);
|
||||
Assert.Empty(result.Landblock.Entities);
|
||||
Assert.Same(PhysicsDatBundle.Empty, result.Landblock.PhysicsDats);
|
||||
Assert.Null(result.Collisions);
|
||||
Assert.Equal(0, source.Reads);
|
||||
Assert.Equal([(typeof(LandBlock), LandblockId)], proxy.Reads);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System.Collections.Immutable;
|
||||
using System.Numerics;
|
||||
using AcDream.App.Rendering;
|
||||
using AcDream.App.Rendering.Walk;
|
||||
using AcDream.App.Rendering.Wb;
|
||||
using AcDream.App.Rendering.Vfx;
|
||||
using AcDream.App.Streaming;
|
||||
|
|
@ -527,6 +528,223 @@ public sealed class LandblockConcretePresentationPipelineTests
|
|||
Assert.Equal(1, fixture.Render.Diagnostics.EnvCellRemovalCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FarLoaded_WorkerAndRealWalkPreserveTerrainBeyondNearRadiusWithoutNearPopulation()
|
||||
{
|
||||
ConcreteFixture fixture = Fixture(new List<string>());
|
||||
LandblockBuild far = Build() with
|
||||
{
|
||||
EnvCells = null,
|
||||
Origin = new LandblockBuildOrigin(0xA3, 0xB4),
|
||||
TerrainBounds = new(240.5f, 4.25f),
|
||||
};
|
||||
|
||||
using var streamer = LandblockStreamer.CreateForRequests(
|
||||
loadLandblock: _ => far,
|
||||
buildMeshOrNull: (_, _) => EmptyMesh(),
|
||||
workerCount: 1);
|
||||
streamer.EnqueueLoad(new LandblockBuildRequest(
|
||||
LandblockId, LandblockStreamJobKind.LoadFar, Generation: 483, far.Origin));
|
||||
streamer.Start();
|
||||
LandblockStreamResult? completion = null;
|
||||
for (int attempt = 0; attempt < 200 && completion is null; attempt++)
|
||||
{
|
||||
IReadOnlyList<LandblockStreamResult> drained = streamer.DrainCompletions();
|
||||
if (drained.Count > 0)
|
||||
completion = Assert.Single(drained);
|
||||
else
|
||||
await Task.Delay(10);
|
||||
}
|
||||
var loaded = Assert.IsType<LandblockStreamResult.Loaded>(completion);
|
||||
Assert.Equal(483ul, loaded.Generation);
|
||||
Assert.Equal(far.Origin, loaded.Build.Origin);
|
||||
Assert.Equal(far.TerrainBounds, loaded.Build.TerrainBounds);
|
||||
Assert.Null(loaded.Build.EnvCells);
|
||||
Assert.Same(PhysicsDatBundle.Empty, loaded.Landblock.PhysicsDats);
|
||||
|
||||
Pipeline(fixture).PublishLoaded(loaded);
|
||||
|
||||
AssertFarTerrain(fixture);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public void AcceptedNearAsFar_BothOverloadsPreserveTerrainAndStripNearPopulation(bool metered)
|
||||
{
|
||||
var calls = new List<string>();
|
||||
ConcreteFixture fixture = Fixture(calls);
|
||||
var pipeline = Pipeline(fixture);
|
||||
LandblockBuild near = BuildWithWalkBuilding() with
|
||||
{
|
||||
Origin = new LandblockBuildOrigin(0xA3, 0xB4),
|
||||
};
|
||||
LandblockStreamResult.Loaded accepted = Result(near);
|
||||
|
||||
if (metered)
|
||||
{
|
||||
// One mutation per frame forces the real retained publication path.
|
||||
var budget = new StreamingWorkBudget(
|
||||
TimeSpan.FromSeconds(1),
|
||||
maxCompletionAdmissions: 64,
|
||||
maxAdoptedCpuBytes: 1_000_000,
|
||||
maxEntityOperations: 1,
|
||||
maxGpuUploadBytes: 1_000_000,
|
||||
maxGlRetireOperations: 64,
|
||||
destinationReserveFraction: 0.75f);
|
||||
LandblockPublicationAdvance advance = default;
|
||||
for (int frame = 0; frame < 64 && !advance.Completed; frame++)
|
||||
{
|
||||
var meter = new StreamingWorkMeter(budget);
|
||||
advance = pipeline.PublishAsFar(
|
||||
accepted, near, accepted.MeshData, meter, ensureProgress: false);
|
||||
meter.FinishFrame();
|
||||
Assert.True(meter.Snapshot.Used.EntityOperations <= 1);
|
||||
}
|
||||
Assert.True(advance.Completed);
|
||||
}
|
||||
else
|
||||
{
|
||||
pipeline.PublishAsFar(accepted, near, accepted.MeshData);
|
||||
}
|
||||
|
||||
Assert.False(pipeline.HasPendingPublication(accepted));
|
||||
Assert.Equal(1, calls.Count(call => call == "terrain"));
|
||||
Assert.Equal(1, fixture.Render.Diagnostics.CompleteCount);
|
||||
AssertFarTerrain(fixture);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConcreteRetirement_DemotionKeepsTerrain_PromotionAndRevisitRestoreBuildings()
|
||||
{
|
||||
ConcreteFixture fixture = Fixture(new List<string>());
|
||||
var pipeline = Pipeline(fixture);
|
||||
LandblockBuild near = BuildWithWalkBuilding();
|
||||
WalkBuilding building = Assert.Single(near.EnvCells!.WalkBuildings).Building;
|
||||
|
||||
pipeline.PublishLoaded(Result(near));
|
||||
AssertNearTerrain(fixture, building);
|
||||
|
||||
pipeline.BeginNearLayerRetirement(LandblockId);
|
||||
pipeline.BeginNearLayerRetirement(LandblockId);
|
||||
Assert.Equal(0, pipeline.PendingRetirementCount);
|
||||
Assert.True(fixture.State.IsLoaded(LandblockId));
|
||||
Assert.False(fixture.State.IsNearTier(LandblockId));
|
||||
Assert.Equal(0, fixture.Render.Diagnostics.TerrainRemovalCount);
|
||||
fixture.Render.RemoveBuildingRegistry(LandblockId); // repeated near cleanup
|
||||
AssertTerrainBounds(fixture.Render.WalkLandscape);
|
||||
Assert.NotEmpty(DrawTerrain(fixture, farViewer: false).TerrainTurns);
|
||||
Assert.Empty(fixture.Render.WalkBuildings.GetBuildings(LandblockId));
|
||||
Assert.False(fixture.Render.WalkBuildings.TryGetEntry(building, out _));
|
||||
Assert.All(PublishedBlock(fixture.Render.WalkLandscape).CellBuildings,
|
||||
value => Assert.Null(value));
|
||||
|
||||
pipeline.PublishPromoted(
|
||||
new LandblockStreamResult.Promoted(LandblockId, near, EmptyMesh()),
|
||||
mergeIntoExistingLandblock: true);
|
||||
AssertNearTerrain(fixture, building);
|
||||
|
||||
pipeline.BeginFullRetirement(LandblockId);
|
||||
pipeline.BeginFullRetirement(LandblockId);
|
||||
Assert.Equal(0, pipeline.PendingRetirementCount);
|
||||
Assert.False(fixture.State.IsLoaded(LandblockId));
|
||||
fixture.Render.RemoveTerrain(LandblockId); // duplicate full cleanup
|
||||
fixture.Render.RemoveBuildingRegistry(LandblockId); // late stage after terrain removal
|
||||
Assert.Empty(DrawTerrain(fixture, farViewer: false).TerrainTurns);
|
||||
Assert.All(fixture.Render.WalkLandscape.Landscape.Blocks, value => Assert.Null(value));
|
||||
Assert.Empty(fixture.Render.WalkBuildings.GetBuildings(LandblockId));
|
||||
|
||||
pipeline.PublishLoaded(Result(near));
|
||||
AssertNearTerrain(fixture, building);
|
||||
}
|
||||
|
||||
private static LandblockBuild BuildWithWalkBuilding()
|
||||
{
|
||||
var building = new WalkBuilding { PositionCellId = 0xA9B40009u };
|
||||
var entry = new WalkBuildingFactory.Entry(
|
||||
building, Matrix4x4.Identity, Matrix4x4.Identity);
|
||||
LandblockBuild build = Build(Entity(0x80A9B401u));
|
||||
return build with
|
||||
{
|
||||
EnvCells = new EnvCellLandblockBuild(
|
||||
LandblockId, [], [], [entry], walkMaxZ: 240.5f, walkMinZ: 4.25f),
|
||||
TerrainBounds = new(240.5f, 4.25f),
|
||||
};
|
||||
}
|
||||
|
||||
private static void AssertFarTerrain(ConcreteFixture fixture)
|
||||
{
|
||||
TerrainTurnRecorder turns = DrawTerrain(fixture, farViewer: true);
|
||||
// Ring six uses one coarse terrain cell. This fails if the far block
|
||||
// has a mesh/state entry but is missing from the sole landscape walk.
|
||||
Assert.Equal((LandblockId & 0xFFFF0000u, 1, 0), Assert.Single(turns.TerrainTurns));
|
||||
AssertTerrainBounds(fixture.Render.WalkLandscape);
|
||||
Assert.Empty(turns.Buildings);
|
||||
Assert.Empty(fixture.Render.WalkBuildings.GetBuildings(LandblockId));
|
||||
Assert.All(PublishedBlock(fixture.Render.WalkLandscape).CellBuildings,
|
||||
value => Assert.Null(value));
|
||||
Assert.True(fixture.State.IsLoaded(LandblockId));
|
||||
Assert.False(fixture.State.IsNearTier(LandblockId));
|
||||
Assert.Empty(fixture.State.Entities);
|
||||
Assert.Empty(fixture.World.Entities);
|
||||
}
|
||||
|
||||
private static void AssertNearTerrain(ConcreteFixture fixture, WalkBuilding building)
|
||||
{
|
||||
TerrainTurnRecorder turns = DrawTerrain(fixture, farViewer: false);
|
||||
Assert.NotEmpty(turns.TerrainTurns);
|
||||
Assert.Contains(building.PositionCellId, turns.Buildings);
|
||||
AssertTerrainBounds(fixture.Render.WalkLandscape);
|
||||
Assert.Same(building, PublishedBlock(fixture.Render.WalkLandscape).CellBuildings[8]);
|
||||
Assert.Same(building, Assert.Single(
|
||||
fixture.Render.WalkBuildings.GetBuildings(LandblockId)).Building);
|
||||
Assert.True(fixture.State.IsNearTier(LandblockId));
|
||||
}
|
||||
|
||||
private static void AssertTerrainBounds(WalkLandscapeAssembler assembler)
|
||||
{
|
||||
WalkLandBlock block = PublishedBlock(assembler);
|
||||
Assert.Equal(240.5f, block.MaxZ);
|
||||
Assert.Equal(4.25f, block.MinZ);
|
||||
}
|
||||
|
||||
private static WalkLandBlock PublishedBlock(WalkLandscapeAssembler assembler) =>
|
||||
Assert.Single(assembler.Landscape.Blocks.OfType<WalkLandBlock>());
|
||||
|
||||
private static TerrainTurnRecorder DrawTerrain(ConcreteFixture fixture, bool farViewer)
|
||||
{
|
||||
// The far-only block is six blocks east of the viewer, beyond NearRadius4.
|
||||
uint cameraCell = farViewer ? 0xA3B40001u : 0xA9B40001u;
|
||||
var eye = new Vector3(12f, 12f, 100f);
|
||||
var target = new Vector3(farViewer ? 6 * 192f + 96f : 144f, 12f, 20f);
|
||||
Vector3 forward = Vector3.Normalize(target - eye);
|
||||
Matrix4x4 viewProjection = Matrix4x4.CreateLookAt(eye, target, Vector3.UnitZ)
|
||||
* Matrix4x4.CreatePerspectiveFieldOfView(MathF.PI / 2f, 16f / 9f, 0.1f, 10_000f);
|
||||
fixture.Render.WalkLandscape.SetViewer(cameraCell, eye);
|
||||
var context = new WalkProductionFrameContext(
|
||||
new CellVisibility(), fixture.Render.WalkBuildings,
|
||||
eye, forward, viewProjection, 1600f, 900f, cameraCell);
|
||||
var recorder = new TerrainTurnRecorder();
|
||||
new RetailFrameWalk().WalkFrame(
|
||||
cameraCell, null, fixture.Render.WalkLandscape.Landscape, context, recorder);
|
||||
return recorder;
|
||||
}
|
||||
|
||||
private sealed class TerrainTurnRecorder : IWalkEventSink
|
||||
{
|
||||
public List<(uint LandblockId, int SideCellCount, int CellIndex)> TerrainTurns { get; } = [];
|
||||
public List<uint> Buildings { get; } = [];
|
||||
|
||||
public void Emit(in WalkEvent walkEvent)
|
||||
{
|
||||
if (walkEvent.Kind == WalkEventKind.Building)
|
||||
Buildings.Add(walkEvent.CellId);
|
||||
}
|
||||
|
||||
public void OnLandCellTurn(uint landblockId, int sideCellCount, int cellIndex) =>
|
||||
TerrainTurns.Add((landblockId, sideCellCount, cellIndex));
|
||||
}
|
||||
|
||||
private static LandblockPresentationPipeline Pipeline(
|
||||
ConcreteFixture fixture) => new(
|
||||
fixture.Render,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue