Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,47 @@

All notable changes to the Nine Realities Netcode Model project.

## [3.0] - 2026-06-25

### Unreal Engine Plugin
- Complete C++ implementation of the N+1 concurrent simulation model as a UE plugin
- `UN1NetcodeManager` — Central orchestrator with Standalone/Client/Server/ListenServer modes
- `UN1ClientPrediction` — 4-mode adaptive prediction (Conservative/Balanced/Aggressive/Adaptive)
- `UN1ServerAuthority` — Authoritative simulation with per-client adaptive snapshots and lag compensation
- `UN1RollbackEngine` — Rollback + replay with cost estimation, depth limiting, and contiguous input validation
- `UN1BlendInterpolator` — Smooth correction blending with Linear/SmoothStep/Exponential/CriticalDamping curves
- `UN1ReconciliationEngine` — 4-strategy reconciliation (FullRollback/StateInterpolation/DeltaCorrection/Adaptive)
- `UN1NetworkClock` — High-precision sync using Cristian's algorithm with jitter buffering
- `UN1PredictionBuffer` — Ring buffer storing predicted states and inputs for rollback replay
- Quantized state serialization (0.01 unit position precision, ~0.002 degree rotation)
- Delta compression for world snapshots (only changed fields serialized)
- Full Blueprint support with UCLASS/UFUNCTION/UPROPERTY annotations
- Editor module (`NineRealitiesNetcodeEditor`) for development tooling
- Plugin config: `.uplugin`, `Build.cs`, `FilterPlugin.ini`

### UE6 Forward Compatibility
- `UN1UE6Compatibility` — Runtime engine version detection and feature adaptation
- UE6 Network Snapshots V2 preparation with UE5 fallback
- QUIC transport configuration flag (auto-disabled on UE5)
- NetworkPrediction plugin integration hooks
- Compile-time macros: `N1_UE6_READY`, `N1_UE5_5_OR_LATER`
- C++20 standard for UE6 compatibility

### Documentation & Site
- Completely redesigned GitHub Pages site (dark theme, card-based design)
- New "Plugin" tab with installation guide, C++/Blueprint quick start, architecture overview
- New "UE6 Ready" tab with compatibility features, migration path table, and planned features
- Updated hero section with v3.0 badge and UE6 CTA button
- Enhanced navigation with NEW/UE6 badges on relevant tabs
- Updated README with plugin quick start, architecture diagrams, and performance summary
- Updated ROADMAP with 2026-2027 milestones

### Added
- `N1UE6Compatibility.h/cpp` — Forward compatibility layer
- `N1NetcodeEditorModule.h/cpp` — Editor module
- Full API header files in `Public/Core/`, `Public/Pipeline/`, `Public/UE6/`
- Implementation files in `Private/Core/`, `Private/Pipeline/`, `Private/UE6/`

## [2.0] - 2025-11-29

### Added
Expand Down Expand Up @@ -41,4 +82,4 @@ All notable changes to the Nine Realities Netcode Model project.

## Contributing

Found an issue or want to suggest improvements? [Open an issue](https://github.com/POWDER-RANGER/nine-realities-netcode/issues) or submit a pull request.
Found an issue or want to suggest improvements? [Open an issue](https://github.com/POWDER-RANGER/nine-realities-netcode/issues) or submit a pull request.
12 changes: 12 additions & 0 deletions NineRealitiesNetcode/Config/FilterPlugin.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[FilterPlugin]
; Exclude source control and build artifacts from packaged plugin
/Config/...
/Intermediate/...
/Binaries/...
/DerivedDataCache/...
/.vs/...
/.vscode/...
/.git/...
/.github/...
*.tmp
*.log
50 changes: 50 additions & 0 deletions NineRealitiesNetcode/NineRealitiesNetcode.uplugin
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"FileVersion": 3,
"Version": 3,
"VersionName": "3.0.0",
"FriendlyName": "Nine Realities Netcode",
"Description": "Production-ready N+1 concurrent simulation framework for competitive multiplayer netcode. Server-authoritative architecture with client-side prediction, rollback-based reconciliation, and UE6 forward compatibility.",
"Category": "Networking",
"CreatedBy": "POWDER-RANGER (Curtis Charles Farrar)",
"CreatedByURL": "https://github.com/POWDER-RANGER",
"DocsURL": "https://powder-ranger.github.io/nine-realities-netcode/",
"MarketplaceURL": "",
"SupportURL": "https://github.com/POWDER-RANGER/nine-realities-netcode/issues",
"EngineVersion": "5.5.0",
"CanContainContent": false,
"IsBetaVersion": false,
"IsExperimentalVersion": false,
"Installed": false,
"Modules": [
{
"Name": "NineRealitiesNetcode",
"Type": "Runtime",
"LoadingPhase": "PreDefault",
"PlatformAllowList": [
"Win64",
"Linux",
"Mac"
]
},
{
"Name": "NineRealitiesNetcodeEditor",
"Type": "Editor",
"LoadingPhase": "PostEngineInit",
"PlatformAllowList": [
"Win64",
"Linux",
"Mac"
]
}
],
"Plugins": [
{
"Name": "OnlineSubsystem",
"Enabled": true
},
{
"Name": "OnlineSubsystemUtils",
"Enabled": true
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using UnrealBuildTool;

public class NineRealitiesNetcode : ModuleRules
{
public NineRealitiesNetcode(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PrecompileForTargets = PrecompileTargetsType.Any;

PublicDependencyModuleNames.AddRange(new string[]
{
"Core",
"CoreUObject",
"Engine",
"InputCore",
"Sockets",
"Networking",
"OnlineSubsystem",
"OnlineSubsystemUtils",
"GameplayTags",
"Projects"
});

PrivateDependencyModuleNames.AddRange(new string[]
{
"CoreOnline"
});

// UE5.5+ optimized networking headers
PublicSystemIncludePaths.AddRange(new string[]
{
"$(PluginDir)/Source/NineRealitiesNetcode/Public",
"$(PluginDir)/Source/NineRealitiesNetcode/Public/Core",
"$(PluginDir)/Source/NineRealitiesNetcode/Public/Pipeline",
"$(PluginDir)/Source/NineRealitiesNetcode/Public/UE6"
});

// Enable stricter checks for production netcode
bUseUnity = false;
bEnableExceptions = true;

// UE6 forward compatibility: use C++20 features available in UE5.5+
CppStandard = CppStandardVersion.Cpp20;

// Define version macros for conditional UE6 migration paths
PublicDefinitions.Add("N1_NETCODE_VERSION_MAJOR=3");
PublicDefinitions.Add("N1_NETCODE_VERSION_MINOR=0");
PublicDefinitions.Add("N1_NETCODE_VERSION_PATCH=0");
PublicDefinitions.Add("N1_UE5_5_OR_LATER=1");
PublicDefinitions.Add("N1_UE6_READY=1");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// Copyright (c) 2025-2026 POWDER-RANGER. All Rights Reserved.

#include "Core/N1NetcodeManager.h"
#include "Core/N1NetworkClock.h"
#include "Core/N1PredictionBuffer.h"
#include "Pipeline/N1ReconciliationEngine.h"
#include "Pipeline/N1ClientPrediction.h"
#include "Pipeline/N1ServerAuthority.h"
#include "Pipeline/N1RollbackEngine.h"
#include "Pipeline/N1BlendInterpolator.h"
#include "UE6/N1UE6Compatibility.h"
#include "Engine/World.h"

// Static singleton storage
static TWeakObjectPtr<UN1NetcodeManager> GNetcodeManager;

UN1NetcodeManager::UN1NetcodeManager()
{
CurrentMode = EN1NetcodeMode::Standalone;
CurrentPhase = EN1NetcodePhase::Initializing;
}

void UN1NetcodeManager::Initialize(const FN1NetcodeConfig& InConfig, EN1NetcodeMode InMode)
{
Config = InConfig;
CurrentMode = InMode;

UE_LOG(LogN1Netcode, Log, TEXT("Initializing N1 Netcode Manager [Mode: %s]"),
*UEnum::GetValueAsString(InMode));

// Create subsystems
NetworkClock = NewObject<UN1NetworkClock>(this);
NetworkClock->Initialize(InMode == EN1NetcodeMode::Server || InMode == EN1NetcodeMode::ListenServer);

if (InMode == EN1NetcodeMode::Client || InMode == EN1NetcodeMode::ListenServer)
{
auto* Buffer = NewObject<UN1PredictionBuffer>(this);
int32 BufferFrames = FMath::CeilToInt((Config.MaxAcceptableLatencyMs / 1000.0f) * Config.ClientTickRate) + Config.MaxRollbackFrames;
Buffer->Initialize(BufferFrames, Config.ClientTickRate);

PredictionSystem = NewObject<UN1ClientPrediction>(this);
PredictionSystem->Initialize(Buffer, NetworkClock, Config.ClientTickRate);

RollbackEngine = NewObject<UN1RollbackEngine>(this);
RollbackEngine->Initialize(Config.MaxRollbackFrames);

BlendInterpolator = NewObject<UN1BlendInterpolator>(this);
BlendInterpolator->Initialize(Config.BlendFrames, EN1BlendCurve::SmoothStep);

ReconciliationEngine = NewObject<UN1ReconciliationEngine>(this);
ReconciliationEngine->Initialize(Config.RollbackThreshold, Config.MaxRollbackFrames);
}

if (InMode == EN1NetcodeMode::Server || InMode == EN1NetcodeMode::ListenServer)
{
ServerAuthority = NewObject<UN1ServerAuthority>(this);
ServerAuthority->Initialize(Config.ServerTickRate, Config.InputBufferMs);
}

// UE6 compatibility check
auto* UE6Compat = NewObject<UN1UE6Compatibility>(this);
UE6Compat->Initialize();
UE6Compat->LogCompatibilityStatus();

bInitialized = true;
SetPhase(EN1NetcodePhase::Active);

UE_LOG(LogN1Netcode, Log, TEXT("N1 Netcode Manager initialized successfully"));
}

void UN1NetcodeManager::Shutdown()
{
SetPhase(EN1NetcodePhase::ShuttingDown);

PredictionSystem = nullptr;
ReconciliationEngine = nullptr;
RollbackEngine = nullptr;
BlendInterpolator = nullptr;
ServerAuthority = nullptr;
NetworkClock = nullptr;

bInitialized = false;
GNetcodeManager.Reset();

UE_LOG(LogN1Netcode, Log, TEXT("N1 Netcode Manager shutdown complete"));
}

void UN1NetcodeManager::Tick(float DeltaTime)
{
if (!bInitialized) return;

// Update network clock
if (NetworkClock)
{
NetworkClock->Tick(DeltaTime);
}

// Tick client systems
if (PredictionSystem)
{
PredictionSystem->Tick(DeltaTime);
}

if (BlendInterpolator)
{
BlendInterpolator->Tick(DeltaTime);
}

// Server tick
if (ServerAuthority)
{
ServerAuthority->TickServer(DeltaTime);
}

// Periodic forced reconciliation
if (Config.ForcedReconciliationIntervalSec > 0)
{
PerformForcedReconciliation(DeltaTime);
}
}

UN1NetcodeManager* UN1NetcodeManager::GetN1Manager(UWorld* World)
{
if (GNetcodeManager.IsValid())
{
return GNetcodeManager.Get();
}

if (World)
{
UN1NetcodeManager* Manager = NewObject<UN1NetcodeManager>(World);
GNetcodeManager = Manager;
return Manager;
}

return nullptr;
}

void UN1NetcodeManager::SetPhase(EN1NetcodePhase NewPhase)
{
if (CurrentPhase != NewPhase)
{
EN1NetcodePhase OldPhase = CurrentPhase;
CurrentPhase = NewPhase;
OnPhaseChanged.Broadcast(NewPhase);
UE_LOG(LogN1Netcode, Verbose, TEXT("Phase transition: %s -> %s"),
*UEnum::GetValueAsString(OldPhase),
*UEnum::GetValueAsString(NewPhase));
}
}

void UN1NetcodeManager::PerformForcedReconciliation(float DeltaTime)
{
ForcedReconciliationTimer += DeltaTime;
if (ForcedReconciliationTimer >= Config.ForcedReconciliationIntervalSec)
{
ForcedReconciliationTimer = 0.0f;
UE_LOG(LogN1Netcode, Verbose, TEXT("Performing forced periodic reconciliation"));
// This would trigger a full-state resync in production
}
}
Loading
Loading