subnautica-ii-coop-deep-synergy-mod
Original:🇺🇸 English
Translated
BepInEx multiplayer mod for Subnautica 2 enabling synchronized co-op survival with deterministic session architecture
4installs
Sourcearadotso/devtools-skills
Added on
NPX Install
npx skill4agent add aradotso/devtools-skills subnautica-ii-coop-deep-synergy-modTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Subnautica II Deep Synergy Co-op Mod
Skill by ara.so — Devtools Skills collection.
Overview
The Deep Synergy Multiplayer Mod transforms Subnautica 2 into a synchronized cooperative experience using BepInEx framework. It implements deterministic session synchronization (DSS) where game state, inventory, base-building, and creature AI are shared across clients without central servers.
Key Architecture:
- Peer-to-peer WebRTC connectivity with NAT punch-through
- Blockchain-inspired Merkle tree inventory verification
- Hot-reloadable BepInEx plugin modules
- Adaptive dynamic scaling based on player count
- Optional AI narrative integration (OpenAI/Claude APIs)
Installation
Prerequisites
- Subnautica 2 installed via Steam/GOG
- BepInEx 6.0.x IL2CPP version for Unity games
Setup Steps
bash
# 1. Download BepInEx 6.0.x for IL2CPP from GitHub
# Extract to Subnautica 2 game directory (where Subnautica2.exe is located)
# 2. Run the game once to generate BepInEx folders
# Close the game after main menu loads
# 3. Download Deep Synergy mod from the project repository
# Extract contents to: Subnautica2/BepInEx/plugins/DeepSynergy/
# Verify directory structure:
Subnautica2/
├── BepInEx/
│ ├── config/
│ │ └── synergy_profile.json
│ ├── core/
│ └── plugins/
│ └── DeepSynergy/
│ ├── DeepSynergy.dll
│ ├── SessionManager.dll
│ └── StateSynchronizer.dll
└── Subnautica2.exeFirst Launch
bash
# Launch game normally - BepInEx will load automatically
# Look for console window showing:
[Info : BepInEx] BepInEx 6.0.0-pre.1 - Subnautica2
[Info : DeepSynergy] Deep Synergy Mod v1.0 loaded
[Info : DeepSynergy] Multiplayer hooks initializedConfiguration
Session Profile (synergy_profile.json)
Create or edit :
BepInEx/config/synergy_profile.jsonjson
{
"session_name": "DeepDiveSquad",
"max_players": 4,
"difficulty_scale": "adaptive",
"resource_multiplier": 1.5,
"oxygen_consumption": 0.85,
"creature_spawn_divider": 1.5,
"enable_pvp": false,
"friendly_fire": false,
"shared_blueprints": true,
"ping_locations_shared": true,
"time_of_day_sync": "host",
"voice_chat_integration": "discord_rpc",
"network": {
"port_range": "7777-7780",
"max_latency_ms": 250,
"packet_loss_tolerance": 0.05
},
"api_integration": {
"openai": {
"enabled": false,
"api_key_env": "OPENAI_API_KEY",
"role": "narrator",
"model": "gpt-4"
},
"claude": {
"enabled": false,
"api_key_env": "ANTHROPIC_API_KEY",
"role": "lore_engine",
"model": "claude-3-sonnet"
}
},
"sync_settings": {
"tick_rate": 20,
"state_hash_interval_ms": 500,
"inventory_verify_frequency": 5
},
"locale": "en-US"
}Configuration Fields
| Field | Type | Description |
|---|---|---|
| float | Scales harvestable resources (1.5 = 50% more) |
| float | Oxygen drain modifier (0.85 = 15% slower) |
| float | Reduces creature counts (1.5 = 33% fewer) |
| string | |
| int | State sync updates per second |
| int | Inventory verification interval |
Console Commands
Access via BepInEx console (F12 by default):
Session Management
bash
# Start hosting a session
/start_server
# Returns: Server created: session code = 9B2A-4C7D-E8F1
# Join existing session
/join_session 9B2A-4C7D-E8F1
# Check connection status
/synergy_status
# Output:
# Connected peers: 3
# State sync: 100% complete
# Inventory hash: 0xFA342B1E
# Average latency: 42ms
# Packet loss: 0.02%
# Disconnect from session
/leave_sessionSession Scaling
bash
# Temporarily adjust difficulty
/synergy_scale 1.8
# Scales creature/resource parameters by factor
# Override world seed for consistency
/seed_override 8251
# Forces same procedural generation across clients
# Reset to config defaults
/synergy_resetAI Integration
bash
# Trigger narrative generation (requires API keys)
/api_narrate "discovering the precursor facility"
# OpenAI/Claude generates contextual journal entry
# Generate species description for scanned creature
/api_lore creature_reaper_001
# Returns procedural biology reportCode Integration Patterns
Plugin Development Hook
For extending the mod with custom BepInEx plugins:
csharp
using BepInEx;
using BepInEx.IL2CPP;
using DeepSynergy.Core;
using DeepSynergy.Sync;
namespace MyCustomExtension
{
[BepInPlugin("com.myname.custommod", "Custom Synergy Extension", "1.0.0")]
[BepInDependency("com.deepsynergy.core", BepInDependency.DependencyFlags.HardDependency)]
public class CustomSynergyPlugin : BasePlugin
{
public override void Load()
{
// Hook into session events
SessionManager.OnSessionStarted += OnSessionStart;
StateSynchronizer.OnInventorySync += OnInventoryUpdated;
Log.LogInfo("Custom extension loaded");
}
private void OnSessionStart(SessionContext context)
{
Log.LogInfo($"Session {context.SessionCode} started with {context.PlayerCount} players");
// Apply custom scaling logic
if (context.PlayerCount >= 3)
{
context.ApplyDifficultyModifier(1.2f);
}
}
private void OnInventoryUpdated(InventoryState state)
{
// Verify custom item sync
var merkleRoot = state.ComputeMerkleRoot();
Log.LogInfo($"Inventory hash: {merkleRoot}");
}
}
}Custom Session Event Listener
csharp
using DeepSynergy.Events;
using UnityEngine;
public class BaseConstructionSyncer : MonoBehaviour
{
void Start()
{
// Subscribe to base building events
ConstructionSync.OnBasePiecePlaced += HandlePiecePlaced;
ConstructionSync.OnBasePieceRemoved += HandlePieceRemoved;
}
void HandlePiecePlaced(ConstructionPiece piece, ulong playerId)
{
// Broadcast to peers with timestamp
var syncPacket = new SyncPacket
{
Type = SyncType.ConstructionAdd,
Timestamp = NetworkTime.CurrentTimestamp(),
PlayerId = playerId,
Data = piece.Serialize()
};
SessionManager.Broadcast(syncPacket);
}
void HandlePieceRemoved(Vector3 position, ulong playerId)
{
var syncPacket = new SyncPacket
{
Type = SyncType.ConstructionRemove,
Timestamp = NetworkTime.CurrentTimestamp(),
PlayerId = playerId,
Data = position.Serialize()
};
SessionManager.Broadcast(syncPacket);
}
}AI Narration Integration
csharp
using DeepSynergy.AI;
using System.Threading.Tasks;
public class NarrativeController
{
private AIIntegrationService aiService;
public async Task GenerateDiscoveryNarrative(string eventDescription)
{
if (!aiService.IsEnabled("openai")) return;
var prompt = $@"
Context: Multiplayer Subnautica 2 session
Event: {eventDescription}
Generate a 2-3 sentence journal entry from the player's perspective.
";
var narrative = await aiService.CallOpenAI(
model: "gpt-4",
prompt: prompt,
maxTokens: 150,
temperature: 0.7f
);
// Display in-game PDA
PDAManager.AddJournalEntry(narrative);
}
public async Task<string> GenerateSpeciesDescription(string creatureId)
{
if (!aiService.IsEnabled("claude")) return null;
var prompt = $@"
Generate a fictional marine biology report for creature ID: {creatureId}
Include: Classification, behavior patterns, threat level, ecosystem role
Format: Scientific database entry style
";
return await aiService.CallClaude(
model: "claude-3-sonnet-20240229",
prompt: prompt,
maxTokens: 400
);
}
}Common Usage Patterns
Hosting a Session
bash
# 1. Configure session in synergy_profile.json
# 2. Launch game
# 3. In BepInEx console:
/start_server
# 4. Share session code with friends (displayed in console)
# Session code: A7B3-9D2E-F1C4
# 5. Friends join via:
/join_session A7B3-9D2E-F1C4Debugging Sync Issues
bash
# Check state synchronization
/synergy_status
# Force inventory re-sync
/synergy_resync inventory
# Dump current session state to log
/synergy_dump_state
# Check for Merkle tree mismatches
/synergy_verify_integrityPerformance Tuning
json
{
"sync_settings": {
"tick_rate": 15, // Reduce for lower bandwidth
"state_hash_interval_ms": 750, // Less frequent checks
"inventory_verify_frequency": 10 // Verify every 10th sync
},
"network": {
"max_latency_ms": 300, // Allow higher latency
"packet_loss_tolerance": 0.08 // Tolerate more loss
}
}Troubleshooting
"Session Code Invalid" Error
Cause: Mismatched mod versions or network timeout
bash
# Verify mod version
/synergy_version
# Both host and client must match
# Check network connectivity
/synergy_ping <host_ip>
# Regenerate session with explicit port
/start_server --port 7777Inventory Desynchronization
Symptoms: Items appear duplicated or missing
bash
# Force full state reconciliation
/synergy_reconcile_state
# Check Merkle tree integrity
/synergy_verify_integrity
# Look for "Hash mismatch detected" warnings
# If corrupted, reset to last checkpoint
/synergy_rollback_checkpointCreature AI Conflicts
Symptoms: Creatures behave erratically or freeze
json
// Increase AI sync frequency in config
{
"sync_settings": {
"ai_state_interval_ms": 200 // Default: 500
}
}bash
# Debug creature state lattice
/synergy_debug_ai creature_stalker_032High Latency/Packet Loss
bash
# Check network metrics
/synergy_netstat
# Output shows per-peer latency and packet loss
# Reduce tick rate for slower connections
/synergy_tickrate 12
# Enable aggressive compression
/synergy_compression lz4API Integration Failures
OpenAI/Claude not responding:
bash
# Verify environment variables are set
echo $OPENAI_API_KEY
echo $ANTHROPIC_API_KEY
# Test API connectivity
/api_test openai
/api_test claude
# Check logs for error details
tail -f BepInEx/LogOutput.log | grep APISession Migration After Host Disconnect
Automatic recovery:
bash
# Monitor migration status
/synergy_status
# Output shows "Migrating session to peer 2..."
# Manually force migration to specific peer
/synergy_migrate_host <peer_id>Advanced Configuration
Custom Difficulty Profiles
json
{
"difficulty_profiles": {
"casual": {
"resource_multiplier": 2.0,
"oxygen_consumption": 0.6,
"creature_spawn_divider": 2.5,
"damage_taken_multiplier": 0.7
},
"hardcore": {
"resource_multiplier": 0.8,
"oxygen_consumption": 1.3,
"creature_spawn_divider": 0.7,
"damage_taken_multiplier": 1.5,
"permadeath": true
}
},
"active_profile": "casual"
}Locale-Specific Settings
json
{
"locale": "ja-JP",
"localization_override": {
"console_commands": "ja-JP",
"ui_elements": "ja-JP",
"api_prompts": "en-US" // Keep AI prompts in English
}
}WebRTC Configuration
json
{
"network": {
"webrtc": {
"ice_servers": [
"stun:stun.l.google.com:19302",
"stun:stun1.l.google.com:19302"
],
"enable_turn": false,
"turn_server_env": "TURN_SERVER_URL",
"turn_credentials_env": "TURN_CREDENTIALS"
}
}
}Best Practices
- Always backup saves before using multiplayer sessions
- Match mod versions across all players to prevent sync issues
- Use adaptive scaling for dynamic player counts
- Set realistic latency tolerances based on geographic distances
- Enable AI features sparingly to avoid API rate limits
- Monitor console logs during first session for configuration errors
- Use checkpoint systems via every 15-20 minutes
/synergy_checkpoint
Environment Variables
bash
# Optional API integrations
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
# Optional TURN server for restricted NAT
export TURN_SERVER_URL="turn:turnserver.example.com:3478"
export TURN_CREDENTIALS="username:password"