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
Added on

NPX Install

npx skill4agent add aradotso/devtools-skills subnautica-ii-coop-deep-synergy-mod

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

  1. Subnautica 2 installed via Steam/GOG
  2. 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.exe

First 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 initialized

Configuration

Session Profile (synergy_profile.json)

Create or edit
BepInEx/config/synergy_profile.json
:
json
{
  "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

FieldTypeDescription
resource_multiplier
floatScales harvestable resources (1.5 = 50% more)
oxygen_consumption
floatOxygen drain modifier (0.85 = 15% slower)
creature_spawn_divider
floatReduces creature counts (1.5 = 33% fewer)
difficulty_scale
string
"fixed"
,
"adaptive"
, or
"manual"
tick_rate
intState sync updates per second
state_hash_interval_ms
intInventory 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_session

Session 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_reset

AI 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 report

Code 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-F1C4

Debugging 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_integrity

Performance 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 7777

Inventory 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_checkpoint

Creature 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_032

High 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 lz4

API 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 API

Session 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

  1. Always backup saves before using multiplayer sessions
  2. Match mod versions across all players to prevent sync issues
  3. Use adaptive scaling for dynamic player counts
  4. Set realistic latency tolerances based on geographic distances
  5. Enable AI features sparingly to avoid API rate limits
  6. Monitor console logs during first session for configuration errors
  7. Use checkpoint systems via
    /synergy_checkpoint
    every 15-20 minutes

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"