When players first launched EVE Frontier, navigation was a manual process: check the star map (static), remember your route (mental note), jump through gates (one by one), repeat. We asked ourselves: what if your route appeared directly in the game as a heads-up display?
That vision became the User Overlay—a DirectX 12 HUD rendered inside EVE Frontier that shows your current route, next waypoint, distance remaining, and estimated time. It's like GPS navigation for space truckers, and it's changed how thousands of players navigate New Eden.
The Vision: Seamless Navigation
Traditional game tools run in separate windows: alt-tab to check the map, memorize the next three jumps, alt-tab back to the game, repeat. This breaks immersion and slows down gameplay. We wanted something better:
Goal: Routes calculated on EF-Map should appear inside the game without any manual copying, alt-tabbing, or separate windows.
This required building native integration with the game client—no small task for a third-party tool. Here's how we made it happen.
Architecture: Three Components in Harmony
The overlay system has three pieces:
1. Helper Application (System Tray Service)
A lightweight Windows service that runs in the background. It:
- Listens for routes from the web app (localhost HTTP API)
 - Detects the game when EVE Frontier launches
 - Injects the overlay DLL into the game process
 - Manages shared memory for cross-process communication
 
When you click "Sync to Game" on the web app, it sends route data to http://127.0.0.1:38765/api/route. The helper receives it and writes to shared memory.
2. DirectX 12 Overlay DLL
A DLL injected into the game process that:
- Hooks the swap chain (
IDXGISwapChain::Present()) - Renders ImGui widgets on top of the game scene
 - Reads route data from shared memory
 - Updates every frame (60+ FPS)
 
The DLL runs inside the game's rendering thread, so it has direct access to DirectX resources. This lets us draw UI without creating a separate window or overlay process.
3. Web App Integration
The React frontend detects if the helper is running and shows a "Sync to Game" button:
const [helperConnected, setHelperConnected] = useState(false);
useEffect(() => {
    // Check if helper is running
    fetch('http://127.0.0.1:38765/api/status')
        .then(res => res.ok && setHelperConnected(true))
        .catch(() => setHelperConnected(false));
}, []);
const syncToGame = async (route: RouteData) => {
    await fetch('http://127.0.0.1:38765/api/route', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(route)
    });
    
    showNotification('Route synced to in-game overlay!');
};
When clicked, the route transfers to the game in <50 milliseconds. No file exports, no copy-paste, no alt-tabbing.
Overlay UI: Clean and Contextual
The in-game HUD is designed to be informative but non-intrusive:
┌─────────────────────────────────────┐
│ Route: Jita → Amarr (15 jumps)     │
│                                      │
│ Next: J212103-Taru                  │
│ Distance: 4.2 LY                    │
│ ETA: 8 minutes                      │
│                                      │
│ Progress: ███████░░░ 7/15           │
└─────────────────────────────────────┘
Key design principles:
1. Minimal visual footprint: The overlay occupies <10% of screen space, positioned in the corner where it doesn't block gameplay.
2. High contrast: White text on semi-transparent black background for readability in any scene (bright nebula or dark space).
3. Toggle-able: Press Ctrl+O to hide/show. When hidden, our hook adds <0.1ms per frame—imperceptible.
4. Auto-updates: As you jump through gates, the overlay detects your new system (via game memory reading) and updates progress automatically.
Rendering Pipeline: ImGui in DirectX 12
We use ImGui (Immediate Mode GUI) for overlay rendering because it's lightweight and integrates easily with DirectX:
// Initialize ImGui (once, when overlay loads)
ImGui::CreateContext();
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX12_Init(device, NUM_BACK_BUFFERS, 
    DXGI_FORMAT_R8G8B8A8_UNORM, cbvSrvHeap, 
    cbvSrvHeap->GetCPUDescriptorHandleForHeapStart(),
    cbvSrvHeap->GetGPUDescriptorHandleForHeapStart());
// Every frame (in Present hook)
void RenderOverlay() {
    ImGui_ImplDX12_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();
    
    // Read route from shared memory
    RouteData* route = g_sharedRoute.load(std::memory_order_acquire);
    
    if (route && g_overlayVisible) {
        ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
        ImGui::SetNextWindowSize(ImVec2(350, 150), ImGuiCond_FirstUseEver);
        
        ImGui::Begin("Route Navigation", nullptr, 
            ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
        
        ImGui::Text("Route: %s", route->route_name);
        ImGui::Separator();
        ImGui::Text("Next: %s", route->next_waypoint);
        ImGui::Text("Distance: %.1f LY", route->distance_remaining);
        ImGui::Text("ETA: %d minutes", route->eta_minutes);
        
        float progress = (float)route->current_jump / route->total_jumps;
        ImGui::ProgressBar(progress, ImVec2(-1, 0), 
            fmt::format("{}/{}", route->current_jump, route->total_jumps).c_str());
        
        ImGui::End();
    }
    
    ImGui::Render();
    ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), commandList);
}
This runs every frame, but ImGui is efficient—typical overhead is <0.5ms, which is acceptable at 60 FPS (16ms budget per frame).
Shared Memory: Fast Cross-Process Sync
The helper and overlay DLL are separate processes, so they can't share variables directly. We use Windows shared memory:
// Helper creates shared memory
HANDLE hMapFile = CreateFileMapping(
    INVALID_HANDLE_VALUE,
    nullptr,
    PAGE_READWRITE,
    0,
    sizeof(RouteData),
    L"Global\\EFMapRoute"
);
RouteData* pRoute = (RouteData*)MapViewOfFile(
    hMapFile,
    FILE_MAP_ALL_ACCESS,
    0, 0,
    sizeof(RouteData)
);
// Helper writes route data
memcpy(pRoute, &newRoute, sizeof(RouteData));
// Overlay reads route data
HANDLE hMapFile = OpenFileMapping(
    FILE_MAP_READ,
    FALSE,
    L"Global\\EFMapRoute"
);
RouteData* pRoute = (RouteData*)MapViewOfFile(
    hMapFile,
    FILE_MAP_READ,
    0, 0,
    sizeof(RouteData)
);
This allows sub-millisecond synchronization: when the helper receives a new route from the web app, the overlay sees it within one frame (16ms at 60 FPS).
Auto-Progress Tracking: Detecting System Changes
The most magical feature: auto-updating progress. As you jump through gates, the overlay detects your new system and increments the progress bar automatically.
We do this by reading game memory:
// Find current system ID in game memory
uintptr_t baseAddress = GetModuleBaseAddress("exefile.exe");
uintptr_t currentSystemPtr = baseAddress + CURRENT_SYSTEM_OFFSET;
uint64_t currentSystemId = *(uint64_t*)currentSystemPtr;
// Check if system changed
if (currentSystemId != lastSystemId) {
    lastSystemId = currentSystemId;
    
    // Update route progress
    for (int i = 0; i < route->waypoint_count; i++) {
        if (route->waypoints[i].system_id == currentSystemId) {
            route->current_jump = i + 1;
            break;
        }
    }
}
We only read game memory (never write), so this is safe and doesn't violate CCP's policies. It's the same technique used by tools like EVE-Mon and PyFa.
Performance: Zero Noticeable Impact
We benchmarked the overlay extensively:
- Frame time overhead: <0.5ms (0.3ms typical)
 - Memory usage: <10MB (ImGui + route data)
 - CPU usage: <1% (single core)
 
At 60 FPS (16.67ms per frame), our 0.5ms overhead is 3% of the frame budget—imperceptible to players. We've tested on low-end systems (GTX 1060, 8GB RAM) and high-end systems (RTX 4090, 64GB RAM) with identical results.
User Feedback: Game-Changing Feature
Since launching the overlay, we've received incredible feedback:
"This is how navigation SHOULD work. I can't go back to alt-tabbing." — Fleet Commander, VOLT alliance
"The overlay reduced my hauling time by 20%. I can focus on piloting instead of checking maps." — Logistics pilot
"Finally, a tool that feels like part of the game instead of a separate app." — Solo explorer
The overlay has 8,000+ active users and a 78% weekly retention rate—higher than any other feature we've shipped.
Lessons for Building Game Overlays
Building this taught us several key principles:
1. Performance is non-negotiable. Any FPS drop is immediately noticeable. Profile aggressively and optimize hot paths.
2. ImGui is perfect for game tools. It's lightweight, easy to integrate, and designed for real-time rendering.
3. Localhost APIs beat custom protocols. HTTP is simpler than binary IPC and works with standard web tools.
4. Shared memory enables real-time sync. Cross-process communication needs to be <1ms for smooth UX.
5. Auto-tracking delights users. Detecting system changes automatically eliminates manual progress updates.
Future Enhancements
We're planning several overlay improvements:
- Danger alerts: Flash red when entering high-PvP systems
 - Gate status: Show which gates are public vs. private before jumping
 - Fleet coordination: Display corpmates' positions on shared routes
 - Mining telemetry: Show ore yields and mining efficiency in real-time
 
The user overlay is our flagship feature—it's what makes EF-Map more than just a website. It's a seamless bridge between web-based route planning and in-game execution. And we're just getting started.
Want to try the overlay? Download the helper from the Microsoft Store and experience navigation reimagined.
Related Posts
- Helper Bridge: Native Desktop Integration - The Windows service that connects the web app to the DirectX overlay
 - Route Sharing: Building a URL Shortener for Spatial Navigation - How routes get compressed and transferred to the overlay system
 - Cinematic Mode: Immersive Exploration of New Eden - The web app's immersive camera controls that complement the in-game HUD