LogicThreadBase class

Non-template base class for all LogicThread<> specializations.

Owns all shared data fields and provides type-erased accessors for external systems (RendererCore, OwnerNet, EditorContext) that do not need the concrete template instantiation — they hold LogicThreadBase* instead.

Derived classes

template<typename TNet, typename TRollback, typename TFrame>
class LogicThread
The Brain — fixed-timestep simulation coordinator for one World.

Constructors, destructors, conversion operators

LogicThreadBase() defaulted
~LogicThreadBase() defaulted virtual
LogicThreadBase(const LogicThreadBase&) deleted

Public functions

auto operator=(const LogicThreadBase&) -> LogicThreadBase& deleted
void Initialize(Registry* registry, const EngineConfig* config, JoltPhysics* physics, InputBuffer* simInput, InputBuffer* vizInput, TrinyxJobs::WorldQueueHandle worldQueue, const std::atomic<bool>* jobsInitialized, int windowWidth, int windowHeight) pure virtual
Bind all non-owning pointers. Called by WorldBase::InitBase before Start().
void Start() pure virtual
Spawn the Brain thread and begin the fixed-rate loop.
void Stop() pure virtual
Signal the Brain thread to exit after the current frame.
void Join() pure virtual
Block the caller until the Brain thread exits.
void TickOnce() pure virtual
Run one complete simulation frame synchronously on the calling thread.
auto IsRunning() const -> bool
Returns true while the Brain thread is running.
auto IsResimulating() const -> bool
Returns true while ExecuteRollback is actively resimulating frames.
void RequestRollback(uint32_t f)
Request a rollback to f on the next tick. Thread-safe.
void RequestRollbackTest()
Request a rollback determinism self-test (F5 in editor). Thread-safe.
auto IsRollbackTestComplete() const -> bool
True after ExecuteRollbackTest has run; reset by RequestRollbackTest(). Thread-safe.
auto GetRollbackTestPassed() const -> bool
True if the most recent rollback test was byte-perfect. Valid after IsRollbackTestComplete(). Thread-safe.
auto GetLastCompletedFrame() const -> uint32_t
Last fully-published sim frame number. Render thread uses this for interpolation.
auto GetAccumulator() const -> double
Current accumulator depth.
auto GetFixedAlpha() const -> double
Normalised interpolation alpha [0, 1] between the last two completed fixed steps.
void SetSimPaused(bool paused)
Pause or resume the fixed-rate sim loop. Thread-safe.
void Wake()
Wake the Brain if it is sleeping in edit mode (paused). Thread-safe, lock-free. Called for world-queue jobs, pause changes, and stop; harmless while the sim runs.
void RequestEditCommit()
Commit the editor's changes as one sim frame while paused. Thread-safe.
void RequestStep()
While paused, simulate exactly one fixed step and publish it. Thread-safe; requests accumulate. Ignored while running.
auto IsSimPaused() const -> bool
Returns true while the sim loop is paused.
auto GetPausedAtFrame() const -> uint32_t
Frame number at which the sim was paused. Valid while IsSimPaused(). Editor scrubber uses this as the rewind target.
void SetConstructRegistry(ConstructRegistry* cr)
Inject the ConstructRegistry so Constructs can self-register at spawn time.
void SetWorld(WorldBase* world)
The world this thread simulates: its commands and per-player input.
auto GetConstructRegistry() const -> ConstructRegistry*
Expose the ConstructRegistry for editor inspection (read-only).
void SetFreeFlyCamera(SimFloat x, SimFloat y, SimFloat z, SimFloat yaw, SimFloat pitch)
Set the free-fly camera position and orientation for editor/debug use.
void SetLocalCameraManager(CameraManager* mgr)
Inject the per-Soul CameraManager so the Brain resolves the active camera each frame.
void SetEarliestValidRollbackFrame(uint32_t frame)
Set the earliest frame a spawn-triggered rollback may target.
auto GetLogicFPS() const -> float
auto GetLogicFrameMs() const -> float
auto GetFixedFPS() const -> float
auto GetFixedFrameMs() const -> float

Public variables

ConstructBatch ScalarPrePhysicsBatch
Runs before PrePhysics wide sweeps each fixed step.
ConstructBatch ScalarPostPhysicsBatch
Runs after PostPhysics wide sweeps each fixed step.
ConstructBatch ScalarUpdateBatch
Runs each variadic (uncapped) logic tick.
ConstructBatch ScalarPhysicsStepBatch
Runs between FlushPendingBodies and the Jolt step.
SimCommandHandlers Commands
Constructs' OnCommand handlers, by command type.

Protected static variables

static SimFloat CamMoveSpeed constexpr
Free-fly camera speed (sim units/s).
static SimFloat CamMouseSens constexpr
Free-fly mouse sensitivity (rad/pixel).

Protected variables

Registry* RegistryPtr
const EngineConfig* ConfigPtr
JoltPhysics* PhysicsPtr
ComponentCacheBase* TemporalCache
ConstructRegistry* ConstructsPtr
CameraManager* LocalCameraManager
TrinyxJobs::WorldQueueHandle WQHandle
const std::atomic<bool>* JobsInitPtr
WorldBase* OwnerWorld
Non-owning; set by the World that owns this thread.
InputBuffer* SimInput
Non-owning; WorldBase owns the buffer.
InputBuffer* VizInput
Non-owning; WorldBase owns the buffer.
Vector3 CamPos
SimFloat CamYaw
SimFloat CamPitch
Vector3 LastPubCamPos
Quat LastPubCamRot
SimFloat LastPubCamFoV
std::atomic<uint32_t> LastCompletedFrame
Frame mailbox; last completed frame the Render thread may read.
std::thread Thread
std::atomic<bool> bIsRunning
std::atomic<bool> bSimPaused
std::counting_semaphore WakeSignal
std::atomic<bool> bEditCommitRequested
uint32_t WorldJobsRanThisLoop
Brain-only: jobs drained at the top of the current loop.
bool bWasPausedLastLoop
Brain-only: detects entering pause.
std::atomic<uint32_t> PendingSteps
bool bSteppingThisLoop
Brain-only: this loop runs one paused step through the normal path.
std::atomic<uint32_t> PausedAtFrame
std::atomic<double> Accumulator
double SimulationTime
uint32_t FrameNumber
uint32_t PhysicsDivizor
int WindowWidth
int WindowHeight
double FixedStepTimeCache
Cached from EngineConfig at Initialize time.
uint32_t FpsFrameCount
double FpsTimer
uint32_t FpsFixedCount
double FpsFixedTimer
double LastFPSCheck
BrainStepRate StepRate
fixed steps against real time, for EngineStats
std::atomic<float> LogicFPS
std::atomic<float> LogicFrameMs
std::atomic<float> FixedFPS
std::atomic<float> FixedFrameMs
bool bRollbackActive
std::atomic<uint32_t> PendingRollbackFrame
std::atomic<bool> bRollbackTestRequested
std::atomic<bool> bRollbackTestComplete
Set by ExecuteRollbackTest when done; cleared by RequestRollbackTest.
std::atomic<bool> bRollbackTestPassed
True if the last test was byte-perfect; valid after bRollbackTestComplete.
std::atomic<uint32_t> EarliestValidRollbackFrame

Function documentation

void LogicThreadBase::Initialize(Registry* registry, const EngineConfig* config, JoltPhysics* physics, InputBuffer* simInput, InputBuffer* vizInput, TrinyxJobs::WorldQueueHandle worldQueue, const std::atomic<bool>* jobsInitialized, int windowWidth, int windowHeight) pure virtual

Bind all non-owning pointers. Called by WorldBase::InitBase before Start().

Parameters
registry
config
physics
simInput
vizInput
worldQueue World-scoped job queue; Brain submits pre/post-physics jobs here.
jobsInitialized Engine jobs-ready gate; Brain spins on this before draining the queue.
windowWidth
windowHeight

void LogicThreadBase::TickOnce() pure virtual

Run one complete simulation frame synchronously on the calling thread.

Intended for editor use after level load, before the background thread starts. Advances the accumulator, runs Constructs, writes a temporal frame, and increments LastCompletedFrame.

double LogicThreadBase::GetAccumulator() const

Current accumulator depth.

void LogicThreadBase::SetEarliestValidRollbackFrame(uint32_t frame)

Set the earliest frame a spawn-triggered rollback may target.

Must be called once per level load on the Logic thread (inside SpawnAndWait), with a frame value strictly greater than the previous value. Prevents rollbacks from targeting frames whose Jolt snapshots predate the current level geometry.

float LogicThreadBase::GetLogicFPS() const

Variable documentation

std::atomic<uint32_t> LogicThreadBase::EarliestValidRollbackFrame protected

Hard floor for spawn rollback targets — set once per level load so rollbacks never target a frame whose Jolt snapshot predates the level geometry. Written on the Logic thread; relaxed ordering is sufficient because visibility is guaranteed by the spawn handshake that precedes any EnqueueSpawnRollback call.