Game
CaveVox
5 days ago

Hi everyone! This is the 11th devlog for CaveVox. This time, I’ll be talking about the multiplayer aspects of the game. I also think I’m still on track to finish all the core features for Early Access, which is planned for mid-February. Before that, Devlog 12 will be released, where I’ll share more details. After Early Access, a large update is planned for March.

I’m also happy to announce that CaveVox will participate in Medieval Fest 2026, from April 20 to April 27.

Multiplayer

With the core foundations of the game completed, I moved on to implementing the multiplayer mode, which took about a week of focused work.

As you know, I’m using Godot, which provides several levels of network functionality:

  • Low-level API (ENet / PacketPeer / StreamPeer) — full control over protocol and logic;

  • High-level Multiplayer API — replication, authority, ownership;

  • RPC — function calls between clients and server;

  • MultiplayerSynchronizer — automatic node state synchronization.

However, I took a different approach: the default Godot networking stack proved too limiting for CaveVox, and since I actively use Rust, I built a bridge between the engine and a separate server using Quinn.

What is Quinn?
Quinn is a compact library for the QUIC protocol — a modern transport layer over UDP that combines TCP-like reliability, stream multiplexing, built-in encryption, and low connection latency.

QUIC allows you to:

  • use UDP without its traditional limitations;

  • have multiple independent streams within a single connection without head-of-line blocking;

  • send both reliable and unreliable messages;

  • establish connections faster compared to TCP + TLS;

  • manage separate channels for different traffic types (player input, events, snapshots, chat).

In short, QUIC is a modern hybrid of the best features of TCP and UDP, designed for realtime applications and networked games.

For an FPS-roguelike, this is critical: high update rates, predictable latency, independent channels for important and secondary messages, and full control over server logic.

250125_1.png

Co-op

Since the game is planned as a four-player co-op, I designed the server primarily as a relay. Incoming messages from clients are simply forwarded to other session participants without heavy simulation on the server side.

This is called a relay architecture: the server acts as a central routing node, ensuring packet delivery and message ordering where needed, and synchronizing clients without taking over full game logic.

This reduces server load, simplifies scaling, and keeps latency minimal — crucial for co-op FPS games where responsiveness and accuracy matter.

For example, if client A turns off a torch, the server just forwards the event to everyone else, and their torches turn off as well. The server has no authority or validation, since in a small four-player co-op, that’s unnecessary — operations are delivered as quickly as possible.

Also, a Steam client is required for multiplayer, as the game is tied to Steam to obtain player nicknames. Without it, the player won’t appear in the lobby. I’ve also added nickname display above characters and plan to add more convenience features over time.

250125_0.png

Datagrams

Some operations — like player movement, animations, and rotations — are transmitted via datagrams.

Datagrams are small packets with no guaranteed delivery or ordering, sent at high frequency. They may be lost in transit, but constant state updates in subsequent packets keep synchronization intact: position and orientation are simply corrected with fresh data.

This method is ideal for realtime data, where timeliness is more important than 100% reliability.

Bidirectional Streams

All critical operations — such as player connections, action confirmations, damage, deaths, or object activation — are sent over separate reliable channels with guaranteed delivery and ordering.

In QUIC, this is implemented via bidirectional streams: independent two-way streams within a single connection that do not block each other, isolating different types of traffic. Loss or delay in one stream does not affect others — perfect for games.

Using this system, I implemented:

  • a full player lobby;

  • world sharing via a common generation seed;

  • position synchronization;

  • object interaction synchronization.

This is especially efficient because clients generate identical worlds deterministically. As a result, only minimal data — events and adjustments — is sent over the network, keeping the server lightweight and simple.

Other changes

  • Updated tree generation using caches and threads for faster generation;

  • Added new tree types — spruce and oak on the surface (screenshot);

  • Fixed surface level name display when entering/exiting dungeons;

  • Added render queue based on player position — renders areas near the player first;

  • Added chunk unloading based on player level — only the nearest 3 levels are rendered, distant chunks are unloaded;

  • Optimized resource loading at game start using threads;

  • Optimized chunk threads to reduce blocking, significantly speeding up rendering;

  • Added all basic player animations (walking in four directions, falling, jumping), integrated into game logic;

  • Numerous fixes to the game menu, game start, and background processes (previously some algorithms were running in the background);

  • Fixed audio occlusion — now tied to the active player;

  • Completed all static parts of the surface above the dungeon (currently no NPCs or logic, to be added in the next update).

Conclusion

There’s still a lot of work ahead on multiplayer and core player mechanics. I hope this devlog was informative — thanks for reading!

250125_2.gif


0 comments

Loading...

Next up

Dynamic Player Animations in My Game #gamedev #animations #game #gameplay

Tree & Grass in My Game #cavevox #voxel #indie

Slime Jumping in My Game #gamedev #animations #game #gameplay

Network Gameplay Sync in My Game #networking #multiplayer #online #coop #fps #gameplay

I love writing generation for moments like this. #cavevox #generation #voxel

Different Shadow Types in My Game #3d #render #shadows #voxel #dynamic #animation

Working on player animations #cavevox #indie #animations

Just as Pecaminosa's musicians #improvise this rendition of #LittleSunflower 🌻, so do we improvise with this post you're reading. 😂

What's coming out of your own improvs? 🤔

#Pecaminosa | #IndieDev | #OST | #Jazz

Today I was setting up the location of the first boss. His name is "Father" and he is the first of the Patagonians. His task is to guard the road to the House.🛡🗡 Bookmark pre-launch page🔖🔖🔖

https://www.kickstarter.com/projects/rdvindiegame/the-patagonian…