
subnautica-ii-deep-synergy-coop-mod
BepInEx multiplayer mod for Subnautica 2 with synchronized co-op gameplay, adaptive scaling, and shared world state
- Installs
- 239
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/reason-machines/devtools-skills --skill subnautica-ii-deep-synergy-coop-mod- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads subnautica-ii-deep-synergy-coop-mod automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
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. It implements deterministic session synchronization, adaptive difficulty scaling based on player count, and peer-to-peer networking via WebRTC. The mod provides shared inventory management, cross-platform multiplayer, and optional AI-powered narrative generation.
Architecture:
- BepInEx 6.0+ plugin architecture (IL2CPP hooks)
- Peer-to-peer WebRTC data channels (no central server)
- Merkle tree-based inventory verification
- NAT punch-through for cross-platform connectivity
- Optional OpenAI/Claude API integration for dynamic narration
Installation
Prerequisites
- Subnautica 2 installed via Steam or GOG
- BepInEx 6.0.x for Unity IL2CPP games
Steps
# 1. Install BepInEx to Subnautica 2 directory
# Download from https://github.com/BepInEx/BepInEx/releases
# Extract to game root (where Subnautica2.exe is located)
# 2. Download Deep Synergy mod
# Extract to BepInEx/plugins/ directory
BepInEx/
plugins/
DeepSynergy/
DeepSynergy.dll
WebRTC.Native.dll
SyncEngine.dll
# 3. Create configuration directory
mkdir -p BepInEx/config/DeepSynergy
# 4. Launch game once to generate default configs
# Configs will appear in BepInEx/config/DeepSynergy/
Verify Installation
# Check BepInEx console output on game launch
# Should see:
# [Info : BepInEx] Loading [DeepSynergy 1.0.0]
# [Info : DeepSynergy] Session Manager initialized
# [Info : DeepSynergy] WebRTC channel ready
Configuration
Basic Session Profile
Create BepInEx/config/DeepSynergy/synergy_profile.json:
{
"session_name": "My Co-op Session",
"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": "all",
"voice_chat_integration": "none",
"api_integration": {
"openai": {
"enabled": false,
"role": "narrator"
},
"claude": {
"enabled": false,
"role": "lore_engine"
}
}
}
Network Configuration
Create BepInEx/config/DeepSynergy/network.json:
{
"nat_traversal": "auto",
"stun_servers": [
"stun:stun.l.google.com:19302",
"stun:stun1.l.google.com:19302"
],
"max_latency_ms": 150,
"sync_rate_hz": 20,
"compression": "zstd",
"encryption": true
}
AI Integration (Optional)
Create .env in game root directory:
OPENAI_API_KEY=your_openai_key_here
CLAUDE_API_KEY=your_claude_key_here
Enable in synergy_profile.json:
{
"api_integration": {
"openai": {
"enabled": true,
"role": "narrator",
"model": "gpt-4",
"max_tokens": 150,
"temperature": 0.7
},
"claude": {
"enabled": true,
"role": "lore_engine",
"model": "claude-3-opus-20240229",
"max_tokens": 300
}
}
}
Console Commands
Access BepInEx console with F12 (default) in-game:
Session Management
# Start hosting a session
/start_server
# Join existing session with code
/join_session 9B2A-4C7D-E8F1
# Leave current session
/leave_session
# Display session status
/synergy_status
Difficulty Scaling
# Adjust difficulty multiplier (temporary)
/synergy_scale 1.5
# Reset to profile defaults
/synergy_scale reset
# Show current scaling values
/synergy_info
Debugging
# Check synchronization state
/sync_check
# Force inventory resync
/force_sync inventory
# Show peer connection details
/peer_info
# Override world seed
/seed_override 12345
AI Narration
# Trigger custom narration
/api_narrate "discovering ancient alien ruins"
# Generate creature lore
/api_lore_gen "ghost leviathan"
# Get contextual hint
/api_hint current_biome
Programming Guide
Creating Custom Session Profiles Programmatically
using DeepSynergy.API;
using System.Collections.Generic;
public class CustomSessionManager
{
public static SessionProfile CreateHardcoreProfile()
{
return new SessionProfile
{
SessionName = "Hardcore Duo",
MaxPlayers = 2,
DifficultyScale = ScaleMode.Static,
ResourceMultiplier = 0.7f,
OxygenConsumption = 1.3f,
CreatureSpawnDivider = 0.8f,
EnablePvP = false,
FriendlyFire = true,
SharedBlueprints = false,
TimeOfDaySync = SyncMode.Host
};
}
public static void ApplyProfile(SessionProfile profile)
{
var manager = SynergyCore.GetSessionManager();
manager.LoadProfile(profile);
manager.BroadcastConfiguration();
}
}
Hooking into Sync Events
using DeepSynergy.Events;
using BepInEx;
using BepInEx.IL2CPP;
[BepInPlugin("com.mymod.synergyextension", "Synergy Extension", "1.0.0")]
public class SynergyExtension : BasePlugin
{
public override void Load()
{
// Subscribe to inventory sync events
SyncEvents.OnInventorySync += HandleInventorySync;
// Subscribe to player join/leave
SyncEvents.OnPlayerJoined += HandlePlayerJoined;
SyncEvents.OnPlayerLeft += HandlePlayerLeft;
// Subscribe to base building events
SyncEvents.OnStructurePlaced += HandleStructurePlaced;
}
private void HandleInventorySync(InventorySyncData data)
{
Log.LogInfo($"Inventory synced: {data.ItemCount} items, hash {data.MerkleRoot}");
}
private void HandlePlayerJoined(PlayerJoinData data)
{
Log.LogInfo($"Player joined: {data.PlayerName} (ID: {data.PlayerId})");
}
private void HandlePlayerLeft(PlayerLeaveData data)
{
Log.LogInfo($"Player left: {data.PlayerId}");
}
private void HandleStructurePlaced(StructureData data)
{
Log.LogInfo($"Structure placed: {data.Type} at {data.Position}");
}
}
Custom Difficulty Scaler
using DeepSynergy.Scaling;
public class CustomScaler : IAdaptiveScaler
{
public float CalculateResourceMultiplier(int playerCount)
{
// Linear scaling: each player adds 25% resources
return 1.0f + (playerCount - 1) * 0.25f;
}
public float CalculateCreatureSpawnRate(int playerCount)
{
// Logarithmic scaling to avoid overwhelming players
return 1.0f + Mathf.Log10(playerCount);
}
public float CalculateOxygenConsumption(int playerCount)
{
// Reduce oxygen drain slightly in co-op
return Mathf.Max(0.5f, 1.0f - (playerCount - 1) * 0.1f);
}
}
// Register custom scaler
SynergyCore.GetSessionManager().RegisterScaler(new CustomScaler());
Accessing Synchronized State
using DeepSynergy.State;
public class BaseMonitor
{
public void CheckSharedBaseStatus()
{
var stateManager = SynergyCore.GetStateManager();
// Get all synchronized base structures
var bases = stateManager.GetSyncedStructures();
foreach (var structure in bases)
{
Debug.Log($"Structure: {structure.Id}");
Debug.Log($" Type: {structure.Type}");
Debug.Log($" Owner: {structure.PlacedByPlayerId}");
Debug.Log($" Position: {structure.Position}");
Debug.Log($" Integrity: {structure.Integrity}%");
}
// Get shared inventory state
var inventory = stateManager.GetSharedInventory();
Debug.Log($"Total items in network: {inventory.TotalItemCount}");
Debug.Log($"Merkle root: {inventory.MerkleRoot}");
}
}
WebRTC Connection Management
using DeepSynergy.Networking;
public class ConnectionManager
{
public async Task<string> CreateSession()
{
var network = SynergyCore.GetNetworkManager();
// Initialize WebRTC host
var sessionCode = await network.CreateHostSession();
Debug.Log($"Session created: {sessionCode}");
// Set up connection callbacks
network.OnPeerConnected += (peerId) => {
Debug.Log($"Peer connected: {peerId}");
};
network.OnPeerDisconnected += (peerId) => {
Debug.Log($"Peer disconnected: {peerId}");
};
return sessionCode;
}
public async Task<bool> JoinSession(string sessionCode)
{
var network = SynergyCore.GetNetworkManager();
try
{
await network.JoinSession(sessionCode);
Debug.Log("Successfully joined session");
return true;
}
catch (NetworkException ex)
{
Debug.LogError($"Failed to join: {ex.Message}");
return false;
}
}
}
Common Patterns
Graceful Session Migration
When the host disconnects, the mod automatically migrates to another peer:
using DeepSynergy.Migration;
SyncEvents.OnHostMigration += (newHostId) => {
if (newHostId == SynergyCore.GetLocalPlayerId())
{
// This client is now the host
Debug.Log("Became session host");
// Broadcast new session state
var state = SynergyCore.GetStateManager();
state.BroadcastFullState();
}
else
{
Debug.Log($"New host: {newHostId}");
}
};
Conditional AI Narration
using DeepSynergy.AI;
public class NarrativeController
{
private AIIntegration aiIntegration;
public void Initialize()
{
aiIntegration = SynergyCore.GetAIIntegration();
// Only enable if configured
if (!aiIntegration.IsEnabled())
{
Debug.Log("AI integration disabled in profile");
return;
}
}
public async Task NarrateDiscovery(string biome, string discovery)
{
if (!aiIntegration.IsEnabled()) return;
var prompt = $"The team discovered {discovery} in the {biome}. " +
$"Write a brief journal entry (50 words max).";
var narration = await aiIntegration.GenerateNarration(prompt);
// Broadcast to all players
SynergyCore.GetChatManager().SendSystemMessage(narration);
}
}
Profile Validation
using DeepSynergy.Validation;
public static class ProfileValidator
{
public static bool ValidateProfile(SessionProfile profile, out string error)
{
error = null;
if (profile.MaxPlayers < 2 || profile.MaxPlayers > 8)
{
error = "MaxPlayers must be between 2 and 8";
return false;
}
if (profile.ResourceMultiplier < 0.1f || profile.ResourceMultiplier > 5.0f)
{
error = "ResourceMultiplier must be between 0.1 and 5.0";
return false;
}
if (profile.OxygenConsumption < 0.1f)
{
error = "OxygenConsumption cannot be less than 0.1";
return false;
}
return true;
}
}
Troubleshooting
Session Code Not Generating
Problem: /start_server returns empty session code
Solutions:
# Check network configuration
cat BepInEx/config/DeepSynergy/network.json
# Verify STUN servers are accessible
ping stun.l.google.com
# Check firewall settings (allow UDP ports 49152-65535)
# Enable verbose logging
/synergy_debug enable
# Check BepInEx console for errors
# Look for: [Error : DeepSynergy] Failed to initialize WebRTC
Inventory Desync
Problem: Players see different inventory states
Solutions:
# Force full resync
/force_sync all
# Check sync status
/sync_check
# Verify Merkle tree integrity
/debug merkle_verify
In code:
// Manual resync trigger
var stateManager = SynergyCore.GetStateManager();
stateManager.RequestFullSync();
// Check for conflicts
var conflicts = stateManager.GetSyncConflicts();
foreach (var conflict in conflicts)
{
Debug.LogWarning($"Sync conflict: {conflict.Type} at {conflict.Timestamp}");
}
High Latency Between Peers
Problem: Laggy interactions, delayed inventory updates
Solutions:
// Reduce sync rate in network.json
{
"sync_rate_hz": 10,
"max_latency_ms": 200,
"compression": "lz4"
}
# Check peer latency
/peer_info
# Output example:
# Peer 1 (9B2A): 45ms, packet loss 0.2%
# Peer 2 (4C7D): 180ms, packet loss 2.1%
AI Integration Not Responding
Problem: /api_narrate commands fail silently
Solutions:
# Verify environment variables
echo $OPENAI_API_KEY
echo $CLAUDE_API_KEY
# Check API status in logs
grep "AI Integration" BepInEx/LogOutput.log
# Test API connection directly
/api_test openai
/api_test claude
Structure Placement Conflicts
Problem: Two players place structures at same location
Solutions:
The mod uses timestamp-based conflict resolution:
// Conflict resolution is automatic, but you can listen for events
SyncEvents.OnStructureConflict += (conflict) => {
Debug.Log($"Structure conflict resolved: {conflict.WinningPlayerId} " +
$"placed {conflict.StructureType} at {conflict.Position}");
};
Session Migration Failures
Problem: All players disconnect when host leaves
Solutions:
// Enable migration in synergy_profile.json
{
"enable_host_migration": true,
"migration_timeout_seconds": 10
}
// Monitor migration status
SyncEvents.OnMigrationStarted += () => {
Debug.Log("Host migration in progress...");
};
SyncEvents.OnMigrationFailed += (reason) => {
Debug.LogError($"Migration failed: {reason}");
// Optionally save session state locally
SynergyCore.GetStateManager().SaveLocalBackup();
};
Blueprint Sync Issues
Problem: Unlocked blueprints not appearing for all players
Solutions:
# Verify shared_blueprints setting
/synergy_info | grep blueprints
# Force blueprint resync
/force_sync blueprints
// Manual blueprint sync
var blueprintManager = SynergyCore.GetBlueprintManager();
blueprintManager.SyncAllBlueprints();
// Check blueprint state
var syncedBlueprints = blueprintManager.GetSyncedBlueprints();
Debug.Log($"Synced blueprints: {syncedBlueprints.Count}");
Best Practices
- Always validate profiles before applying to avoid runtime errors
- Use environment variables for API keys, never hardcode
- Enable compression for sessions with 3+ players
- Monitor sync conflicts in production sessions
- Implement graceful degradation when AI APIs are unavailable
- Test host migration scenarios before public sessions
- Use adaptive scaling for variable player counts
Resources
- BepInEx documentation: https://docs.bepinex.dev/
- WebRTC specifications: https://webrtc.org/
- Subnautica modding wiki: Community-maintained documentation
FAQ
What does the subnautica-ii-deep-synergy-coop-mod skill do?
BepInEx multiplayer mod for Subnautica 2 with synchronized co-op gameplay, adaptive scaling, and shared world state
How do I install subnautica-ii-deep-synergy-coop-mod?
Run npx skills add https://github.com/reason-machines/devtools-skills --skill subnautica-ii-deep-synergy-coop-mod in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/subnautica-ii-deep-synergy-coop-mod/ (personal) or .claude/skills/subnautica-ii-deep-synergy-coop-mod/ (project).
Which AI agents can use subnautica-ii-deep-synergy-coop-mod?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is subnautica-ii-deep-synergy-coop-mod safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains subnautica-ii-deep-synergy-coop-mod?
It is published by reason-machines in reason-machines/devtools-skills. It has 239 recorded installs.
More from reason-machines/devtools-skills
cc-switch-cli
reason-machines/devtools-skills
Cross-platform CLI tool for managing Claude Code, Codex, Gemini, OpenCode & OpenClaw providers, MCP servers, prompts, skills, and proxies.
wx-cli-wechat-local-data
reason-machines/devtools-skills
Open the skill to read its SKILL.md instructions.
chrome-devtools-mcp-automation
reason-machines/devtools-skills
Use Chrome DevTools MCP to control Chrome, debug web apps, analyze performance, and automate browser tasks via MCP tools
officecli-office-automation
reason-machines/devtools-skills
Use OfficeCLI to create, read, and edit Word, Excel, and PowerPoint files from the command line with AI-friendly commands.
cli-anything-agent-native-software
reason-machines/devtools-skills
Generate and use command-line interfaces that make any software controllable by AI agents with structured JSON output
autocli-web-scraping
reason-machines/devtools-skills
Open the skill to read its SKILL.md instructions.
Popular other skills
hyperframes-cli
heygen-com/hyperframes
The HyperFrames CLI by job - scaffold, check, look at frames, edit the timeline, preview, render locally or in the cloud, publish, project history - plus reading its JSON and recovering from build or render failures.
triage
mattpocock/skills
Move issues and external PRs through a state machine of triage roles, categorise, verify, grill if needed, and write agent-ready briefs.
ask-matt
mattpocock/skills
Ask which skill or flow fits your situation. A router over the skills in this repo.
to-questionnaire
mattpocock/skills
Turn a decision you can't fully answer into a questionnaire for someone else to fill in.
loop-me
mattpocock/skills
Grill me about specs for the workflows I want to build, within this workspace.