| name | subnautica-2-deep-synergy-multiplayer-mod |
| description | BepInEx multiplayer mod for Subnautica 2 enabling co-op gameplay with synchronized sessions, shared bases, and dynamic scaling |
| triggers | ["install subnautica 2 multiplayer mod","setup deep synergy coop mod","configure bepinex subnautica multiplayer","create subnautica 2 coop session","troubleshoot subnautica multiplayer sync","customize subnautica mod settings","enable subnautica 2 shared gameplay","add ai narration to subnautica mod"] |
Subnautica 2 Deep Synergy Multiplayer Mod
Skill by ara.so — Devtools Skills collection.
Overview
The Deep Synergy Multiplayer Mod transforms Subnautica 2 from a solo survival experience into a synchronized cooperative game. Built on the BepInEx modding framework, it implements:
- Deterministic Session Synchronization (DSS): Conflict-resolved world state sharing across clients
- Adaptive Dynamic Scaling (ADS): Adjusts difficulty based on player count
- Decentralized Architecture: Peer-to-peer connectivity without central servers
- Cross-Platform Support: Windows, Linux (Steam Deck), macOS via WebRTC NAT punch-through
- Shared Inventory & Base Building: Merkle tree-based integrity verification
- Optional AI Integration: OpenAI/Claude API for dynamic narrative generation
Installation
Prerequisites
- Subnautica 2 installed via Steam or GOG
- BepInEx 6.0.x for Unity IL2CPP games
BepInEx Setup
cd "C:\Program Files (x86)\Steam\steamapps\common\Subnautica 2"
cd ~/.steam/steam/steamapps/common/Subnautica\ 2
Mod Installation
cd BepInEx/plugins/
ls -la
First Launch
Subnautica2.exe
./Subnautica2.x86_64
Configuration
Profile Configuration
Create BepInEx/config/synergy_profile.json:
{
"session_name": "Ocean Explorers",
"max_players": 4,
"difficulty_scale": "adaptive",
"resource_multiplier": 1.0,
"oxygen_consumption": 1.0,
"creature_spawn_divider": 1,
"enable_pvp": false,
"friendly_fire": false,
"shared_blueprints": true,
"ping_locations_shared": true,
"time_of_day_sync": "host",
"voice_chat_integration": "none",
"network": {
"port":
Key Configuration Fields
| Field | Type | Description |
|---|
max_players | int | 2-8 players per session |
difficulty_scale | string | "adaptive", "fixed", or "manual" |
resource_multiplier | float | Scales harvestable resources (0.5 = half, 2.0 = double) |
oxygen_consumption | float | Fraction of normal O2 drain (0.8 = 20% slower) |
creature_spawn_divider | int | Divides creature spawn count (2 = half as many) |
shared_blueprints | bool | Blueprint unlocks apply to all players |
time_of_day_sync | string | "host", "vote", or "independent" |
Console Commands
Access via BepInEx console (F1 by default):
Session Management
/start_server
/join_session 9B2A-4C7D-E8F1
/leave_session
/synergy_status
Gameplay Adjustments
/synergy_scale 1.5
/seed_override 8251
/force_sync inventory
/tp_to PlayerName
AI Narration (if enabled)
/api_narrate "exploring the underwater caves"
/api_creature_log "ghostray"
/api_hint "cyclops upgrade"
Programming API (For Mod Developers)
Creating Custom Session Hooks
using BepInEx;
using DeepSynergy.Core;
using DeepSynergy.Network;
namespace MyCustomMod
{
[BepInPlugin("com.example.customsession", "Custom Session Hook", "1.0.0")]
[BepInDependency("com.deepsynergy.core", BepInDependency.DependencyFlags.HardDependency)]
public class CustomSessionPlugin : BaseUnityPlugin
{
private void Awake()
{
SessionManager.OnPlayerJoined += OnPlayerJoinedHandler;
SessionManager.OnItemPickup += OnItemPickupHandler;
SessionManager.OnBasePartPlaced += OnBasePartHandler;
}
private void OnPlayerJoinedHandler(PlayerSession player)
{
Logger.LogInfo($"Player {player.Name} joined from {player.IPAddress}");
NetworkMessenger.SendToPlayer(player.PeerId, new WelcomeMessage
{
Text = $"Welcome to the abyss, {player.Name}!",
Color = UnityEngine.Color.cyan
});
}
private void OnItemPickupHandler(ItemPickupEvent evt)
{
Logger.LogInfo($"{evt.PlayerName} picked up {evt.ItemType} at {evt.Position}");
StateSync.BroadcastItemState(evt.ItemGuid, evt.InventorySlot);
}
{
(BaseValidator.IsValidPlacement(evt.PartType, evt.Position, evt.Rotation))
{
StateSync.BroadcastBasePart(evt);
}
{
Logger.LogWarning();
NetworkMessenger.SendToPlayer(evt.PlayerId, PlacementError
{
Reason =
});
}
}
}
}
Custom Inventory Sync
using DeepSynergy.Inventory;
using System.Collections.Generic;
public class CustomInventoryManager
{
private InventoryMerkleTree _merkleTree;
public void SyncCustomContainer(string containerId, List<Item> items)
{
var containerHash = _merkleTree.HashContainer(containerId, items);
var syncPacket = new ContainerSyncPacket
{
ContainerId = containerId,
MerkleRoot = containerHash,
Items = items.Select(i => new ItemState
{
Guid = i.Guid,
TechType = i.TechType,
StackSize = i.StackSize,
Metadata = i.SerializeMetadata()
}).ToList()
};
NetworkMessenger.Broadcast(syncPacket);
}
public bool VerifyContainerIntegrity(string containerId, byte[] receivedHash)
{
var localHash = _merkleTree.GetContainerHash(containerId);
return localHash.SequenceEqual(receivedHash);
}
}
AI Integration Example
using DeepSynergy.AI;
using System.Threading.Tasks;
public class NarrativeEngine
{
private OpenAIClient _openai;
private ClaudeClient _claude;
public async Task<string> GenerateExplorationNarrative(ExplorationEvent evt)
{
if (!ConfigManager.GetBool("api_integration.openai.enabled"))
return null;
var prompt = $@"The player has discovered a new biome: {evt.BiomeName}
Depth: {evt.Depth}m
Notable features: {string.Join(", ", evt.Features)}
Previous context: {evt.RecentHistory}
Generate a 2-sentence journal entry in the style of a marine biologist.";
var response = await _openai.GenerateCompletion(new OpenAIRequest
{
Model = "gpt-4",
Prompt = prompt,
MaxTokens = 100,
Temperature = 0.7,
ApiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")
});
return response.Choices[0].Text.Trim();
}
public async Task<CreatureDataLog> GenerateCreatureLog(string creatureTechType)
{
if (!ConfigManager.GetBool("api_integration.claude.enabled"))
return null;
prompt = ;
response = _claude.SendMessage( ClaudeRequest
{
Model = ,
Messages = [] { Message { Role = , Content = prompt } },
MaxTokens = ,
ApiKey = Environment.GetEnvironmentVariable()
});
JsonConvert.DeserializeObject<CreatureDataLog>(response.Content[].Text);
}
}
Common Patterns
Hosting a Session
nano BepInEx/config/synergy_profile.json
/start_server
/synergy_status
Joining a Session
/join_session 9B2A-4C7D-E8F1
/synergy_status
Adjusting Difficulty Mid-Session
{
"difficulty_scale": "adaptive",
"resource_multiplier": 0.8,
"creature_spawn_divider": 1
}
/reload_config
/synergy_scale 1.3
Enabling AI Narration
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
{
"api_integration": {
"openai": {
"enabled": true,
"role": "narrator"
},
"claude": {
"enabled": true,
"role": "lore_engine"
}
}
}
/api_narrate "discovered precursor artifact"
Troubleshooting
Session Connection Failed
Symptom: /join_session returns "Connection timeout"
Solutions:
sudo ufw allow 7777/tcp
/network_debug
/join_direct 192.168.1.100:7777
"network": {
"port": 7777, // Try different port if blocked
"use_upnp": true // Enable automatic port forwarding
}
Inventory Desync
Symptom: Items appear in different slots for different players
Solutions:
/force_sync inventory
/verify_merkle
/rebuild_merkle
/leave_session
/join_session <code>
Base Parts Not Syncing
Symptom: Placed base parts invisible to other players
Solutions:
/synergy_status
/force_sync base
/base_debug
"network": {
"timeout_seconds": 60 // Increase for slow connections
}
High Latency Issues
Symptom: Actions appear delayed for other players
Solutions:
/synergy_status
"max_players": 2 // Less bandwidth per player
"api_integration": {
"openai": { "enabled": false },
"claude": { "enabled": false }
}
"network": {
"sync_rate_hz": 10 // Default 20, lower = less bandwidth
}
Mod Not Loading
Symptom: No multiplayer menu appears in-game
Solutions:
cat BepInEx/LogOutput.log | grep "Deep Synergy"
ls BepInEx/plugins/
rm -rf BepInEx/cache/
API Integration Not Working
Symptom: /api_narrate returns "API disabled"
Solutions:
echo $OPENAI_API_KEY
echo $ANTHROPIC_API_KEY
cat BepInEx/config/synergy_profile.json
/api_test openai
Advanced Configuration
Custom Network Settings
{
"network": {
"port": 7777,
"use_upnp": true,
"stun_servers": [
"stun.l.google.com:19302",
"stun.stunprotocol.org:3478"
],
"max_latency_ms": 150,
"timeout_seconds": 30,
"sync_rate_hz": 20,
"compression": "lz4",
"encryption": "aes256"
}
}
Difficulty Presets
{
"difficulty_presets": {
"casual": {
"resource_multiplier": 1.5,
"oxygen_consumption": 0.7,
"creature_spawn_divider": 2
},
"hardcore": {
"resource_multiplier": 0.5,
"oxygen_consumption": 1.3,
"creature_spawn_divider": 1
}
},
"active_preset": "casual"
}
Localization
{
"locale": "en-US",
"available_locales": [
"en-US", "zh-CN", "ja-JP", "de-DE",
"fr-FR", "pt-BR", "ru-RU", "es-LA", "ko-KR"
]
}
File Locations
- Config:
BepInEx/config/synergy_profile.json
- Logs:
BepInEx/LogOutput.log
- Cache:
BepInEx/cache/DeepSynergy/
- Session Data:
BepInEx/cache/DeepSynergy/sessions/
- Localizations:
BepInEx/plugins/DeepSynergy/localizations/