subnautica-ii-deep-synergy-coop-mod
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSubnautica II Deep Synergy Co-op Mod
Subnautica 2 Deep Synergy 合作模组
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
Deep Synergy多人游戏模组通过BepInEx将Subnautica 2转化为同步合作体验。它实现了确定性会话同步、基于玩家数量的自适应难度缩放,以及通过WebRTC实现的点对点网络连接。该模组支持共享库存管理、跨平台多人游戏,以及可选的AI驱动叙事生成。
架构:
- BepInEx 6.0+ 插件架构(IL2CPP钩子)
- 基于WebRTC的点对点数据通道(无需中央服务器)
- 基于Merkle树的库存验证
- NAT穿透实现跨平台连接
- 可选的OpenAI/Claude API集成,用于动态叙事
Installation
安装
Prerequisites
前置条件
- Subnautica 2 installed via Steam or GOG
- BepInEx 6.0.x for Unity IL2CPP games
- 通过Steam或GOG安装Subnautica 2
- 适用于Unity IL2CPP游戏的BepInEx 6.0.x
Steps
步骤
bash
undefinedbash
undefined1. Install BepInEx to Subnautica 2 directory
1. 将BepInEx安装到Subnautica 2目录
Download from https://github.com/BepInEx/BepInEx/releases
Extract to game root (where Subnautica2.exe is located)
解压到游戏根目录(即Subnautica2.exe所在位置)
2. Download Deep Synergy mod
2. 下载Deep Synergy模组
Extract to BepInEx/plugins/ directory
解压到BepInEx/plugins/目录
BepInEx/
plugins/
DeepSynergy/
DeepSynergy.dll
WebRTC.Native.dll
SyncEngine.dll
BepInEx/
plugins/
DeepSynergy/
DeepSynergy.dll
WebRTC.Native.dll
SyncEngine.dll
3. Create configuration directory
3. 创建配置目录
mkdir -p BepInEx/config/DeepSynergy
mkdir -p BepInEx/config/DeepSynergy
4. Launch game once to generate default configs
4. 启动游戏一次以生成默认配置
Configs will appear in BepInEx/config/DeepSynergy/
配置文件将出现在BepInEx/config/DeepSynergy/目录下
undefinedundefinedVerify Installation
验证安装
bash
undefinedbash
undefinedCheck BepInEx console output on game launch
启动游戏时查看BepInEx控制台输出
Should see:
应显示:
[Info : BepInEx] Loading [DeepSynergy 1.0.0]
[Info : BepInEx] Loading [DeepSynergy 1.0.0]
[Info : DeepSynergy] Session Manager initialized
[Info : DeepSynergy] Session Manager initialized
[Info : DeepSynergy] WebRTC channel ready
[Info : DeepSynergy] WebRTC channel ready
undefinedundefinedConfiguration
配置
Basic Session Profile
基础会话配置文件
Create :
BepInEx/config/DeepSynergy/synergy_profile.jsonjson
{
"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"
}
}
}创建:
BepInEx/config/DeepSynergy/synergy_profile.jsonjson
{
"session_name": "我的合作会话",
"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.jsonjson
{
"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
}创建:
BepInEx/config/DeepSynergy/network.jsonjson
{
"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)
AI集成(可选)
Create in game root directory:
.envbash
OPENAI_API_KEY=your_openai_key_here
CLAUDE_API_KEY=your_claude_key_hereEnable in :
synergy_profile.jsonjson
{
"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
}
}
}在游戏根目录创建文件:
.envbash
OPENAI_API_KEY=your_openai_key_here
CLAUDE_API_KEY=your_claude_key_here在中启用:
synergy_profile.jsonjson
{
"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 (default) in-game:
F12在游戏中按(默认快捷键)打开BepInEx控制台:
F12Session Management
会话管理
bash
undefinedbash
undefinedStart hosting a session
开始托管会话
/start_server
/start_server
Join existing session with code
通过会话码加入现有会话
/join_session 9B2A-4C7D-E8F1
/join_session 9B2A-4C7D-E8F1
Leave current session
离开当前会话
/leave_session
/leave_session
Display session status
显示会话状态
/synergy_status
undefined/synergy_status
undefinedDifficulty Scaling
难度缩放
bash
undefinedbash
undefinedAdjust difficulty multiplier (temporary)
临时调整难度乘数
/synergy_scale 1.5
/synergy_scale 1.5
Reset to profile defaults
重置为配置文件默认值
/synergy_scale reset
/synergy_scale reset
Show current scaling values
显示当前缩放参数
/synergy_info
undefined/synergy_info
undefinedDebugging
调试
bash
undefinedbash
undefinedCheck synchronization state
检查同步状态
/sync_check
/sync_check
Force inventory resync
强制库存重同步
/force_sync inventory
/force_sync inventory
Show peer connection details
显示对等连接详情
/peer_info
/peer_info
Override world seed
覆盖世界种子
/seed_override 12345
undefined/seed_override 12345
undefinedAI Narration
AI叙事
bash
undefinedbash
undefinedTrigger custom narration
触发自定义叙事
/api_narrate "discovering ancient alien ruins"
/api_narrate "discovering ancient alien ruins"
Generate creature lore
生成生物背景故事
/api_lore_gen "ghost leviathan"
/api_lore_gen "ghost leviathan"
Get contextual hint
获取场景化提示
/api_hint current_biome
undefined/api_hint current_biome
undefinedProgramming Guide
编程指南
Creating Custom Session Profiles Programmatically
以编程方式创建自定义会话配置文件
csharp
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();
}
}csharp
using DeepSynergy.API;
using System.Collections.Generic;
public class CustomSessionManager
{
public static SessionProfile CreateHardcoreProfile()
{
return new SessionProfile
{
SessionName = "硬核双人组",
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
挂钩同步事件
csharp
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}");
}
}csharp
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()
{
// 订阅库存同步事件
SyncEvents.OnInventorySync += HandleInventorySync;
// 订阅玩家加入/离开事件
SyncEvents.OnPlayerJoined += HandlePlayerJoined;
SyncEvents.OnPlayerLeft += HandlePlayerLeft;
// 订阅基地建造事件
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
自定义难度缩放器
csharp
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());csharp
using DeepSynergy.Scaling;
public class CustomScaler : IAdaptiveScaler
{
public float CalculateResourceMultiplier(int playerCount)
{
// 线性缩放:每位玩家增加25%资源
return 1.0f + (playerCount - 1) * 0.25f;
}
public float CalculateCreatureSpawnRate(int playerCount)
{
// 对数缩放,避免玩家被过度压制
return 1.0f + Mathf.Log10(playerCount);
}
public float CalculateOxygenConsumption(int playerCount)
{
// 合作模式下略微降低氧气消耗
return Mathf.Max(0.5f, 1.0f - (playerCount - 1) * 0.1f);
}
}
// 注册自定义缩放器
SynergyCore.GetSessionManager().RegisterScaler(new CustomScaler());Accessing Synchronized State
访问同步状态
csharp
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}");
}
}csharp
using DeepSynergy.State;
public class BaseMonitor
{
public void CheckSharedBaseStatus()
{
var stateManager = SynergyCore.GetStateManager();
// 获取所有同步的基地建筑
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}%");
}
// 获取共享库存状态
var inventory = stateManager.GetSharedInventory();
Debug.Log($"Total items in network: {inventory.TotalItemCount}");
Debug.Log($"Merkle root: {inventory.MerkleRoot}");
}
}WebRTC Connection Management
WebRTC连接管理
csharp
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;
}
}
}csharp
using DeepSynergy.Networking;
public class ConnectionManager
{
public async Task<string> CreateSession()
{
var network = SynergyCore.GetNetworkManager();
// 初始化WebRTC主机
var sessionCode = await network.CreateHostSession();
Debug.Log($"Session created: {sessionCode}");
// 设置连接回调
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:
csharp
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}");
}
};当主机断开连接时,模组会自动迁移到另一个对等节点:
csharp
using DeepSynergy.Migration;
SyncEvents.OnHostMigration += (newHostId) => {
if (newHostId == SynergyCore.GetLocalPlayerId())
{
// 此客户端现在成为主机
Debug.Log("Became session host");
// 广播新的会话状态
var state = SynergyCore.GetStateManager();
state.BroadcastFullState();
}
else
{
Debug.Log($"New host: {newHostId}");
}
};Conditional AI Narration
条件式AI叙事
csharp
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);
}
}csharp
using DeepSynergy.AI;
public class NarrativeController
{
private AIIntegration aiIntegration;
public void Initialize()
{
aiIntegration = SynergyCore.GetAIIntegration();
// 仅在配置启用时生效
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);
// 广播给所有玩家
SynergyCore.GetChatManager().SendSystemMessage(narration);
}
}Profile Validation
配置文件验证
csharp
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;
}
}csharp
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必须在2到8之间";
return false;
}
if (profile.ResourceMultiplier < 0.1f || profile.ResourceMultiplier > 5.0f)
{
error = "ResourceMultiplier必须在0.1到5.0之间";
return false;
}
if (profile.OxygenConsumption < 0.1f)
{
error = "OxygenConsumption不能小于0.1";
return false;
}
return true;
}
}Troubleshooting
故障排除
Session Code Not Generating
会话码无法生成
Problem: returns empty session code
/start_serverSolutions:
bash
undefined问题: 返回空会话码
/start_server解决方案:
bash
undefinedCheck network configuration
检查网络配置
cat BepInEx/config/DeepSynergy/network.json
cat BepInEx/config/DeepSynergy/network.json
Verify STUN servers are accessible
验证STUN服务器是否可访问
ping stun.l.google.com
ping stun.l.google.com
Check firewall settings (allow UDP ports 49152-65535)
检查防火墙设置(允许UDP端口49152-65535)
Enable verbose logging
启用详细日志
/synergy_debug enable
/synergy_debug enable
Check BepInEx console for errors
查看BepInEx控制台中的错误
Look for: [Error : DeepSynergy] Failed to initialize WebRTC
寻找:[Error : DeepSynergy] Failed to initialize WebRTC
undefinedundefinedInventory Desync
库存不同步
Problem: Players see different inventory states
Solutions:
bash
undefined问题: 玩家看到的库存状态不一致
解决方案:
bash
undefinedForce full resync
强制全量重同步
/force_sync all
/force_sync all
Check sync status
检查同步状态
/sync_check
/sync_check
Verify Merkle tree integrity
验证Merkle树完整性
/debug merkle_verify
In code:
```csharp
// 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}");
}/debug merkle_verify
代码方式:
```csharp
// 手动触发重同步
var stateManager = SynergyCore.GetStateManager();
stateManager.RequestFullSync();
// 检查冲突
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:
json
// Reduce sync rate in network.json
{
"sync_rate_hz": 10,
"max_latency_ms": 200,
"compression": "lz4"
}bash
undefined问题: 交互卡顿、库存更新延迟
解决方案:
json
// 在network.json中降低同步频率
{
"sync_rate_hz": 10,
"max_latency_ms": 200,
"compression": "lz4"
}bash
undefinedCheck peer latency
检查对等节点延迟
/peer_info
/peer_info
Output example:
输出示例:
Peer 1 (9B2A): 45ms, packet loss 0.2%
Peer 1 (9B2A): 45ms, packet loss 0.2%
Peer 2 (4C7D): 180ms, packet loss 2.1%
Peer 2 (4C7D): 180ms, packet loss 2.1%
undefinedundefinedAI Integration Not Responding
AI集成无响应
Problem: commands fail silently
/api_narrateSolutions:
bash
undefined问题: 命令无反馈
/api_narrate解决方案:
bash
undefinedVerify environment variables
验证环境变量
echo $OPENAI_API_KEY
echo $CLAUDE_API_KEY
echo $OPENAI_API_KEY
echo $CLAUDE_API_KEY
Check API status in logs
在日志中检查API状态
grep "AI Integration" BepInEx/LogOutput.log
grep "AI Integration" BepInEx/LogOutput.log
Test API connection directly
直接测试API连接
/api_test openai
/api_test claude
undefined/api_test openai
/api_test claude
undefinedStructure Placement Conflicts
建筑放置冲突
Problem: Two players place structures at same location
Solutions:
The mod uses timestamp-based conflict resolution:
csharp
// 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}");
};问题: 两名玩家在同一位置放置建筑
解决方案:
模组使用基于时间戳的冲突解决机制:
csharp
// 冲突自动解决,但你可以监听事件
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:
json
// Enable migration in synergy_profile.json
{
"enable_host_migration": true,
"migration_timeout_seconds": 10
}csharp
// 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();
};问题: 主机离开时所有玩家断开连接
解决方案:
json
// 在synergy_profile.json中启用迁移
{
"enable_host_migration": true,
"migration_timeout_seconds": 10
}csharp
// 监控迁移状态
SyncEvents.OnMigrationStarted += () => {
Debug.Log("Host migration in progress...");
};
SyncEvents.OnMigrationFailed += (reason) => {
Debug.LogError($"Migration failed: {reason}");
// 可选:本地保存会话状态
SynergyCore.GetStateManager().SaveLocalBackup();
};Blueprint Sync Issues
蓝图同步问题
Problem: Unlocked blueprints not appearing for all players
Solutions:
bash
undefined问题: 解锁的蓝图未在所有玩家处显示
解决方案:
bash
undefinedVerify shared_blueprints setting
验证shared_blueprints设置
/synergy_info | grep blueprints
/synergy_info | grep blueprints
Force blueprint resync
强制蓝图重同步
/force_sync blueprints
```csharp
// Manual blueprint sync
var blueprintManager = SynergyCore.GetBlueprintManager();
blueprintManager.SyncAllBlueprints();
// Check blueprint state
var syncedBlueprints = blueprintManager.GetSyncedBlueprints();
Debug.Log($"Synced blueprints: {syncedBlueprints.Count}");/force_sync blueprints
```csharp
// 手动同步蓝图
var blueprintManager = SynergyCore.GetBlueprintManager();
blueprintManager.SyncAllBlueprints();
// 检查蓝图状态
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
- 应用前始终验证配置文件,避免运行时错误
- 使用环境变量存储API密钥,切勿硬编码
- 为3人及以上会话启用压缩
- 在生产会话中监控同步冲突
- 当AI API不可用时实现优雅降级
- 公开会话前测试主机迁移场景
- 对可变玩家数量使用自适应缩放
Resources
资源
- BepInEx documentation: https://docs.bepinex.dev/
- WebRTC specifications: https://webrtc.org/
- Subnautica modding wiki: Community-maintained documentation
- BepInEx文档:https://docs.bepinex.dev/
- WebRTC规范:https://webrtc.org/
- Subnautica模组开发维基:社区维护的文档