subnautica-ii-deep-synergy-coop-mod

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Subnautica II Deep Synergy Co-op Mod

Subnautica 2 Deep Synergy 合作模组

Skill by ara.so — Devtools Skills collection.
ara.so开发的Skill — 属于Devtools Skills系列。

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

前置条件

  1. Subnautica 2 installed via Steam or GOG
  2. BepInEx 6.0.x for Unity IL2CPP games
  1. 通过Steam或GOG安装Subnautica 2
  2. 适用于Unity IL2CPP游戏的BepInEx 6.0.x

Steps

步骤

bash
undefined
bash
undefined

1. Install BepInEx to Subnautica 2 directory

1. 将BepInEx安装到Subnautica 2目录

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/目录下

undefined
undefined

Verify Installation

验证安装

bash
undefined
bash
undefined

Check 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

undefined
undefined

Configuration

配置

Basic Session Profile

基础会话配置文件

Create
BepInEx/config/DeepSynergy/synergy_profile.json
:
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"
    }
  }
}
创建
BepInEx/config/DeepSynergy/synergy_profile.json
json
{
  "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.json
:
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
}
创建
BepInEx/config/DeepSynergy/network.json
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)

AI集成(可选)

Create
.env
in game root directory:
bash
OPENAI_API_KEY=your_openai_key_here
CLAUDE_API_KEY=your_claude_key_here
Enable in
synergy_profile.json
:
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
    }
  }
}
在游戏根目录创建
.env
文件:
bash
OPENAI_API_KEY=your_openai_key_here
CLAUDE_API_KEY=your_claude_key_here
synergy_profile.json
中启用:
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:
在游戏中按
F12
(默认快捷键)打开BepInEx控制台:

Session Management

会话管理

bash
undefined
bash
undefined

Start 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
undefined

Difficulty Scaling

难度缩放

bash
undefined
bash
undefined

Adjust 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
undefined

Debugging

调试

bash
undefined
bash
undefined

Check 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
undefined

AI Narration

AI叙事

bash
undefined
bash
undefined

Trigger 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
undefined

Programming 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:
/start_server
returns empty session code
Solutions:
bash
undefined
问题:
/start_server
返回空会话码
解决方案:
bash
undefined

Check 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

undefined
undefined

Inventory Desync

库存不同步

Problem: Players see different inventory states
Solutions:
bash
undefined
问题: 玩家看到的库存状态不一致
解决方案:
bash
undefined

Force 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
undefined

Check 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%

undefined
undefined

AI Integration Not Responding

AI集成无响应

Problem:
/api_narrate
commands fail silently
Solutions:
bash
undefined
问题:
/api_narrate
命令无反馈
解决方案:
bash
undefined

Verify 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
undefined

Structure 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
undefined

Verify 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

最佳实践

  1. Always validate profiles before applying to avoid runtime errors
  2. Use environment variables for API keys, never hardcode
  3. Enable compression for sessions with 3+ players
  4. Monitor sync conflicts in production sessions
  5. Implement graceful degradation when AI APIs are unavailable
  6. Test host migration scenarios before public sessions
  7. Use adaptive scaling for variable player counts
  1. 应用前始终验证配置文件,避免运行时错误
  2. 使用环境变量存储API密钥,切勿硬编码
  3. 为3人及以上会话启用压缩
  4. 在生产会话中监控同步冲突
  5. 当AI API不可用时实现优雅降级
  6. 公开会话前测试主机迁移场景
  7. 对可变玩家数量使用自适应缩放

Resources

资源