| name | subnautica-2-coop-mod |
| description | BepInEx multiplayer mod for Subnautica 2 enabling synchronized co-op survival with shared base building and real-time state synchronization |
| triggers | ["install subnautica 2 multiplayer mod","setup subnautica coop mod","configure deep synergy multiplayer","host subnautica 2 session","troubleshoot subnautica mod connection","customize subnautica multiplayer settings","sync subnautica inventory state","configure bepinex subnautica plugin"] |
Subnautica 2 Co-op Mod Skill
Skill by ara.so — Devtools Skills collection.
Overview
The Deep Synergy Multiplayer Mod transforms Subnautica 2 into a synchronized cooperative experience using BepInEx plugin architecture. It implements peer-to-peer multiplayer with deterministic state synchronization, shared inventory systems, and adaptive difficulty scaling based on player count.
Core Capabilities:
- Peer-to-peer WebRTC connections with NAT traversal
- Real-time world state synchronization (base building, inventory, creature AI)
- Host migration and session persistence
- Adaptive difficulty scaling (2-4 players)
- Cross-platform support (Windows, Linux, macOS)
Installation
Prerequisites
- Install BepInEx 6.0.x for Subnautica 2:
-
Verify BepInEx is working:
- Launch game once, check for
BepInEx/LogOutput.log
- Should see "Chainloader initialized" message
-
Install Deep Synergy Mod:
Directory Structure
Subnautica2/
├── BepInEx/
│ ├── core/
│ ├── plugins/
│ │ └── DeepSynergy/
│ │ ├── DeepSynergy.dll
│ │ └── dependencies/
│ └── config/
│ └── synergy_profile.json
Configuration
Basic Profile Configuration
Create or edit 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": "disabled",
"network": {
"port":
Configuration Fields Reference
| Field | Type | Description | Default |
|---|
session_name | string | Display name for session | "Co-op Session" |
max_players | int | 2-4 players supported | 2 |
difficulty_scale | enum | "adaptive", "fixed", "hardcore" | "adaptive" |
resource_multiplier | float | Scales harvestable resources (0.5-2.0) | 1.0 |
oxygen_consumption | float | O2 drain multiplier (0.5-1.5) | 1.0 |
shared_blueprints | bool | Unlocks shared across players | true |
time_of_day_sync | enum | "host", "all", "independent" | "host" |
Console Commands
The mod adds in-game console commands accessible via BepInEx terminal (F5 by default):
Session Management
/start_server
/join_session <session-code>
/leave_session
/kick_player <player-id>
Session Monitoring
/synergy_status
/list_players
Gameplay Adjustments
/synergy_scale <multiplier>
/seed_override <seed-number>
/force_sync
/debug_inventory
AI Integration (if enabled)
/api_narrate "<context>"
/api_lore_species <creature-name>
Code Examples
Creating a Custom Mod Plugin (C#)
If extending the Deep Synergy mod with custom functionality:
using BepInEx;
using BepInEx.IL2CPP;
using DeepSynergy.Core;
using UnityEngine;
namespace MyCustomExtension
{
[BepInPlugin("com.example.subnautica2.extension", "Custom Extension", "1.0.0")]
[BepInDependency("com.deepsynergy.subnautica2", BepInDependency.DependencyFlags.HardDependency)]
public class CustomPlugin : BasePlugin
{
public override void Load()
{
SessionManager.OnPlayerJoined += HandlePlayerJoin;
SessionManager.OnStateSync += HandleStateSync;
Log.LogInfo("Custom Extension loaded");
}
private void HandlePlayerJoin(PlayerInfo player)
{
Log.LogInfo($"Player {player.Name} joined with ID {player.Id}");
NetworkMessenger.SendToPlayer(player.Id, new WelcomeMessage
{
Text = $"Welcome {player.Name}!",
Color = Color.cyan
});
}
private void HandleStateSync(SyncEvent syncEvent)
{
if (syncEvent.Type == SyncType.InventoryUpdate)
{
Log.LogInfo();
}
}
}
}
Custom Network Message Handler
using DeepSynergy.Networking;
public class CustomMessageHandler : INetworkMessageHandler
{
public void RegisterHandlers()
{
NetworkManager.RegisterHandler<CustomDataPacket>(OnCustomData);
}
private void OnCustomData(CustomDataPacket packet)
{
Debug.Log($"Received from {packet.SenderId}: {packet.Payload}");
if (NetworkManager.IsHost)
{
NetworkManager.BroadcastExcept(packet, packet.SenderId);
}
}
}
[Serializable]
public class CustomDataPacket : INetworkPacket
{
public string SenderId { get; set; }
public string Payload { get; set; }
public long Timestamp { get; set; }
}
Session Configuration Override at Runtime
using DeepSynergy.Config;
public class DynamicConfigManager
{
public static void AdjustDifficulty(float multiplier)
{
var config = SessionConfig.Current;
config.ResourceMultiplier *= multiplier;
config.CreatureSpawnDivider = (int)(config.CreatureSpawnDivider / multiplier);
SessionConfig.ApplyChanges(config);
NetworkManager.SyncConfig();
}
public static void EnableAPI(string provider)
{
var config = SessionConfig.Current;
if (provider == "openai")
{
config.ApiIntegration.OpenAI.Enabled = true;
config.ApiIntegration.OpenAI.ApiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
}
else if (provider == "claude")
{
config.ApiIntegration.Claude.Enabled = true;
config.ApiIntegration.Claude.ApiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY");
}
SessionConfig.ApplyChanges(config);
}
}
Common Patterns
Hosting a Session
vim BepInEx/config/synergy_profile.json
/start_server
/list_players
Joining a Session
/join_session 9B2A-4C7D-E8F1
/synergy_status
/list_players
Handling Disconnects
The mod automatically handles host migration:
SessionManager.OnHostMigration += (newHostId) =>
{
Debug.Log($"Host migrated to player {newHostId}");
};
if (!NetworkManager.IsConnected)
{
NetworkManager.AttemptReconnect(lastSessionCode);
}
Custom Difficulty Presets
{
"presets": {
"easy": {
"resource_multiplier": 1.5,
"oxygen_consumption": 0.7,
"creature_spawn_divider": 2
},
"normal": {
"resource_multiplier": 1.0,
"oxygen_consumption": 1.0,
"creature_spawn_divider": 1
},
"hardcore": {
"resource_multiplier": 0.7,
"oxygen_consumption": 1.3,
"creature_spawn_divider": 0.8,
"friendly_fire": true
}
}
Troubleshooting
Connection Issues
Problem: Cannot join session / "Connection timeout"
Solutions:
sudo ufw allow 7777/udp
/synergy_status
"network": {
"timeout_seconds": 60,
"max_latency_ms": 500
}
/join_session <host-ip>:7777
State Desync
Problem: Players see different base structures / inventory
Solutions:
/force_sync
/debug_inventory
/leave_session
rm -rf BepInEx/cache/synergy_state.dat
Performance Degradation
Problem: Lag spikes, FPS drops with multiple players
Solutions:
"network": {
"sync_interval_ms": 100,
"state_compression": true
}
"creature_sync_range": 100,
/synergy_status
"api_integration": {
"openai": { "enabled": false },
"claude": { "enabled": false }
}
Mod Conflicts
Problem: Crashes with other BepInEx mods
Solutions:
tail -f BepInEx/LogOutput.log
mv BepInEx/plugins/ConflictingMod.dll BepInEx/plugins/disabled/
API Integration Errors
Problem: OpenAI/Claude features not working
Solutions:
echo $OPENAI_API_KEY
echo $ANTHROPIC_API_KEY
/api_narrate "test connection"
"api_integration": {
"openai": { "enabled": false },
"fallback_to_local": true
}
Advanced Configuration
Custom Network Transport
using DeepSynergy.Networking;
public class CustomTransportLayer : INetworkTransport
{
public void Initialize(TransportConfig config)
{
}
public void Send(byte[] data, string targetId)
{
}
public void Broadcast(byte[] data)
{
}
}
NetworkManager.RegisterTransport(new CustomTransportLayer());
Event Hooks
SessionManager.OnPlayerJoined += (player) => { };
SessionManager.OnPlayerLeft += (playerId) => { };
SessionManager.OnStateSync += (syncEvent) => { };
SessionManager.OnHostMigration += (newHostId) => { };
InventoryManager.OnItemPickup += (item, playerId) => { };
BaseBuilder.OnStructurePlaced += (structure, playerId) => { };
Best Practices
- Always verify state sync before critical actions (e.g., blueprint unlocks)
- Use console commands for debugging before modifying config files
- Back up save files before enabling PvP or hardcore modes
- Monitor network stats with
/synergy_status regularly
- Disable API integrations if not needed (reduces overhead)
- Test with 2 players first before scaling to 3-4
- Use environment variables for API keys, never hardcode
Resources
- Wiki: Project documentation and compatibility lists
- Discord: Real-time community support
- Issue Tracker: Bug reports and feature requests
- BepInEx Docs: https://docs.bepinex.dev/