Skip to content

joooeeeeeeee/Cerebrum

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Cerebrum

Custom CFrame replication framework for Roblox, built in --!strict Luau.

Cerebrum replaces how entity positions and rotations travel across the network. Instead of relying on Roblox's built-in replication (which you can't control), Cerebrum serializes CFrames into compact binary buffers, sends them through custom channels, and reconstructs smooth movement on the receiving end with snapshot interpolation. On top of that core: dead reckoning, lag-compensated hitbox rewind, per-player visibility rules, distance-based tick rates, and NTP-style clock synchronization. Hot paths run with --!native.

Author: eternaIjoe


Why

Roblox's default replication is a black box. You can't control who sees what, how often updates are sent, or how movement gets smoothed on the receiving end. If you've ever played a competitive Roblox game and noticed players teleporting, rubberbanding, or being hit behind walls — that's the default system showing its limits.

Cerebrum gives you full control over the replication pipeline:

  • Per-player visibility — hide entities from specific players, show only to teammates, distance-gate replication
  • Binary serialization — 11–21 bytes per entity per tick instead of Roblox's bloated property replication
  • Snapshot interpolation — Hermite cubic splines using true physics velocities as tangents, SLERP for rotation, adaptive jitter buffers
  • Dead reckoning — render entities at estimated current position instead of buffer-seconds in the past
  • Lag compensation — rewind entity hitboxes to where they were on the shooter's screen for fair hit detection
  • Distance-based tick rates — full rate nearby, half rate at medium range, nothing at long range
  • ClockSync — NTP-style probing measures the actual uncertainty of GetServerTimeNow() per client

At a Glance

Feature Roblox Default Cerebrum
Per-player visibility control No Yes
Binary packet serialization No Yes (buffer API)
Client-side interpolation Basic Hermite cubic + SLERP
Dead reckoning No Yes (opt-in per type)
Lag-compensated raycasting No Yes (OBB + capsule)
Half-tick / distance culling No Yes
Entity mounting (parent→child) No Yes
Frustum culling No Yes
Clock error measurement No Yes (NTP-style Kalman)
Live debug overlay No Yes

Module Map

Cerebrum/
├── Cerebrum.lua              ← Entry point
│
├── Shared/
│   ├── Config.lua            ← Settings, entity type registration
│   ├── Entity.lua            ← Entity lifecycle, CFrame management, constraint lock
│   ├── Holder.lua            ← ID registry, model index, player-character map
│   ├── Snapshot.lua          ← Ring-buffer with Hermite interpolation (stored-velocity tangents)
│   ├── Serializer.lua        ← Binary buffer packing (9-bit quaternion, position, velocity)
│   ├── DeadReckoning.lua     ← Velocity extrapolation + correction blending
│   ├── ClockSync.lua         ← NTP-style clock error estimation (Kalman filtered)
│   ├── Ticker.lua            ← Server-side tick-rate group scheduler
│   ├── Signal.lua            ← Lightweight Signal/Event system
│   ├── Events.lua            ← Global event bus
│   ├── Remotes.lua           ← Remote creation/waiting
│   ├── ReplicationRules.lua  ← Per-entity player visibility rules
│   ├── ModelHelper.lua       ← CUSTOM mode model cloning/resolution
│   ├── ApplyMounts.lua       ← Entity mount chain solver (cycle-safe)
│   ├── Stats.lua             ← Live performance counters
│   └── Types.lua             ← Exported type definitions
│
├── Server/
│   ├── Replicate.lua         ← Server main loop (PreSimulation)
│   ├── Sender.lua            ← Builds + fires binary packets per-player
│   ├── Receiver.lua          ← Validates incoming client positions
│   ├── Grid.lua              ← Spatial hash proximity grid (integer keys, priority accumulator)
│   ├── Player.lua            ← Auto-registers player characters
│   ├── Clock.lua             ← Per-player Kalman clock offset + adaptive buffer API
│   └── LagCompensation.lua   ← Server-side hitbox rewind (Raycast, Spherecast)
│
├── Client/
│   ├── Replicate.lua         ← Client main loop (RenderStep), frustum culling
│   ├── Receiver.lua          ← Parses packets, pushes to Snapshot
│   ├── Sender.lua            ← Sends owned-entity positions to server
│   ├── Player.lua            ← Tracks the local player's entity
│   └── Clock.lua             ← Adaptive jitter-compensated playback clock
│
└── Debug/
    └── Debugger.lua          ← Live debug overlay (F8 to toggle)

Quick Start

1. Place Cerebrum in ReplicatedStorage

2. Server (ServerScriptService)

local Cerebrum = require(game.ReplicatedStorage.Cerebrum)

Cerebrum.Config.SetConfig("TELEPORT_THRESHOLD", 80)
Cerebrum.Config.RegisterEntityType("NPC", {
    TICK_RATE     = 1/20,
    FULL_ROTATION = false,
    BUFFER        = 0.08,
    NETWORK_MODE  = "NATIVE",
})

Cerebrum.Start()

3. Client (StarterPlayerScripts)

require(game.ReplicatedStorage.Cerebrum).Start()

Player characters are auto-registered. They replicate with snapshot interpolation, constraint-locked HRP, and full binary serialization at 60 Hz out of the box.


Network Modes

Mode What Happens Best For
NATIVE Model lives in Workspace. Cerebrum reads CFrame directly. Roblox handles physics replication. NPCs, simple objects
NATIVE_WITH_LOCK Same as NATIVE, but adds AlignPosition + AlignOrientation constraints on the HumanoidRootPart so Roblox's native replication can't fight Cerebrum's CFrame writes. Player characters (default and recommended)
CUSTOM Model is cloned per-client from a registered template. Full server authority. No native replication at all. Projectiles, server-spawned objects, entities needing per-player visibility

Dead Reckoning

Standard interpolation renders entities buffer seconds in the past. Dead reckoning renders them at their estimated current server position using velocity extrapolation. When a new packet arrives and the prediction was wrong, the error is blended out smoothly over DR_BLEND_TIME.

Recommended for player characters. Without DR, players are seen ~25ms in the past at all times. With DR, they're rendered at the estimated current position, making movement feel immediate and the gap in the debug overlay stay green.

Enable per entity type:

Cerebrum.Config.RegisterEntityType("PLAYER", {
    TICK_RATE               = 1/60,
    NETWORK_MODE            = "NATIVE_WITH_LOCK",
    BUFFER                  = 0,
    FULL_ROTATION           = true,
    DR_ENABLED              = true,
    DR_MAX_EXTRAPOLATION    = 0.100,   -- max 100ms forward prediction
    DR_BLEND_TIME           = 0.150,   -- blend corrections over 150ms
    DR_CORRECTION_THRESHOLD = 0.15,    -- ignore errors < 0.15 studs
})

Good for balls, projectiles, and any smoothly-moving entity. For entities that teleport or change direction instantly, use standard interpolation.


Lag Compensation

Server-side hitbox rewind for fair hit detection across all ping levels. No parts are moved — pure math against the snapshot history. The rewind time accounts for each shooter's actual client-side render buffer, not just one-way latency, so hits are validated against exactly what the shooter saw on their screen.

local LagComp = Cerebrum.Server.LagCompensation

-- Raycast (optional tickRate for more accurate rewind with non-default entity types)
local hit = LagComp.Raycast(shooter, origin, direction * 300, ignoreList)
if hit then
    print(hit.entity, hit.position, hit.distance, hit.rewindTime)
end

-- Spherecast (swept sphere — for melee and area abilities)
local hit = LagComp.Spherecast(shooter, origin, direction * 10, 2.5, ignoreList)

Replication Rules

Control which players receive updates for a given entity. Evaluated server-side — hidden entities produce zero network traffic.

local Rules = Cerebrum.ReplicationRules

Rules.SetRule(entity, Rules.Include({ player1, player2 }))
Rules.SetRule(entity, Rules.Exclude({ player3 }))
Rules.SetRule(entity, Rules.SameTeam)
Rules.SetRule(entity, Rules.WithinDistance(50))
Rules.SetRule(entity, Rules.SameOwner)
Rules.SetRule(entity, nil)    -- visible to all

Config Reference

Set with Cerebrum.Config.SetConfig(key, value) before Start().

Key Default Description
MIN_BUFFER 0.033 Minimum interpolation buffer (seconds)
MAX_BUFFER 0.300 Maximum interpolation buffer (seconds)
MAX_SNAPSHOTS 32 Snapshot ring buffer size per entity
DEFAULT_NETWORK_MODE "NATIVE_WITH_LOCK" Fallback network mode
DEFAULT_NORMAL_DIST 60 Full-tick replication range (studs)
DEFAULT_HALF_DIST 120 Half-tick replication range (studs)
MOVE_THRESHOLD 0.06 Minimum movement to trigger an update (studs)
FROZEN_TIMEOUT 4.0 Seconds before a stopped entity sends a stationary clock ping
MAX_SPEED 150 Speed hack rejection threshold (studs/sec)
TELEPORT_THRESHOLD 50 Position jump treated as teleport (studs)
EXTRAP_MAX 0.12 Max extrapolation past latest snapshot (seconds)
VEL_SCALE 200 Velocity quantization scale factor
ANG_VEL_SCALE 500 Angular velocity quantization scale
MAP_BOUNDS 3276 World size for position serialization precision
PLAYER_REPLICATION "AUTOMATIC" "AUTOMATIC" or "MANUAL"
REPLICATE_DEATHS "PLAYER_ENTITIES" "ALL", "PLAYER_ENTITIES", "NONE"
MAX_REWIND_MS 500 Max lag compensation rewind (ms)
CORRECTION_BLEND_TIME 0.25 Client-side correction blend duration (seconds)

Entity Type Fields

Cerebrum.Config.RegisterEntityType("MY_TYPE", {
    TICK_RATE               = 1/30,           -- send rate (Hz)
    NETWORK_MODE            = "NATIVE",       -- "NATIVE" | "NATIVE_WITH_LOCK" | "CUSTOM"
    BUFFER                  = 0.08,           -- interpolation buffer (0 = adaptive minimum)
    FULL_ROTATION           = false,          -- true = 9-bit quaternion, false = yaw only
    NORMAL_DIST             = 60,             -- full tick radius (studs)
    HALF_DIST               = 120,            -- half tick radius (studs)

    -- Dead Reckoning (optional)
    DR_ENABLED              = false,
    DR_MAX_EXTRAPOLATION    = 0.150,
    DR_BLEND_TIME           = 0.100,
    DR_CORRECTION_THRESHOLD = 0.5,
})

Built-in Types

These exist by default — override with RegisterEntityType before Start().

Type Tick Rate Rotation Buffer Mode
DEFAULT 30 Hz Yaw Adaptive NATIVE_WITH_LOCK
PLAYER 60 Hz Full quaternion Adaptive min NATIVE_WITH_LOCK
NPC 20 Hz Yaw 80ms NATIVE

Docs

  • API.md — complete function reference
  • TUTORIAL.md — how replication works under the hood, step-by-step examples

License

MIT

About

A Custom Replication for Roblox. Inspired on chrono of parihsz

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors