Problem
In a Lithos probe capture on Stratum (Vintage Story 1.22.7, 2,185 connected clients, Debian Linux x64), ServerSystemEntitySimulation.OnServerTick accounted for 147,440 total samples (57.1% of the gameplay thread). Within this call tree, GameMain.FindNearestRayIntersectingEntity accounted for 114,383 self samples (44.3% of the entire gameplay thread).
ServerSystemEntitySimulation.cs implements an angle and movement threshold throttle (StratumSelectionMaxSkipTicks = 3) to reduce per-client raytracing. With 2,185 active clients, this threshold still executes at least 728 raytraces on every single server tick. Each trace invokes server.RayTraceForSelection, which calls FindNearestRayIntersectingEntity. That method iterates 8 to 27 chunk volumes in a 3D bounding box around the player and checks entity.IntersectsRay across all entities in those chunks.
On the server, entityPlayer.EntitySelection is not consumed by the tick loop. The entity intersection search is performed solely to check if an entity occludes the player's view of a block, which the server uses only to fire Block.OnBeingLookedAt (in vanilla survival, implemented only by Farmland, FertileGround, and Tapestry for client-side tooltips). Authoritative block breaks, placements, and entity combat interactions are already driven by client-sent interaction packets.
Existing issue #348 covers repeated calls to EntityPlayer.get_IsInteractable during dense entity queries (which accounted for under 1% of samples in this capture). The primary bottleneck under massive concurrency is the volume of chunk traversals and ray-intersection tests executed per tick across thousands of players.
Proposed change
- Scale StratumSelectionMaxSkipTicks dynamically based on online player count, or expose it as a configurable setting under Performance.EntitySimulation.
- Skip the FindNearestRayIntersectingEntity occlusion pass when the server only needs BlockSelection for OnBeingLookedAt, or fast-reject chunks that contain no interactable entities.
- Provide a configuration toggle to disable ambient server-side OnBeingLookedAt raytracing under high-concurrency environments.
Acceptance criteria
- Gameplay-thread CPU time spent in FindNearestRayIntersectingEntity is reduced substantially under high player counts.
- Block breaking, placing, and entity combat continue to function accurately through client interaction packets.
- Server scenarios and smoke tests pass with zero regressions.
Scope
Problem
In a Lithos probe capture on Stratum (Vintage Story 1.22.7, 2,185 connected clients, Debian Linux x64), ServerSystemEntitySimulation.OnServerTick accounted for 147,440 total samples (57.1% of the gameplay thread). Within this call tree, GameMain.FindNearestRayIntersectingEntity accounted for 114,383 self samples (44.3% of the entire gameplay thread).
ServerSystemEntitySimulation.cs implements an angle and movement threshold throttle (StratumSelectionMaxSkipTicks = 3) to reduce per-client raytracing. With 2,185 active clients, this threshold still executes at least 728 raytraces on every single server tick. Each trace invokes server.RayTraceForSelection, which calls FindNearestRayIntersectingEntity. That method iterates 8 to 27 chunk volumes in a 3D bounding box around the player and checks entity.IntersectsRay across all entities in those chunks.
On the server, entityPlayer.EntitySelection is not consumed by the tick loop. The entity intersection search is performed solely to check if an entity occludes the player's view of a block, which the server uses only to fire Block.OnBeingLookedAt (in vanilla survival, implemented only by Farmland, FertileGround, and Tapestry for client-side tooltips). Authoritative block breaks, placements, and entity combat interactions are already driven by client-sent interaction packets.
Existing issue #348 covers repeated calls to EntityPlayer.get_IsInteractable during dense entity queries (which accounted for under 1% of samples in this capture). The primary bottleneck under massive concurrency is the volume of chunk traversals and ray-intersection tests executed per tick across thousands of players.
Proposed change
Acceptance criteria
Scope