<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kohan Mathers</title>
    <description>The latest articles on Forem by Kohan Mathers (@kohanmathers).</description>
    <link>https://forem.com/kohanmathers</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3716068%2F185d0bad-20e4-46cd-9d13-dc3f18e8db02.jpeg</url>
      <title>Forem: Kohan Mathers</title>
      <link>https://forem.com/kohanmathers</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kohanmathers"/>
    <language>en</language>
    <item>
      <title>Stop Reinventing Multiplayer Netcode — Here's How I Built a Universal Protocol</title>
      <dc:creator>Kohan Mathers</dc:creator>
      <pubDate>Sat, 17 Jan 2026 07:14:32 +0000</pubDate>
      <link>https://forem.com/kohanmathers/stop-reinventing-multiplayer-netcode-heres-how-i-built-a-universal-protocol-117f</link>
      <guid>https://forem.com/kohanmathers/stop-reinventing-multiplayer-netcode-heres-how-i-built-a-universal-protocol-117f</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I got tired of every game needing custom netcode, so I built Project Neon — a minimal UDP protocol that works for &lt;em&gt;any&lt;/em&gt; multiplayer game. 8-byte header, zero assumptions about your game logic, and you define your own packets. MIT licensed, works with Unity/Unreal/Godot via JNI.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;You want to add multiplayer to your game. Simple, right?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1:&lt;/strong&gt; Use a library (Photon, Mirror, Netcode for GameObjects)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Fast to get started&lt;/li&gt;
&lt;li&gt;❌ Vendor lock-in&lt;/li&gt;
&lt;li&gt;❌ Black box you can't modify&lt;/li&gt;
&lt;li&gt;❌ Doesn't work with your custom engine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Option 2:&lt;/strong&gt; Roll your own&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Full control&lt;/li&gt;
&lt;li&gt;❌ You're implementing TCP handshakes in 2026&lt;/li&gt;
&lt;li&gt;❌ NAT traversal is &lt;em&gt;still&lt;/em&gt; a nightmare&lt;/li&gt;
&lt;li&gt;❌ You just reinvented the same connection management everyone else has&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's no middle ground. Either you get a bloated framework with RPCs and state sync you don't need, or you're writing raw socket code and debugging why packets disappear behind your router.&lt;/p&gt;

&lt;h2&gt;
  
  
  What If We Just... Didn't?
&lt;/h2&gt;

&lt;p&gt;Here's the insight: &lt;strong&gt;Every multiplayer game needs connection management. Zero games need the same game logic.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I built Project Neon with one rule: &lt;em&gt;The protocol should know nothing about your game.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;NeonPacket&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;PacketHeader&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// 8 bytes - that's it&lt;/span&gt;
    &lt;span class="nc"&gt;PacketPayload&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="c1"&gt;// Your game, your rules&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The header:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Magic number (are you even talking Project Neon?)&lt;/li&gt;
&lt;li&gt;Version (protocol compatibility)&lt;/li&gt;
&lt;li&gt;Packet type (0x01-0x0F reserved, 0x10+ yours)&lt;/li&gt;
&lt;li&gt;Sequence number (for ordering/reliability)&lt;/li&gt;
&lt;li&gt;Client ID + Destination (who's talking, who's listening)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;That's it.&lt;/strong&gt; The relay doesn't parse your payloads. It doesn't care if you're sending player positions, chess moves, or Minecraft blocks. It just routes bytes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show Me Code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Client connects to a session:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;NeonClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NeonClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PlayerName"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"relay.example.com:7777"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connected! My ID: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClientId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

    &lt;span class="c1"&gt;// Game loop&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameRunning&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;processPackets&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Handle incoming&lt;/span&gt;
        &lt;span class="n"&gt;updateGame&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;            &lt;span class="c1"&gt;// Your logic&lt;/span&gt;
        &lt;span class="n"&gt;sendGameState&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// Your packets&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Define your own packet:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// You decide what this looks like&lt;/span&gt;
&lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;PlayerMovement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;playerId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;velocityX&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;velocityY&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;velocityZ&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="nf"&gt;serialize&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;ByteBuffer&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ByteBuffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;allocate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;putInt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playerId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;putFloat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;putFloat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;putFloat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;putFloat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;velocityX&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;putFloat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;velocityY&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;putFloat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;velocityZ&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;array&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Send it&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendGamePacket&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;movement&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;serialize&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 0 = broadcast&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;That's the entire API.&lt;/strong&gt; No inheritance, no component system, no "NetworkBehaviour" base class. Just packets.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture (It's Actually Simple)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌────────┐         ┌───────┐         ┌────────┐
│ Client │ ─────→  │ Relay │  ─────→ │  Host  │
└────────┘         └───────┘         └────────┘
                       │
                       ↓
              (broadcasts to others)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why a relay?&lt;/strong&gt; NAT traversal. Your game works behind routers without port forwarding. The relay is dumb and fast — it validates the 8-byte header and forwards raw bytes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client-Server or Peer-to-Peer?&lt;/strong&gt; Yes. The "host" is just another client with special privileges. You decide if it's authoritative or if clients trust each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Talk: What This &lt;em&gt;Doesn't&lt;/em&gt; Do
&lt;/h2&gt;

&lt;p&gt;Project Neon is &lt;strong&gt;not&lt;/strong&gt; a game networking framework. It's infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You still need to implement:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Player synchronization (positions, animations)&lt;/li&gt;
&lt;li&gt;❌ Client-side prediction / server reconciliation&lt;/li&gt;
&lt;li&gt;❌ Lag compensation&lt;/li&gt;
&lt;li&gt;❌ Authentication (there's no passwords — you add that)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What you get:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Connection management (connect, disconnect, reconnect)&lt;/li&gt;
&lt;li&gt;✅ Session handling (relay routes everything)&lt;/li&gt;
&lt;li&gt;✅ Packet ordering (sequence numbers in header)&lt;/li&gt;
&lt;li&gt;✅ Optional reliability (ACK/retry utility for critical packets)&lt;/li&gt;
&lt;li&gt;✅ Rate limiting (relay blocks floods)&lt;/li&gt;
&lt;li&gt;✅ Metrics (latency tracking, packet counts)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it like &lt;strong&gt;Express.js for game networking.&lt;/strong&gt; It handles the boring parts (sockets, routing, lifecycle) so you can focus on your game.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-Engine? Yeah.
&lt;/h2&gt;

&lt;p&gt;Java core with JNI bindings for C/C++. Works with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unity (call via JNI or run Java directly)&lt;/li&gt;
&lt;li&gt;Unreal Engine (link &lt;code&gt;libneon_jni.so&lt;/code&gt; as ThirdParty)&lt;/li&gt;
&lt;li&gt;Godot (GDNative/GDExtension)&lt;/li&gt;
&lt;li&gt;Custom C++ engines&lt;/li&gt;
&lt;li&gt;Literally anything that can call C functions
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// C API example&lt;/span&gt;
&lt;span class="n"&gt;NeonClientHandle&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;neon_client_new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PlayerName"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;neon_client_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1:7777"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game_running&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;neon_client_process_packets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// your game loop&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;neon_client_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Security: Let's Be Honest
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Project Neon has no encryption.&lt;/strong&gt; It's plaintext UDP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt; Because encryption adds latency, and for LAN parties or trusted networks, you don't need it. For internet deployment, you should:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run the relay behind a VPN/firewall&lt;/li&gt;
&lt;li&gt;Implement app-layer encryption (AES-GCM) for sensitive data&lt;/li&gt;
&lt;li&gt;Add authentication in your game code (use the &lt;code&gt;gameIdentifier&lt;/code&gt; field)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There's a 3000-word &lt;a href="https://github.com/Quiet-Terminal-interactive/ProjectNeon/blob/main/SECURITY.md" rel="noopener noreferrer"&gt;SECURITY.md&lt;/a&gt; that breaks down every threat and mitigation. &lt;strong&gt;Read it before deploying to the internet.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;UDP is also unreliable (packets get lost). You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the built-in &lt;code&gt;ReliablePacketManager&lt;/code&gt; for critical events&lt;/li&gt;
&lt;li&gt;Send redundantly (position updates every frame don't need ACKs)&lt;/li&gt;
&lt;li&gt;Implement your own ACK logic with sequence numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Latency budget:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network RTT: 20-50ms (LAN) / 50-200ms (internet)&lt;/li&gt;
&lt;li&gt;Relay forwarding: &amp;lt;1ms&lt;/li&gt;
&lt;li&gt;Packet serialization: &amp;lt;0.1ms&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total added overhead: ~1ms&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Throughput:&lt;/strong&gt;&lt;br&gt;
Example with 32 clients, 30 packets/sec, 200 bytes/packet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Per-client: 6 KB/s&lt;/li&gt;
&lt;li&gt;Relay total: ~6 MB/s (with broadcast)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The relay is single-threaded and handles 1000+ packets/sec easily. For higher loads, run multiple relays with session-based load balancing.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone and build&lt;/span&gt;
git clone https://github.com/Quiet-Terminal-interactive/ProjectNeon
&lt;span class="nb"&gt;cd &lt;/span&gt;ProjectNeon
mvn clean package

&lt;span class="c"&gt;# Run relay&lt;/span&gt;
java &lt;span class="nt"&gt;-jar&lt;/span&gt; target/neon-relay.jar

&lt;span class="c"&gt;# Run example host (new terminal)&lt;/span&gt;
java &lt;span class="nt"&gt;-jar&lt;/span&gt; target/neon-host.jar 12345

&lt;span class="c"&gt;# Run example client (new terminal)&lt;/span&gt;
java &lt;span class="nt"&gt;-jar&lt;/span&gt; target/neon-client.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Maven integration:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.quietterminal&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;project-neon&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.1.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full docs: &lt;a href="https://github.com/Quiet-Terminal-interactive/ProjectNeon" rel="noopener noreferrer"&gt;github.com/Quiet-Terminal-interactive/ProjectNeon&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;This is v1.1.0 (Beta). The roadmap includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Session persistence (survive relay restarts)&lt;/li&gt;
&lt;li&gt;[ ] DTLS support (optional encryption)&lt;/li&gt;
&lt;li&gt;[ ] NAT traversal (STUN/TURN integration)&lt;/li&gt;
&lt;li&gt;[ ] WebSocket relay variant (browser games)&lt;/li&gt;
&lt;li&gt;[ ] Prometheus metrics endpoint&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the core is stable. I've been using it for a Minecraft multiplayer plugin and it just works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;I got tired of seeing the same connection logic rewritten in every game. TCP handshakes, UDP reliability layers, session management — it's solved problems, yet every engine makes you start from scratch.&lt;/p&gt;

&lt;p&gt;Project Neon is my answer: &lt;strong&gt;Minimal infrastructure so you can build games, not protocols.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're building a multiplayer game and don't want vendor lock-in or to reinvent sockets, give it a shot. It's MIT licensed, well-documented, and designed to get out of your way.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/Quiet-Terminal-interactive/ProjectNeon" rel="noopener noreferrer"&gt;https://github.com/Quiet-Terminal-interactive/ProjectNeon&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://github.com/Quiet-Terminal-interactive/ProjectNeon#readme" rel="noopener noreferrer"&gt;README&lt;/a&gt; | &lt;a href="https://github.com/Quiet-Terminal-interactive/ProjectNeon/blob/main/ARCHITECTURE.md" rel="noopener noreferrer"&gt;Architecture&lt;/a&gt; | &lt;a href="https://github.com/QuietTerminal/ProjectNeon/blob/main/SECURITY.md" rel="noopener noreferrer"&gt;Security&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Questions?&lt;/strong&gt; Open an issue or email &lt;a href="mailto:kohanmathersmcgonnell@gmail.com"&gt;kohanmathersmcgonnell@gmail.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>gamedev</category>
      <category>java</category>
      <category>networking</category>
    </item>
  </channel>
</rss>
