GridForge is a framework-agnostic deterministic voxel-grid library for games, simulations, tools, and server runtimes. It sits in the LSF stack after:
FixedMathSharp- deterministic fixed-point math.SwiftCollections- low-allocation collections, pools, and query-friendly containers.GridForge- explicit voxel worlds, conjoined grids, spatial queries, blockers, occupants, and voxel-local partitions.
The core design goal is to make grid-backed spatial systems scalable without forcing every consumer to reinvent ownership, snapping, neighbor resolution, coverage queries, or occupant indexing.
Priorities:
- Preserve deterministic behavior across supported target frameworks.
- Keep runtime APIs anchored to explicit
GridWorldownership. - Prefer optimized, low time-complexity code. No band-aid solutions.
- Keep hot paths allocation-conscious and pooling-safe.
- Keep the core library engine-agnostic. Unity integration belongs in the
separate
GridForge-Unityrepository. - Prefer proven lower-stack primitives from
FixedMathSharpandSwiftCollectionsbefore adding local math, collection, pool, or helper implementations. - Keep README, wiki pages, tests, benchmarks, package metadata, and workflow behavior aligned when architecture or public API changes.
Read these in order before making non-trivial changes:
README.mdfor package orientation and the public-facing mental model.docs/wiki/Home.md, then the matching wiki page for the area being changed.src/GridForge/GridForge.csprojfor target frameworks, package variants, dependencies, and build behavior.src/GridForge/Grids/Managers/GridWorld.cs,src/GridForge/Grids/VoxelGrid.cs,src/GridForge/Grids/Nodes/Voxel.cs, andsrc/GridForge/Utility/GridTracer.cs.- The relevant source folder under
src/GridForge. - The matching test folder under
tests/GridForge.Tests. tests/GridForge.Benchmarkswhen changing pooling, tracing, scanning, registration, or other performance-sensitive behavior.
For coordinated stack changes, also check the guidance in the affected repositories:
When code, README, and wiki content disagree, prefer the code, project files, and tests. Then update the docs that drifted.
Keep these aligned whenever behavior, public API, package shape, or developer workflow changes:
README.mddocs/wiki, especially pages covering world ownership, tracing, scan cells, blockers, occupants, partitions, determinism, testing, and build workflow.docs/apifor the DocFX landing page, navigation, and API build configuration.AGENTS.mdsrc/GridForge/GridForge.csprojtests/GridForge.Teststests/GridForge.Benchmarkswhen performance claims or hot paths change.- Workflow files under
.github/workflows, especiallybuild-and-test.yml,coverage.yml,sync-wiki.yml, andpublish-nuget.yml.
docs/wiki is the source content for the GitHub wiki. Keep source Markdown
repo-friendly and let the publish helper perform the narrow GitHub wiki link
rewrite.
| Path | Purpose | Notes |
|---|---|---|
src/GridForge |
Main library project | Multi-targets netstandard2.1 and net8.0. |
src/GridForge/Configuration |
Grid creation input and bounds identity | GridConfiguration is normalized by the owning world. |
src/GridForge/Grids |
Core world, grid, voxel, scan-cell, manager, storage, topology, and pool logic | Highest-risk runtime area. |
src/GridForge/Grids/Storage |
Dense and sparse physical voxel storage | Keep storage-specific layout behind VoxelGrid. |
src/GridForge/Grids/Topology |
Topology metrics, snapping, dimensions, and world/index projection | Keep coordinate math deterministic and storage-neutral. |
src/GridForge/Spatial |
Shared coordinates, directions, occupants, partitions, and awareness abstractions | Keep engine-neutral and deterministic. |
src/GridForge/Blockers |
Bounds-based obstacle application over tracer coverage | Test stacked, edge, removal, and multi-grid cases. |
src/GridForge/Support |
Shared support types such as BoundsKey and GridVoxelSet |
Watch pooled result lifetimes. |
src/GridForge/Utility |
GridTracer and GridForgeLogger |
Tracing changes can affect many systems. |
tests/GridForge.Tests |
xUnit v3 test project | Mirrors subsystem boundaries. |
tests/GridForge.Benchmarks |
BenchmarkDotNet project | Covers allocation and throughput-sensitive scenarios. |
docs/wiki |
Developer-facing usage and architecture documentation | Keep aligned with public API and workflow changes. |
docs/api |
DocFX landing page, navigation, and API build configuration | Generated output stays under docs/api/obj. |
.assets/scripts |
PowerShell release packaging helpers | Requires GitVersion.Tool for versioned archives. |
.github/workflows |
CI, coverage, wiki sync, release, and publish automation | Keep workflow names in sync across triggers. |
Ignore generated output when reviewing or editing unless the task is explicitly about build artifacts:
.vs/bin/obj/TestResults/artifacts/BenchmarkDotNet.Artifacts/
- Language: C# 11
- Library target frameworks:
netstandard2.1,net8.0 - Validation target framework:
net8.0 - Test framework: xUnit v3
- Benchmark framework: BenchmarkDotNet
- Main dependencies:
FixedMathSharp,SwiftCollections, and optionalMemoryPack - Library nullable context: enabled
- Test and benchmark nullable context: disabled
- Implicit usings: disabled
- XML documentation: generated for the library project
- Package generation:
GeneratePackageOnBuildis enabled - Configurations:
Debug,Release,ReleaseLean - Local prerequisites: the SDK selected by
global.jsonand the runtimes targeted by tests and benchmarks
Package variants:
Releasebuilds the standardGridForgepackage withMemoryPack,FixedMathSharp, andSwiftCollections.ReleaseLeanbuildsGridForge.LeanwithGRIDFORGE_DISABLE_MEMORYPACK,FixedMathSharp.Lean,SwiftCollections.Lean, and the annotation-onlyChronicler.MemoryPackShimdependency.
Versioning:
- CI and release workflows use GitVersion.
- Local builds without GitVersion fall back to version
0.0.0.
The runtime is built around explicit world ownership:
GridWorldowns one world's ordinary-tier lookup tuning, active grid bucket, bounds tracker, adaptive two-tier spatial index, maximum topology cell edge, versioning, lifecycle, and world-level events. Oversized grids are routed to the secondary fixed BVH automatically.GridConfigurationcarries per-grid storage and topology intent throughGridStorageKind,GridTopologyKind, andGridTopologyMetrics.VoxelGridowns one grid's snapped bounds, dimensions, topology instance, dense or sparse physical voxel storage, scan-cell overlay, active scan-cell set, neighbor relationships, obstacle count, occupancy summary, and grid version.- Dense storage materializes every in-bounds topology-local voxel. Sparse storage uses bounds as an address space and materializes only configured voxels; missing sparse voxels are intentional absence.
Voxelowns local and world-scoped identity, obstacle state, occupant count, partitions, boundary awareness, world position, and neighbor query entrypoints.ScanCellstores occupant buckets grouped byWorldVoxelIndexand ticketed occupant entries for efficient removal and exact lookup.GridTracerconverts lines and bounds into covered voxels or scan cells across the active grids in oneGridWorld.GridObstacleManagermutates obstacle state and emits obstacle events.GridOccupantManagerowns world-scoped occupant registration tracking, add/remove flows, ticket lookup, and occupant events.GridScanManagerperforms radius and typed scans through the scan-cell overlay.Blocker,BoundsBlocker, andAreaBlockertranslate world-space boxes or layer-locked X/Z areas into obstacle application and removal.PartitionProvider,IVoxelPartition, andIVoxelOccupantare the primary extension points for domain-specific behavior.
The library supports a single grid, many conjoined grids, and dynamic load/unload patterns. Higher-level hierarchy should live above GridForge unless there is a concrete reason to add it to the core API.
Any change that affects snapping, lookup, iteration order, identity, tracing, storage layout, topology projection, sparse mutation, neighbor resolution, blocker coverage, occupant registration, scan ordering, or pooled lifetime is high risk.
Always prefer:
Fixed64,Vector2d, andVector3doverfloat,double, orSystem.Numericsin deterministic runtime paths.- Existing
FixedMathSharphelpers for deterministic math and conversions before adding local equivalents. - Stable ordering when traversing grids, voxels, scan cells, occupants, blockers, partitions, or pooled collections.
- Explicit
GridWorldownership over hidden process-global state. WorldVoxelIndexfor cross-system voxel identity.- Exact assertions in tests for snapped coordinates, identity, and event data.
Avoid introducing:
- wall-clock time, background scheduling, or nondeterministic random behavior in runtime logic.
- platform-specific hash-order dependencies.
- floating-point conversions in core spatial math unless the boundary is explicit and tested.
- engine-specific assumptions in the core library.
Always prefer optimized, low time-complexity code. No band-aid solutions.
Likely hotspots include:
GridWorld.TryAddGrid,TryRemoveGrid, lookup, adaptive spatial-index registration, and neighbor updates.VoxelGridgeneration, reset, same-topology neighbor linking, and scan-cell generation.- Dense and sparse voxel storage construction, lookup, enumeration, and runtime sparse add/remove.
- Topology normalization, world/index conversion, and coverage math.
GridTracerline, bounds, and scan-cell coverage.GridScanManagerradius scans and caller-owned result paths.GridOccupantManagerregistration tracking, active scan-cell bookkeeping, and remove flows.Blockerapply/remove paths and covered voxel caching.
Rules:
- Choose data structures by access pattern and time complexity.
- Prefer
SwiftCollectionsconcrete collections overSystem.Collectionsconcrete collections in runtime code and tests that mirror runtime hot paths. Arrays are still appropriate for fixed-size or contiguous indexed storage. - Use existing pools where the surrounding code already does.
- Check
FixedMathSharpandSwiftCollectionsfor existing primitives before writing custom math, collection, pooling, sorting, hashing, or capacity helpers. - Use bit flags or bit masking for compact combinable state when it improves performance or clarity; avoid binary enums that cannot grow or compose.
- Apply
[MethodImpl(MethodImplOptions.AggressiveInlining)]to tiny hot-path helpers, properties, and forwarding methods when it matches surrounding code. - Release rented collections in
finallyblocks when enumeration or user code can exit early. - Do not retain pooled arrays, lists, sets, scan cells, voxels, or
GridVoxelSetresults beyond their documented lifetime. - Benchmark changes that touch pooling, tracing, scan flow, registration, or other allocation-sensitive paths.
- Avoid LINQ in hot paths unless the surrounding code already accepts the cost and benchmarks support it.
Match the surrounding file style instead of imposing a new one.
- Add explicit
usingdirectives.ImplicitUsingsis disabled. - The library project enables nullable analysis; tests and benchmarks disable it. Follow the project being edited.
.editorconfigdisables implicitnew(...); prefer explicit construction.- Public API surface should have XML documentation.
- Preserve existing
#regionorganization in files that already use it. - Route diagnostics through
GridForgeLogger, not ad hoc console output. - Keep interfaces small, deterministic, and engine-agnostic.
- Do not add compatibility adapters or wrapper APIs just to avoid fixing a weak design.
Run tests whenever behavior changes:
dotnet restore GridForge.slnx
dotnet build GridForge.slnx --configuration Debug
dotnet test GridForge.slnx --configuration Debug --no-buildCI validates both Release and ReleaseLean on Ubuntu and Windows:
dotnet test GridForge.slnx --configuration Release
dotnet test GridForge.slnx --configuration ReleaseLeanRun benchmarks when changing pooling, tracing, scan cells, occupant registration, blocker application, grid registration, neighbor caching, or other performance-sensitive paths:
dotnet run --project tests/GridForge.Benchmarks/GridForge.Benchmarks.csproj -c Release -- list
dotnet run --project tests/GridForge.Benchmarks/GridForge.Benchmarks.csproj -c Release -- all --filter '*'
dotnet run --project tests/GridForge.Benchmarks/GridForge.Benchmarks.csproj -c Release -- sparse-voxel-grid --filter '*SparseVoxelGridBenchmarks*'Test guidance:
- Prefer explicit
GridWorldcreation in new tests. - Use
GridWorldTestFactorywhen it keeps setup clear and consistent. - Many tests use
[Collection("GridForgeCollection")]to isolate shared logger or compatibility state. - Prefer deterministic coordinates and exact assertions over fuzzy tolerances.
- If you change tracing, blockers, occupancy, scan cells, grid registration, neighbor handling, snapping, storage, topology, sparse mutation, or identity behavior, update or add tests in the closest matching folder.
Update docs in the same change when user-facing behavior, public API, package shape, or workflow behavior changes.
High-value pages:
docs/wiki/Home.mddocs/wiki/Getting-Started.mddocs/wiki/Core-Concepts.mddocs/wiki/Architecture-Overview.mddocs/wiki/Sparse-Grid-Storage.mddocs/wiki/GridTracer-and-Coverage.mddocs/wiki/Scan-Cells-and-Query-Flow.mddocs/wiki/Blockers-and-Obstacles.mddocs/wiki/Occupants-and-Partitions.mddocs/wiki/Repository-Layout-and-Build.mddocs/wiki/Testing-and-Benchmarking.md
Keep README engaging and concise; push deep subsystem detail into the wiki. Keep wiki source links repo-relative and let the sync helper adapt copied pages for GitHub wiki publishing.
The DocFX site under docs/api is the branded API and discovery
surface. Keep its GridForge icon, blue/cyan custom template, GitHub header link,
namespace overviews, Unity adapter links, and landing-page routes intact. Build
it from the Release net8.0 assembly with warnings treated as errors; generated
content under docs/api/obj is disposable.
docs/feature-work/issue-tracker.md and
docs/feature-work/benchmark-signal-hardening-backlog.md
are evergreen operational trackers, not completed plans. Preserve stable issue
and signal IDs, verify each next-ID counter against Git history, and never reuse
an ID after resolution, closure, promotion, or removal.
- Start in
src/GridForge/Grids. - Decide whether the behavior belongs at world, grid, voxel, scan-cell, query, storage, topology, or manager level.
- Check interactions with snapping, spatial indexing, pooling, versioning, events, neighbor resolution, storage kind, topology metrics, and identity tokens.
- Add or update tests under
tests/GridForge.Tests/Gridsortests/GridForge.Tests/Utility.
- Start in
src/GridForge/Blockersorsrc/GridForge/Utility/GridTracer.cs. - Reuse existing tracer and blocker patterns where possible.
- Test single-grid, multi-grid, edge, stacked, cached, uncached, apply, remove, sparse configured-only coverage, runtime sparse add reconciliation, and reapply cases.
- Start in
src/GridForge/Spatial,src/GridForge/Grids/Managers, orsrc/GridForge/Grids/Nodes/Voxel.cs, depending on the responsibility. - Verify registration, removal, scan-cell ticketing, active scan-cell tracking, callback failure behavior, and blocked voxel behavior.
- Add tests around attach/remove behavior and grid mutation side effects.
src/GridForge/GridForge.csprojpackages the library on build.- Build outputs include
.nupkgand.snupkgunder the configured output path. .assets/scripts/set-version-and-build.ps1builds bothReleaseandReleaseLeanand writes release archives underartifacts/releases..github/workflows/publish-nuget.ymlvalidates release tag version, builds both package variants, checks for exactly four package artifacts, uploads the package artifact, and publishes.nupkgfiles to NuGet..github/workflows/coverage.ymlbuilds the DocFX site and publishes coverage beneath/coveragein the same GitHub Pages artifact..github/workflows/sync-wiki.ymlpublishesdocs/wikito the GitHub Wiki. Both workflows depend on thebuild-and-testworkflow name; update their triggers and README badges if that name changes.
- Reintroducing hidden process-wide grid state.
- Treating
GridIndexalone as durable cross-system identity. - Assuming pooled collections or query results can be retained indefinitely.
- Bypassing snapping or fixed-point conversions in core spatial logic.
- Reintroducing world-level cell geometry instead of per-grid topology metrics.
- Assuming
VoxelGridstorage is always dense or thatVoxelGrid.Voxelsis a public storage-neutral surface. - Treating missing sparse voxels as empty dense voxels.
- Breaking
ReleaseLeanby referencingMemoryPackwithout a guarded path. - Adding Unity or engine-specific code to the core library.
- Changing synchronization around shared mutable state without tests and a clear reason.
- Editing generated output under
bin,obj,TestResults,artifacts, orBenchmarkDotNet.Artifacts. - Updating README examples without checking source and tests.
- Read the README, the relevant wiki page, the project file, and nearby source and tests.
- Decide whether the change affects determinism, global state, identity, pooling, storage, topology, package variants, or docs.
- Make the smallest coherent change that fits existing architecture.
- Check lower-stack libraries for existing primitives before adding local helpers.
- Add or update focused tests for behavior changes.
- Run build and test commands appropriate to the risk.
- Run benchmarks for performance-sensitive changes.
- Mention any warnings, global-state considerations, package-variant risk, or untested edge cases in the handoff.
Keep this document current when solution layout, build flow, package variants, wiki publishing, storage/topology boundaries, or core architecture changes.