FIRST
CI / Go Backend (push) Canceled after 0s

This commit is contained in:
xyou
2026-08-07 23:39:47 +08:00
parent f2105bf14c
commit 9500c4c80a
52 changed files with 3801 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
backend:
name: Go Backend
runs-on: ubuntu-latest
defaults:
run:
working-directory: server
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.22"
- name: Download dependencies
run: go mod download
- name: Build
run: go build ./cmd/...
- name: Vet
run: go vet ./...
- name: Test
run: go test ./... -race -cover
+73
View File
@@ -0,0 +1,73 @@
# ===================== Go =====================
# Binaries
*.exe
*.exe~
*.dll
*.so
*.dylib
server/bin/
# Test binary & coverage
*.test
*.out
*.prof
# Go workspace
go.work
go.work.sum
# Environment
.env
*.env.local
# ===================== Unity =====================
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/[Ll]ogs/
/[Uu]ser[Ss]ettings/
client/Assets/AssetStoreTools*
client/Assets/Plugins/Editor/JetBrains*
# Visual Studio / Rider cache
.vs/
.idea/
# Autogenerated solution & project files
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.mdb
*.opendb
*.VC.db
# Unity meta for generated
*.pidb.meta
*.pdb.meta
*.mdb.meta
# Unity crash report
sysinfo.txt
# Builds
*.apk
*.aab
*.unitypackage
# ===================== OS =====================
.DS_Store
Thumbs.db
desktop.ini
# ===================== Docker =====================
docker-compose.override.yml
+206
View File
@@ -0,0 +1,206 @@
# 初始化 MRCC 项目
## Summary
将 MRCC (MineRedCircuitcraft) 从空目录初始化为完整的 monorepo 骨架,包含 Unity 客户端和 Go 后端(6 个服务),每个服务具备 `/health` 健康检查端点并可独立启动。对应开发文档 Sprint 1 的交付目标。
## Current State Analysis
| 项目 | 状态 |
|------|------|
| Git 仓库 | 已初始化,main 分支,remote: `dcp.itnet.buzz/Deaicup/MRCC` |
| 现有文件 | `README.md``完整开发文档.html` |
| Go | **未安装** |
| Docker | **未安装** |
| Unity CLI | 不在 PATH 中(可能已安装 Editor |
开发文档定义的技术栈:
- 客户端: Unity 2024 LTS (C#)8 个模块
- 后端: Go 1.22 + Gin,5 个业务微服务 + 1 个联机中转站
- 基础设施: PostgreSQL 16、Redis 7.2、MinIO、RabbitMQ 3.13
## Prerequisites
执行前需安装(可通过 dev-env-expert 辅助):
1. **Go 1.22+** — 后端编译运行
2. **Docker Desktop** — 开发环境基础设施(PostgreSQL/Redis/MinIO/RabbitMQ
3. **Unity 2024 LTS** — 客户端打开编辑
> 骨架代码可先创建,Go 安装后即可 `go run` 启动后端。
## Proposed Changes
### 1. 根目录文件 (4 files)
| 文件 | 内容 |
|------|------|
| `.gitignore` | Go + Unity + IDE 忽略规则合并 |
| `docker-compose.dev.yml` | PostgreSQL 16、Redis 7.2、MinIO、RabbitMQ 3.13 开发环境 |
| `Makefile` | 根目录快捷命令:`make dev`(启动基础设施)、`make build-all``make run-*` |
| `.github/workflows/ci.yml` | Go build + vet + testPR 触发 |
### 2. Go 后端 (`server/`)
**Module path**: `mrcc`
```
server/
├── go.mod # module mrcc, go 1.22, deps: gin, gorilla/websocket
├── Makefile # build / run-* / tidy / lint / test
├── cmd/
│ ├── auth-service/main.go # :8081, /health
│ ├── economy-service/main.go # :8082, /health
│ ├── blueprint-service/main.go # :8083, /health
│ ├── match-service/main.go # :8084, /health
│ ├── social-service/main.go # :8085, /health
│ └── relay-server/main.go # :8086, /health + /ws WebSocket 骨架
├── internal/
│ ├── config/config.go # 环境变量加载,ServiceConfig 结构体
│ ├── logger/logger.go # slog 封装,统一日志格式
│ └── httpserver/server.go # Gin 实例工厂:CORS、Recovery、日志中间件、/health 注册
└── pkg/
└── response/response.go # 标准 JSON 响应 {code, message, data}
```
**每个业务微服务 main.go 模式**(以 auth-service 为例):
```go
package main
import (
"log"
"mrcc/internal/config"
"mrcc/internal/httpserver"
)
func main() {
cfg := config.Load("auth-service", "8081")
srv := httpserver.New(cfg)
log.Printf("auth-service listening on :%s", cfg.Port)
if err := srv.Run(":" + cfg.Port); err != nil {
log.Fatal(err)
}
}
```
**relay-server 额外内容**
- `/ws` WebSocket 升级端点(gorilla/websocket
- `Room``Player` 结构体定义(对照文档 18.5 节)
- 连接注册/注销 channel 骨架(不实现完整逻辑)
**go.mod 依赖**(最小化):
- `github.com/gin-gonic/gin v1.10.0`
- `github.com/gorilla/websocket v1.5.3`
### 3. Unity 客户端 (`client/`)
```
client/
├── Assets/
│ └── Scripts/
│ ├── RedCircuit.Grid/ # RedCircuit.Grid.asmdef
│ │ ├── GridCanvas.cs # 网格画布渲染
│ │ ├── ChunkManager.cs # 分块管理
│ │ └── TileRenderer.cs # 瓦片渲染
│ ├── RedCircuit.Simulation/ # RedCircuit.Simulation.asmdef
│ │ ├── SimulationLoop.cs # 仿真主循环
│ │ ├── SignalPropagator.cs # 信号传播
│ │ └── ComponentBehavior.cs # 元件行为基类
│ ├── RedCircuit.Components/ # RedCircuit.Components.asmdef
│ │ ├── ComponentRegistry.cs # 元件注册表
│ │ ├── PlacementController.cs # 放置控制器
│ │ └── ComponentData.cs # 元件数据定义
│ ├── RedCircuit.UI/ # RedCircuit.UI.asmdef
│ │ ├── EditorWindow.cs # 编辑器窗口
│ │ ├── ToolbarController.cs # 工具栏
│ │ ├── PalettePanel.cs # 元件面板
│ │ └── InspectorPanel.cs # 属性面板
│ ├── RedCircuit.Net/ # RedCircuit.Net.asmdef
│ │ ├── ApiClient.cs # REST 客户端
│ │ ├── WsClient.cs # WebSocket 客户端
│ │ └── SyncManager.cs # 同步管理
│ ├── RedCircuit.Save/ # RedCircuit.Save.asmdef
│ │ ├── SaveManager.cs # 存档管理
│ │ ├── LocalDatabase.cs # 本地 SQLite
│ │ └── CloudSync.cs # 云端同步
│ ├── RedCircuit.Audio/ # RedCircuit.Audio.asmdef
│ │ ├── AudioManager.cs # 音频管理
│ │ └── NotePlayer.cs # 音符播放
│ └── RedCircuit.Auth/ # RedCircuit.Auth.asmdef
│ ├── AuthManager.cs # 认证管理
│ ├── TokenStore.cs # Token 存储
│ └── OAuthClient.cs # OAuth 客户端
├── Packages/
│ └── manifest.json # Unity 2024 LTS 基础包
└── ProjectSettings/
└── ProjectVersion.txt # 2024.2.0f1
```
**每个 C# 脚本模式**(空骨架):
```csharp
using UnityEngine;
namespace RedCircuit.Grid
{
/// <summary>网格画布渲染器,负责 PCB 风格网格绘制与视口裁剪。</summary>
public class GridCanvas : MonoBehaviour
{
}
}
```
**Assembly Definition (asmdef) 模式**
```json
{
"name": "RedCircuit.Grid",
"rootNamespace": "RedCircuit.Grid",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"autoReferenced": true,
"defineConstraints": []
}
```
### 4. 文件清单汇总
| 区域 | 文件数 |
|------|--------|
| 根目录 | 4 |
| server/ (Go) | 16 (go.mod, Makefile, 6×main.go, 4×internal, 1×pkg) |
| client/ (Unity) | 29 (8×asmdef, 24×cs, manifest.json, ProjectVersion.txt) |
| **合计** | **~49 files** |
## Assumptions & Decisions
1. **端口分配**: relay-server 使用 8086(文档中 8084 与 match-service 冲突,调整为 8086
2. **Go module path**: 使用 `mrcc`(简单私有项目名,可后续改为 VCS URL)
3. **日志**: 使用标准库 `log/slog`,不引入 zap(最小化依赖)
4. **数据库连接**: 骨架阶段不连接实际数据库,docker-compose 仅供后续 Sprint 使用
5. **Unity 场景**: 不手动创建 .unity 场景文件(格式复杂且版本相关),用户在 Unity Editor 中新建
6. **.meta 文件**: 不创建 Unity .meta 文件,Unity Editor 首次打开自动生成
7. **CI**: 仅 Go 后端 CIUnity CI 需要 Unity License,后续 Sprint 再加)
## Verification Steps
1. **Go 后端编译**:
```powershell
cd server; go mod tidy; go build ./cmd/...
```
2. **各服务启动 + 健康检查**:
```powershell
go run ./cmd/auth-service &
curl http://localhost:8081/health # 期望 {"code":0,"message":"ok"}
# 对 8082-8086 重复
```
3. **relay-server WebSocket**:
```powershell
# 连接 ws://localhost:8086/ws 应成功升级
```
4. **Unity 客户端**:
- 用 Unity Hub 打开 `client/` 文件夹
- 无编译错误,8 个 asmdef 程序集均编译通过
5. **Git 提交**:
```powershell
git add -A; git status # 确认无敏感文件
```
+41
View File
@@ -0,0 +1,41 @@
.PHONY: dev build-all run-auth run-economy run-blueprint run-match run-social run-relay tidy lint test
# 启动开发环境基础设施
dev:
docker compose -f docker-compose.dev.yml up -d
dev-down:
docker compose -f docker-compose.dev.yml down
# 后端:构建所有服务
build-all:
cd server && go build ./cmd/...
# 后端:运行单个服务
run-auth:
cd server && go run ./cmd/auth-service
run-economy:
cd server && go run ./cmd/economy-service
run-blueprint:
cd server && go run ./cmd/blueprint-service
run-match:
cd server && go run ./cmd/match-service
run-social:
cd server && go run ./cmd/social-service
run-relay:
cd server && go run ./cmd/relay-server
# 后端:工具
tidy:
cd server && go mod tidy
lint:
cd server && go vet ./...
test:
cd server && go test ./...
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Audio
{
/// <summary>音频管理器,统一管理 BGM、UI 音效与游戏内音效播放。</summary>
public class AudioManager : MonoBehaviour
{
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Audio
{
/// <summary>音符播放器,驱动音符盒与蜂鸣器,支持频率随信号强度变化。</summary>
public class NotePlayer : MonoBehaviour
{
}
}
@@ -0,0 +1,10 @@
{
"name": "RedCircuit.Audio",
"rootNamespace": "RedCircuit.Audio",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"autoReferenced": true,
"defineConstraints": []
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Auth
{
/// <summary>认证管理器,处理注册、登录、Token 刷新与会话管理。</summary>
public class AuthManager : MonoBehaviour
{
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Auth
{
/// <summary>OAuth 客户端,支持 Google / GitHub / Discord 第三方快捷登录。</summary>
public class OAuthClient : MonoBehaviour
{
}
}
@@ -0,0 +1,10 @@
{
"name": "RedCircuit.Auth",
"rootNamespace": "RedCircuit.Auth",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"autoReferenced": true,
"defineConstraints": []
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Auth
{
/// <summary>Token 存储,安全保存 Access Token 与 Refresh Token,支持自动刷新。</summary>
public class TokenStore : MonoBehaviour
{
}
}
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
namespace RedCircuit.Components
{
/// <summary>元件数据定义,描述元件类型、朝向、可调属性与通电状态。</summary>
[Serializable]
public class ComponentData
{
public string id;
public string type;
public int x;
public int y;
public int rotation;
public Dictionary<string, int> properties = new();
public bool isPowered;
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Components
{
/// <summary>元件注册表,管理 80 种元件的数据定义与图标映射。</summary>
public class ComponentRegistry : MonoBehaviour
{
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Components
{
/// <summary>放置控制器,处理元件拖放放置、删除、旋转操作。</summary>
public class PlacementController : MonoBehaviour
{
}
}
@@ -0,0 +1,10 @@
{
"name": "RedCircuit.Components",
"rootNamespace": "RedCircuit.Components",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"autoReferenced": true,
"defineConstraints": []
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Grid
{
/// <summary>分块管理器,将画布按 16x16 分 Chunk,仅实例化视口内 Chunk。</summary>
public class ChunkManager : MonoBehaviour
{
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Grid
{
/// <summary>网格画布渲染器,负责 PCB 风格网格绘制与视口裁剪。</summary>
public class GridCanvas : MonoBehaviour
{
}
}
@@ -0,0 +1,10 @@
{
"name": "RedCircuit.Grid",
"rootNamespace": "RedCircuit.Grid",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"autoReferenced": true,
"defineConstraints": []
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Grid
{
/// <summary>瓦片渲染器,负责单个元件方块的 GPU Instancing 批量绘制。</summary>
public class TileRenderer : MonoBehaviour
{
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Net
{
/// <summary>REST API 客户端,封装用户认证、商店、蓝图等 HTTP 请求。</summary>
public class ApiClient : MonoBehaviour
{
}
}
@@ -0,0 +1,10 @@
{
"name": "RedCircuit.Net",
"rootNamespace": "RedCircuit.Net",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"autoReferenced": true,
"defineConstraints": []
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Net
{
/// <summary>同步管理器,处理多人协作模式下的电路增量 Delta 同步与冲突解决。</summary>
public class SyncManager : MonoBehaviour
{
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Net
{
/// <summary>WebSocket 客户端,维持与 relay-server 的长连接,处理实时消息收发。</summary>
public class WsClient : MonoBehaviour
{
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Save
{
/// <summary>云端同步,将本地存档与蓝图同步至服务端,支持冲突合并。</summary>
public class CloudSync : MonoBehaviour
{
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Save
{
/// <summary>本地数据库,基于 SQLite 存储存档、蓝图与设置,支持离线缓存。</summary>
public class LocalDatabase : MonoBehaviour
{
}
}
@@ -0,0 +1,10 @@
{
"name": "RedCircuit.Save",
"rootNamespace": "RedCircuit.Save",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"autoReferenced": true,
"defineConstraints": []
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Save
{
/// <summary>存档管理器,管理电路存档的创建、保存、加载与删除。</summary>
public class SaveManager : MonoBehaviour
{
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Simulation
{
/// <summary>元件行为基类,定义元件接收信号后的规则接口。</summary>
public abstract class ComponentBehavior : MonoBehaviour
{
}
}
@@ -0,0 +1,10 @@
{
"name": "RedCircuit.Simulation",
"rootNamespace": "RedCircuit.Simulation",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"autoReferenced": true,
"defineConstraints": []
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Simulation
{
/// <summary>信号传播器,基于优先级队列 BFS 实现红石信号强度衰减传播。</summary>
public class SignalPropagator : MonoBehaviour
{
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.Simulation
{
/// <summary>仿真主循环,每 Tick 执行信号收集、BFS 传播、元件规则、延迟处理、输出更新。</summary>
public class SimulationLoop : MonoBehaviour
{
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.UI
{
/// <summary>编辑器主窗口,管理画布、工具栏、面板的整体布局与生命周期。</summary>
public class EditorWindow : MonoBehaviour
{
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.UI
{
/// <summary>属性面板,显示并编辑选中元件的可调属性(延迟、阻值、模式等)。</summary>
public class InspectorPanel : MonoBehaviour
{
}
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.UI
{
/// <summary>元件面板,按 8 大分类展示 80 种元件供玩家选择放置。</summary>
public class PalettePanel : MonoBehaviour
{
}
}
@@ -0,0 +1,10 @@
{
"name": "RedCircuit.UI",
"rootNamespace": "RedCircuit.UI",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"autoReferenced": true,
"defineConstraints": []
}
@@ -0,0 +1,9 @@
using UnityEngine;
namespace RedCircuit.UI
{
/// <summary>工具栏控制器,管理保存/加载/运行/暂停按钮与模式切换。</summary>
public class ToolbarController : MonoBehaviour
{
}
}
+33
View File
@@ -0,0 +1,33 @@
{
"dependencies": {
"com.unity.2d.sprite": "1.0.0",
"com.unity.2d.tilemap": "1.0.0",
"com.unity.ide.visualstudio": "2.0.22",
"com.unity.ide.rider": "3.0.28",
"com.unity.test-framework": "1.1.33",
"com.unity.ugui": "2.0.0",
"com.unity.ui": "2.0.0",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.animation": "1.0.0",
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.particlesystem": "1.0.0",
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.physics2d": "1.0.0",
"com.unity.modules.screencapture": "1.0.0",
"com.unity.modules.terrain": "1.0.0",
"com.unity.modules.terrainphysics": "1.0.0",
"com.unity.modules.tilemap": "1.0.0",
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.uielements": "1.0.0",
"com.unity.modules.umbra": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.unitywebrequestassetbundle": "1.0.0",
"com.unity.modules.unitywebrequestaudio": "1.0.0",
"com.unity.modules.unitywebrequesttexture": "1.0.0",
"com.unity.modules.unitywebrequestwww": "1.0.0"
}
}
@@ -0,0 +1,2 @@
m_EditorVersion: 2024.2.0f1
m_EditorVersionWithRevision: 2024.2.0f1 (0000000000000)
+80
View File
@@ -0,0 +1,80 @@
version: "3.9"
# MRCC 开发环境基础设施
# 使用: docker compose -f docker-compose.dev.yml up -d
services:
postgres:
image: postgres:16-alpine
container_name: mrcc-postgres
restart: unless-stopped
environment:
POSTGRES_USER: mrcc
POSTGRES_PASSWORD: mrcc_dev_2026
POSTGRES_DB: mrcc
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U mrcc"]
interval: 5s
timeout: 3s
retries: 5
redis:
image: redis:7.2-alpine
container_name: mrcc-redis
restart: unless-stopped
ports:
- "6379:6379"
volumes:
- redisdata:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
minio:
image: minio/minio:latest
container_name: mrcc-minio
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: mrcc
MINIO_ROOT_PASSWORD: mrcc_dev_2026
ports:
- "9000:9000"
- "9001:9001"
volumes:
- miniodata:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 10s
timeout: 5s
retries: 3
rabbitmq:
image: rabbitmq:3.13-management-alpine
container_name: mrcc-rabbitmq
restart: unless-stopped
environment:
RABBITMQ_DEFAULT_USER: mrcc
RABBITMQ_DEFAULT_PASS: mrcc_dev_2026
ports:
- "5672:5672"
- "15672:15672"
volumes:
- rabbitmqdata:/var/lib/rabbitmq
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
pgdata:
redisdata:
miniodata:
rabbitmqdata:
+31
View File
@@ -0,0 +1,31 @@
.PHONY: build run-auth run-economy run-blueprint run-match run-social run-relay tidy lint test
build:
go build ./cmd/...
run-auth:
go run ./cmd/auth-service
run-economy:
go run ./cmd/economy-service
run-blueprint:
go run ./cmd/blueprint-service
run-match:
go run ./cmd/match-service
run-social:
go run ./cmd/social-service
run-relay:
go run ./cmd/relay-server
tidy:
go mod tidy
lint:
go vet ./...
test:
go test ./...
+26
View File
@@ -0,0 +1,26 @@
package main
import (
"log"
"mrcc/internal/config"
"mrcc/internal/httpserver"
"mrcc/internal/logger"
)
func main() {
cfg := config.Load("auth-service", "8081")
logger.WithService(cfg.Name).Info("starting service", "port", cfg.Port)
srv := httpserver.New(cfg)
// TODO: 注册认证路由
// r := srv.Group("/api/auth")
// r.POST("/register", ...)
// r.POST("/login", ...)
log.Printf("auth-service listening on %s", cfg.Address())
if err := srv.Run(cfg.Address()); err != nil {
log.Fatal(err)
}
}
+27
View File
@@ -0,0 +1,27 @@
package main
import (
"log"
"mrcc/internal/config"
"mrcc/internal/httpserver"
"mrcc/internal/logger"
)
func main() {
cfg := config.Load("blueprint-service", "8083")
logger.WithService(cfg.Name).Info("starting service", "port", cfg.Port)
srv := httpserver.New(cfg)
// TODO: 注册蓝图路由
// r := srv.Group("/api/blueprints")
// r.GET("/", ...)
// r.POST("/", ...)
// r.POST("/:id/buy", ...)
log.Printf("blueprint-service listening on %s", cfg.Address())
if err := srv.Run(cfg.Address()); err != nil {
log.Fatal(err)
}
}
+27
View File
@@ -0,0 +1,27 @@
package main
import (
"log"
"mrcc/internal/config"
"mrcc/internal/httpserver"
"mrcc/internal/logger"
)
func main() {
cfg := config.Load("economy-service", "8082")
logger.WithService(cfg.Name).Info("starting service", "port", cfg.Port)
srv := httpserver.New(cfg)
// TODO: 注册经济路由
// r := srv.Group("/api/user")
// r.GET("/balance", ...)
// r := srv.Group("/api/shop")
// r.GET("/items", ...)
log.Printf("economy-service listening on %s", cfg.Address())
if err := srv.Run(cfg.Address()); err != nil {
log.Fatal(err)
}
}
+27
View File
@@ -0,0 +1,27 @@
package main
import (
"log"
"mrcc/internal/config"
"mrcc/internal/httpserver"
"mrcc/internal/logger"
)
func main() {
cfg := config.Load("match-service", "8084")
logger.WithService(cfg.Name).Info("starting service", "port", cfg.Port)
srv := httpserver.New(cfg)
// TODO: 注册匹配路由
// r := srv.Group("/api/multiplayer")
// r.POST("/match", ...)
// r.POST("/join", ...)
// r.POST("/result", ...)
log.Printf("match-service listening on %s", cfg.Address())
if err := srv.Run(cfg.Address()); err != nil {
log.Fatal(err)
}
}
+167
View File
@@ -0,0 +1,167 @@
package main
import (
"log"
"net/http"
"sync"
"time"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"mrcc/internal/config"
"mrcc/internal/httpserver"
"mrcc/internal/logger"
"mrcc/pkg/response"
)
// === 数据结构骨架(对照开发文档 18.5 节)===
type RoomStatus string
const (
RoomCreated RoomStatus = "created"
RoomWaiting RoomStatus = "waiting"
RoomPlaying RoomStatus = "playing"
RoomFinished RoomStatus = "finished"
)
// Player 玩家连接
type Player struct {
UserID string `json:"user_id"`
Username string `json:"username"`
Conn *websocket.Conn `json:"-"`
IsReady bool `json:"is_ready"`
JoinedAt time.Time `json:"joined_at"`
SendQueue chan []byte `json:"-"`
}
// Room 房间
type Room struct {
ID string `json:"id"`
Status RoomStatus `json:"status"`
HostUserID string `json:"host_user_id"`
MaxPlayers int `json:"max_players"`
Players map[string]*Player `json:"players"`
CreatedAt time.Time `json:"created_at"`
mu sync.RWMutex `json:"-"`
}
// RelayServer 中转服务器
type RelayServer struct {
Rooms map[string]*Room
Players map[string]*Player
Register chan *Player
Unregister chan *Player
mu sync.RWMutex
}
func NewRelayServer() *RelayServer {
return &RelayServer{
Rooms: make(map[string]*Room),
Players: make(map[string]*Player),
Register: make(chan *Player, 64),
Unregister: make(chan *Player, 64),
}
}
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true // 开发阶段允许所有来源
},
}
// HandleWS 处理 WebSocket 连接升级
func HandleWS(relay *RelayServer) gin.HandlerFunc {
return func(c *gin.Context) {
userID := c.Query("user_id")
if userID == "" {
userID = "anonymous"
}
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
log.Printf("websocket upgrade failed: %v", err)
return
}
player := &Player{
UserID: userID,
Conn: conn,
JoinedAt: time.Now(),
SendQueue: make(chan []byte, 256),
}
relay.Register <- player
log.Printf("player connected: %s", userID)
// TODO: 实现读写 goroutine、房间管理、消息路由、断线重连
// 当前骨架仅保持连接并读取消息
go func() {
defer func() {
relay.Unregister <- player
conn.Close()
}()
for {
_, _, err := conn.ReadMessage()
if err != nil {
break
}
}
}()
}
}
func main() {
cfg := config.Load("relay-server", "8086")
logger.WithService(cfg.Name).Info("starting relay server", "port", cfg.Port)
relay := NewRelayServer()
// 后台处理注册/注销
go func() {
for {
select {
case player := <-relay.Register:
relay.mu.Lock()
relay.Players[player.UserID] = player
relay.mu.Unlock()
log.Printf("player registered: %s", player.UserID)
case player := <-relay.Unregister:
relay.mu.Lock()
delete(relay.Players, player.UserID)
relay.mu.Unlock()
log.Printf("player unregistered: %s", player.UserID)
}
}
}()
srv := httpserver.New(cfg)
// WebSocket 端点
srv.GET("/ws", HandleWS(relay))
// 房间信息端点(骨架)
srv.GET("/rooms", func(c *gin.Context) {
relay.mu.RLock()
defer relay.mu.RUnlock()
rooms := make([]gin.H, 0, len(relay.Rooms))
for id, room := range relay.Rooms {
rooms = append(rooms, gin.H{
"id": id,
"status": room.Status,
"playerCount": len(room.Players),
})
}
response.OK(c, gin.H{"rooms": rooms, "total": len(rooms)})
})
log.Printf("relay-server listening on %s (WS: /ws)", cfg.Address())
if err := srv.Run(cfg.Address()); err != nil {
log.Fatal(err)
}
}
+28
View File
@@ -0,0 +1,28 @@
package main
import (
"log"
"mrcc/internal/config"
"mrcc/internal/httpserver"
"mrcc/internal/logger"
)
func main() {
cfg := config.Load("social-service", "8085")
logger.WithService(cfg.Name).Info("starting service", "port", cfg.Port)
srv := httpserver.New(cfg)
// TODO: 注册社交路由
// r := srv.Group("/api/user")
// r.GET("/profile", ...)
// r.GET("/achievements", ...)
// r := srv.Group("/api/leaderboard")
// r.GET("/", ...)
log.Printf("social-service listening on %s", cfg.Address())
if err := srv.Run(cfg.Address()); err != nil {
log.Fatal(err)
}
}
+37
View File
@@ -0,0 +1,37 @@
module mrcc
go 1.22
require (
github.com/gin-gonic/gin v1.10.0
github.com/gorilla/websocket v1.5.3
)
require (
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+58
View File
@@ -0,0 +1,58 @@
package config
import (
"fmt"
"os"
"strconv"
)
// ServiceConfig holds configuration shared across all microservices.
type ServiceConfig struct {
Name string // 服务名称,如 auth-service
Port string // 监听端口
// 基础设施连接(骨架阶段仅定义,暂不使用)
PostgresDSN string
RedisAddr string
MinIOAddr string
RabbitMQURL string
// 运行环境: debug / release
GinMode string
}
// Load 从环境变量加载配置,fallback 到默认值。
// serviceName 和 defaultPort 用于在没有设置环境变量时提供默认值。
func Load(serviceName, defaultPort string) *ServiceConfig {
cfg := &ServiceConfig{
Name: serviceName,
Port: envOr("SERVICE_PORT", defaultPort),
PostgresDSN: envOr("POSTGRES_DSN", "postgres://mrcc:mrcc_dev_2026@localhost:5432/mrcc?sslmode=disable"),
RedisAddr: envOr("REDIS_ADDR", "localhost:6379"),
MinIOAddr: envOr("MINIO_ADDR", "localhost:9000"),
RabbitMQURL: envOr("RABBITMQ_URL", "amqp://mrcc:mrcc_dev_2026@localhost:5672/"),
GinMode: envOr("GIN_MODE", "debug"),
}
return cfg
}
// Address 返回 :port 格式的监听地址
func (c *ServiceConfig) Address() string {
return fmt.Sprintf(":%s", c.Port)
}
func envOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}
func envIntOr(key string, fallback int) int {
if v := os.Getenv(key); v != "" {
if n, err := strconv.Atoi(v); err == nil {
return n
}
}
return fallback
}
+60
View File
@@ -0,0 +1,60 @@
package httpserver
import (
"time"
"github.com/gin-gonic/gin"
"mrcc/internal/config"
"mrcc/pkg/response"
)
// New 创建一个配置好中间件的 Gin 实例,并注册 /health 端点。
func New(cfg *config.ServiceConfig) *gin.Engine {
gin.SetMode(cfg.GinMode)
r := gin.New()
// 中间件
r.Use(gin.Recovery())
r.Use(gin.LoggerWithFormatter(func(p gin.LogFormatterParams) string {
return p.TimeStamp.Format(time.RFC3339) + " | " + p.Method + " | " + p.Path + " | " +
itoa(p.StatusCode) + " | " + p.Latency.String() + "\n"
}))
// CORS
r.Use(func(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
})
// 健康检查
r.GET("/health", func(c *gin.Context) {
response.OK(c, gin.H{
"service": cfg.Name,
"status": "running",
})
})
return r
}
func itoa(n int) string {
if n == 0 {
return "0"
}
buf := [10]byte{}
pos := len(buf)
for n > 0 {
pos--
buf[pos] = byte('0' + n%10)
n /= 10
}
return string(buf[pos:])
}
+26
View File
@@ -0,0 +1,26 @@
package logger
import (
"log/slog"
"os"
)
// 全局默认 logger,使用 JSON handler 输出到 stdout。
var defaultLogger *slog.Logger
func init() {
defaultLogger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
}))
slog.SetDefault(defaultLogger)
}
// Default 返回全局 logger 实例
func Default() *slog.Logger {
return defaultLogger
}
// WithService 返回带有 service 字段的 logger
func WithService(name string) *slog.Logger {
return defaultLogger.With("service", name)
}
+27
View File
@@ -0,0 +1,27 @@
package response
import "github.com/gin-gonic/gin"
// 标准响应结构
// {"code": 0, "message": "ok", "data": ...}
const codeOK = 0
const codeError = 1
// OK 返回成功响应
func OK(c *gin.Context, data any) {
c.JSON(200, gin.H{
"code": codeOK,
"message": "ok",
"data": data,
})
}
// Error 返回错误响应
func Error(c *gin.Context, httpStatus int, message string) {
c.JSON(httpStatus, gin.H{
"code": codeError,
"message": message,
"data": nil,
})
}
+2487
View File
@@ -0,0 +1,2487 @@
<!DOCTYPE html>
<html lang="zh-CN" class="dark" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RedCircuit 红石回路 - 完整开发文档</title>
<style id="theme-vars">
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=JetBrains+Mono:wght@400;500;600;700&family=Noto+Sans+SC:wght@400;500;700;900&display=swap');
:root {
--rc-primary-50:#FEF2F2;--rc-primary-100:#FEE2E2;--rc-primary-200:#FECACA;--rc-primary-300:#FCA5A5;--rc-primary-400:#F87171;--rc-primary-500:#E83229;--rc-primary-600:#DC2626;--rc-primary-700:#B91C1C;--rc-primary-800:#991B1B;--rc-primary-900:#7F1D1D;
--rc-neutral-0:#FFFFFF;--rc-neutral-50:#F6F7F8;--rc-neutral-100:#E3E6EA;--rc-neutral-200:#C7CCD3;--rc-neutral-300:#9BA3AE;--rc-neutral-400:#6B7280;--rc-neutral-500:#4B5563;--rc-neutral-600:#374151;--rc-neutral-700:#2A3441;--rc-neutral-800:#1C2230;--rc-neutral-850:#161B22;--rc-neutral-900:#0E1116;--rc-neutral-950:#080B0F;
--state-success:#3FB950;--state-warning:#D29922;--state-error:#F85149;--state-info:#58A6FF;
--rc-radius-small:2px;--rc-radius-medium:8px;--rc-radius-large:12px;--rc-radius-full:9999px;
--rc-font-pixel:'Press Start 2P','JetBrains Mono',monospace;--rc-font-mono:'JetBrains Mono','Cascadia Code',Consolas,monospace;--rc-font-body:'Noto Sans SC',system-ui,-apple-system,'Segoe UI',sans-serif;
--rc-background:#F6F7F8;--rc-foreground:#0E1116;--rc-card:#FFFFFF;--rc-card-foreground:#0E1116;--rc-popover:#FFFFFF;--rc-popover-foreground:#0E1116;--rc-primary:#E83229;--rc-primary-foreground:#FFFFFF;--rc-muted:#E3E6EA;--rc-muted-foreground:#6B7280;--rc-border:#C7CCD3;--rc-input:#E3E6EA;--rc-ring:#E83229;
--rc-surface-1:#FFFFFF;--rc-surface-2:#F6F7F8;--rc-surface-3:#E3E6EA;
--rc-grid-line:rgba(42,52,65,0.08);--rc-grid-dot:rgba(42,52,65,0.12);--rc-trace:rgba(232,50,41,0.15);--rc-trace-glow:rgba(232,50,41,0.35);
}
.dark {
--rc-background:#0E1116;--rc-foreground:#E8EAED;--rc-card:#161B22;--rc-card-foreground:#E8EAED;--rc-popover:#1C2230;--rc-popover-foreground:#E8EAED;--rc-primary:#E83229;--rc-primary-foreground:#FFFFFF;--rc-muted:#1C2230;--rc-muted-foreground:#8B949E;--rc-border:#2A3441;--rc-input:#1C2230;--rc-ring:#E83229;
--rc-surface-1:#161B22;--rc-surface-2:#1C2230;--rc-surface-3:#2A3441;
--rc-grid-line:rgba(139,148,158,0.06);--rc-grid-dot:rgba(139,148,158,0.10);--rc-trace:rgba(232,50,41,0.12);--rc-trace-glow:rgba(232,50,41,0.30);
}
.font-pixel{font-family:var(--rc-font-pixel);letter-spacing:0.02em;line-height:1.4;}
.font-mono{font-family:var(--rc-font-mono);letter-spacing:-0.01em;}
.font-body{font-family:var(--rc-font-body);}
.text-pixel-lg{font-family:var(--rc-font-pixel);font-size:1.5rem;line-height:1.6;letter-spacing:0.02em;}
.text-pixel-sm{font-family:var(--rc-font-pixel);font-size:0.625rem;line-height:1.8;letter-spacing:0.05em;}
.text-mono{font-family:var(--rc-font-mono);font-size:0.8125rem;letter-spacing:-0.01em;}
.text-mono-sm{font-family:var(--rc-font-mono);font-size:0.6875rem;letter-spacing:0;}
.pixel-border{border:2px solid var(--rc-border);box-shadow:0 0 0 2px var(--rc-background),0 0 0 4px var(--rc-border);}
.pixel-corner{clip-path:polygon(0 4px,4px 4px,4px 0,calc(100% - 4px) 0,calc(100% - 4px) 4px,100% 4px,100% calc(100% - 4px),calc(100% - 4px) calc(100% - 4px),calc(100% - 4px) 100%,4px 100%,4px calc(100% - 4px),0 calc(100% - 4px));}
.circuit-grid{background-image:linear-gradient(var(--rc-grid-line) 1px,transparent 1px),linear-gradient(90deg,var(--rc-grid-line) 1px,transparent 1px);background-size:24px 24px;}
.circuit-grid-dots{background-image:radial-gradient(var(--rc-grid-dot) 1px,transparent 1px);background-size:16px 16px;}
.pcb-traces{background-image:linear-gradient(var(--rc-trace) 1px,transparent 1px),linear-gradient(90deg,var(--rc-trace) 1px,transparent 1px),radial-gradient(var(--rc-trace-glow) 1.5px,transparent 2px);background-size:48px 48px,48px 48px,48px 48px;background-position:0 0,0 0,24px 24px;}
.redstone-glow{box-shadow:0 0 8px var(--rc-trace-glow),0 0 16px rgba(232,50,41,0.15);}
.redstone-text-glow{text-shadow:0 0 8px rgba(232,50,41,0.4);}
.dark ::-webkit-scrollbar{width:8px;height:8px;}
.dark ::-webkit-scrollbar-track{background:var(--rc-neutral-900);}
.dark ::-webkit-scrollbar-thumb{background:var(--rc-neutral-700);border-radius:2px;}
.dark ::-webkit-scrollbar-thumb:hover{background:var(--rc-neutral-600);}
</style>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.3.1/dist/index.global.js"></script>
<script src="https://unpkg.com/lucide@1.8.0/dist/umd/lucide.min.js"></script>
<style type="text/tailwindcss">
@theme inline {
--color-background: var(--rc-background);
--color-foreground: var(--rc-foreground);
--color-card: var(--rc-card);
--color-card-foreground: var(--rc-card-foreground);
--color-popover: var(--rc-popover);
--color-popover-foreground: var(--rc-popover-foreground);
--color-primary: var(--rc-primary);
--color-primary-foreground: var(--rc-primary-foreground);
--color-muted: var(--rc-muted);
--color-muted-foreground: var(--rc-muted-foreground);
--color-border: var(--rc-border);
--color-input: var(--rc-input);
--color-ring: var(--rc-ring);
--radius-sm: var(--rc-radius-small);
--radius-md: var(--rc-radius-medium);
--radius-lg: var(--rc-radius-large);
}
@layer base {
body { background: var(--rc-background); color: var(--rc-foreground); }
td, th { @apply break-words; word-break: break-all; word-break: auto-phrase; }
th { @apply whitespace-nowrap; }
}
</style>
<style id="semantic-token-fallback">
.bg-background{background-color:var(--rc-background);}.text-background{color:var(--rc-background);}.border-background{border-color:var(--rc-background);}.ring-background{--tw-ring-color:var(--rc-background);}
.bg-foreground{background-color:var(--rc-foreground);}.text-foreground{color:var(--rc-foreground);}.border-foreground{border-color:var(--rc-foreground);}.ring-foreground{--tw-ring-color:var(--rc-foreground);}
.bg-card{background-color:var(--rc-card);}.text-card{color:var(--rc-card);}.border-card{border-color:var(--rc-card);}.ring-card{--tw-ring-color:var(--rc-card);}
.bg-card-foreground{background-color:var(--rc-card-foreground);}.text-card-foreground{color:var(--rc-card-foreground);}.border-card-foreground{border-color:var(--rc-card-foreground);}.ring-card-foreground{--tw-ring-color:var(--rc-card-foreground);}
.bg-popover{background-color:var(--rc-popover);}.text-popover{color:var(--rc-popover);}.border-popover{border-color:var(--rc-popover);}.ring-popover{--tw-ring-color:var(--rc-popover);}
.bg-popover-foreground{background-color:var(--rc-popover-foreground);}.text-popover-foreground{color:var(--rc-popover-foreground);}.border-popover-foreground{border-color:var(--rc-popover-foreground);}.ring-popover-foreground{--tw-ring-color:var(--rc-popover-foreground);}
.bg-primary{background-color:var(--rc-primary);}.text-primary{color:var(--rc-primary);}.border-primary{border-color:var(--rc-primary);}.ring-primary{--tw-ring-color:var(--rc-primary);}
.bg-primary-foreground{background-color:var(--rc-primary-foreground);}.text-primary-foreground{color:var(--rc-primary-foreground);}.border-primary-foreground{border-color:var(--rc-primary-foreground);}.ring-primary-foreground{--tw-ring-color:var(--rc-primary-foreground);}
.bg-muted{background-color:var(--rc-muted);}.text-muted{color:var(--rc-muted);}.border-muted{border-color:var(--rc-muted);}.ring-muted{--tw-ring-color:var(--rc-muted);}
.bg-muted-foreground{background-color:var(--rc-muted-foreground);}.text-muted-foreground{color:var(--rc-muted-foreground);}.border-muted-foreground{border-color:var(--rc-muted-foreground);}.ring-muted-foreground{--tw-ring-color:var(--rc-muted-foreground);}
.bg-border{background-color:var(--rc-border);}.text-border{color:var(--rc-border);}.border-border{border-color:var(--rc-border);}.ring-border{--tw-ring-color:var(--rc-border);}
.bg-input{background-color:var(--rc-input);}.text-input{color:var(--rc-input);}.border-input{border-color:var(--rc-input);}.ring-input{--tw-ring-color:var(--rc-input);}
.bg-ring{background-color:var(--rc-ring);}.text-ring{color:var(--rc-ring);}.border-ring{border-color:var(--rc-ring);}.ring-ring{--tw-ring-color:var(--rc-ring);}
</style>
<style>
.no-scrollbar::-webkit-scrollbar{display:none;}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none;}
[data-icon]{display:inline-flex;align-items:center;justify-content:center;-webkit-mask-size:contain;mask-size:contain;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center;background-color:currentColor;}
</style>
<style id="critical-layout">
*{box-sizing:border-box;}
html{scroll-behavior:smooth;}
body{margin:0;font-family:var(--rc-font-body);background-color:var(--rc-background);color:var(--rc-foreground);overflow-x:hidden;}
.topbar{position:fixed;top:0;left:0;right:0;height:56px;z-index:200;display:flex;align-items:center;gap:16px;padding:0 20px;background-color:var(--rc-surface-2);border-bottom:1px solid var(--rc-border);}
.topbar-logo{font-family:var(--rc-font-pixel);font-size:0.75rem;color:var(--rc-primary);letter-spacing:0.02em;}
.topbar-meta{font-family:var(--rc-font-mono);font-size:0.75rem;color:var(--rc-muted-foreground);}
.topbar-spacer{flex:1;}
.topbar-back{display:inline-flex;align-items:center;gap:6px;font-family:var(--rc-font-mono);font-size:0.75rem;color:var(--rc-muted-foreground);text-decoration:none;padding:6px 12px;border:1px solid var(--rc-border);border-radius:var(--rc-radius-small);transition:color 0.15s ease,border-color 0.15s ease,background-color 0.15s ease;}
.topbar-back:hover{color:var(--rc-primary);border-color:var(--rc-primary);background-color:var(--rc-surface-3);}
.toc-sidebar{position:fixed;top:56px;left:0;width:260px;height:calc(100vh - 56px);overflow-y:auto;background-color:var(--rc-surface-1);border-right:1px solid var(--rc-border);padding:16px 0 40px;}
.toc-title{font-family:var(--rc-font-pixel);font-size:0.5625rem;color:var(--rc-muted-foreground);letter-spacing:0.05em;padding:0 20px 12px;}
.toc-link{display:block;padding:7px 20px;font-family:var(--rc-font-body);font-size:0.8125rem;color:var(--rc-muted-foreground);text-decoration:none;border-left:2px solid transparent;transition:color 0.15s ease,background-color 0.15s ease,border-color 0.15s ease;}
.toc-link:hover,.toc-link.active{color:var(--rc-primary);background-color:var(--rc-surface-2);border-left-color:var(--rc-primary);}
.toc-num{font-family:var(--rc-font-mono);font-size:0.6875rem;margin-right:6px;color:var(--rc-muted-foreground);}
.toc-link:hover .toc-num,.toc-link.active .toc-num{color:var(--rc-primary);}
.doc-main{margin-left:260px;padding-top:56px;}
.doc-container{max-width:900px;margin:0 auto;padding:40px 32px 80px;}
.doc-section{margin-bottom:64px;scroll-margin-top:72px;}
.section-eyebrow{font-family:var(--rc-font-pixel);font-size:0.5625rem;color:var(--rc-primary);letter-spacing:0.08em;margin-bottom:10px;text-transform:uppercase;}
.section-title{font-family:var(--rc-font-body);font-size:1.625rem;font-weight:900;margin:0 0 6px;color:var(--rc-foreground);line-height:1.3;}
.section-desc{color:var(--rc-muted-foreground);font-size:0.9rem;margin:0 0 24px;line-height:1.6;}
.subsection-title{font-family:var(--rc-font-body);font-size:1.125rem;font-weight:700;margin:32px 0 14px;color:var(--rc-foreground);display:flex;align-items:center;gap:10px;}
.subsection-title::before{content:'';width:4px;height:18px;background-color:var(--rc-primary);border-radius:var(--rc-radius-small);}
.body-text{font-size:0.9rem;line-height:1.75;color:var(--rc-foreground);margin:0 0 16px;}
.body-text strong{color:var(--rc-primary);font-weight:700;}
.table-wrap{overflow-x:auto;margin-bottom:24px;border-radius:var(--rc-radius-medium);}
table.doc-table{width:100%;border-collapse:collapse;background-color:var(--rc-card);border:1px solid var(--rc-border);font-size:0.8125rem;}
table.doc-table thead th{background-color:var(--rc-surface-3);color:var(--rc-foreground);text-align:left;padding:11px 14px;font-weight:700;font-family:var(--rc-font-mono);font-size:0.75rem;letter-spacing:0.02em;border-bottom:1px solid var(--rc-border);white-space:nowrap;}
table.doc-table tbody td{padding:10px 14px;border-bottom:1px solid var(--rc-border);color:var(--rc-foreground);vertical-align:top;}
table.doc-table tbody tr:last-child td{border-bottom:none;}
table.doc-table tbody tr{transition:background-color 0.15s ease;}
table.doc-table tbody tr:hover{background-color:var(--rc-surface-2);}
table.doc-table .num{font-family:var(--rc-font-mono);font-variant-numeric:tabular-nums;}
.pill{display:inline-block;font-family:var(--rc-font-mono);font-size:0.6875rem;padding:2px 8px;border-radius:var(--rc-radius-small);border:1px solid var(--rc-border);}
.pill-power{color:var(--state-error);border-color:var(--state-error);}
.pill-wire{color:var(--state-info);border-color:var(--state-info);}
.pill-switch{color:var(--state-warning);border-color:var(--state-warning);}
.pill-output{color:var(--state-success);border-color:var(--state-success);}
.pill-logic{color:var(--rc-primary);border-color:var(--rc-primary);}
.pill-special{color:var(--rc-muted-foreground);border-color:var(--rc-muted-foreground);}
pre.code-block{background-color:var(--rc-surface-2);border:1px solid var(--rc-border);border-radius:var(--rc-radius-medium);padding:18px 20px;overflow-x:auto;font-family:var(--rc-font-mono);font-size:0.78rem;line-height:1.65;color:var(--rc-foreground);margin:0 0 24px;}
pre.code-block .kw{color:var(--rc-primary);}
pre.code-block .fn{color:var(--state-info);}
pre.code-block .cm{color:var(--rc-muted-foreground);}
pre.code-block .st{color:var(--state-success);}
.info-card{background-color:var(--rc-card);border:1px solid var(--rc-border);border-radius:var(--rc-radius-medium);padding:20px;margin-bottom:24px;}
.info-card-title{font-family:var(--rc-font-mono);font-size:0.8125rem;font-weight:700;color:var(--rc-foreground);margin:0 0 12px;}
.kv-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:14px;}
.kv-item{background-color:var(--rc-surface-2);border:1px solid var(--rc-border);border-radius:var(--rc-radius-small);padding:12px 14px;}
.kv-label{font-family:var(--rc-font-mono);font-size:0.6875rem;color:var(--rc-muted-foreground);margin-bottom:4px;}
.kv-value{font-family:var(--rc-font-mono);font-size:0.875rem;font-weight:700;color:var(--rc-foreground);}
.arch-diagram{display:flex;flex-direction:column;align-items:center;gap:0;padding:28px 16px;background-color:var(--rc-card);border:1px solid var(--rc-border);border-radius:var(--rc-radius-medium);margin-bottom:24px;}
.arch-layer{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;width:100%;}
.arch-node{background-color:var(--rc-surface-2);border:1px solid var(--rc-border);border-radius:var(--rc-radius-medium);padding:12px 16px;font-family:var(--rc-font-mono);font-size:0.75rem;text-align:center;min-width:130px;color:var(--rc-foreground);}
.arch-node.client{border-color:var(--rc-primary);background-color:var(--rc-surface-3);}
.arch-node.gateway{border-color:var(--state-info);}
.arch-node.data{border-color:var(--state-warning);}
.arch-node .arch-node-sub{display:block;font-size:0.625rem;color:var(--rc-muted-foreground);margin-top:3px;}
.arch-connector{display:flex;flex-direction:column;align-items:center;padding:6px 0;color:var(--rc-muted-foreground);}
.arch-connector .line{width:2px;height:14px;background-color:var(--rc-border);}
.arch-connector .label{font-family:var(--rc-font-mono);font-size:0.625rem;padding:1px 8px;}
.signal-atten{background-color:var(--rc-surface-2);border:1px solid var(--rc-border);border-radius:var(--rc-radius-medium);padding:20px;margin-bottom:24px;overflow-x:auto;}
.signal-atten-row{display:flex;align-items:center;gap:4px;flex-wrap:nowrap;font-family:var(--rc-font-mono);font-size:0.8125rem;min-width:max-content;}
.signal-atten-cell{padding:6px 10px;border:1px solid var(--rc-border);border-radius:var(--rc-radius-small);background-color:var(--rc-card);font-weight:700;}
.signal-atten-arrow{color:var(--rc-muted-foreground);}
.chain-flow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:20px;background-color:var(--rc-card);border:1px solid var(--rc-border);border-radius:var(--rc-radius-medium);margin-bottom:24px;}
.chain-node{background-color:var(--rc-surface-2);border:1px solid var(--rc-border);border-radius:var(--rc-radius-small);padding:8px 12px;font-family:var(--rc-font-mono);font-size:0.75rem;}
.chain-arrow{color:var(--rc-primary);font-family:var(--rc-font-mono);font-weight:700;}
.formula-box{background-color:var(--rc-surface-2);border:1px solid var(--rc-border);border-left:3px solid var(--rc-primary);border-radius:var(--rc-radius-medium);padding:16px 20px;margin-bottom:24px;font-family:var(--rc-font-mono);font-size:0.8125rem;color:var(--rc-foreground);overflow-x:auto;}
.doc-footer{margin-left:260px;padding:32px;border-top:1px solid var(--rc-border);background-color:var(--rc-surface-1);text-align:center;}
.doc-footer p{font-family:var(--rc-font-mono);font-size:0.75rem;color:var(--rc-muted-foreground);margin:4px 0;}
.mobile-toggle{display:none;font-family:var(--rc-font-mono);font-size:0.75rem;color:var(--rc-foreground);background:transparent;border:1px solid var(--rc-border);border-radius:var(--rc-radius-small);padding:6px 10px;cursor:pointer;}
@media (max-width:960px){
.toc-sidebar{transform:translateX(-100%);transition:transform 0.25s ease;z-index:150;box-shadow:0 0 24px rgba(0,0,0,0.4);}
.toc-sidebar.open{transform:translateX(0);}
.doc-main{margin-left:0;}
.doc-footer{margin-left:0;}
.mobile-toggle{display:inline-flex;}
.doc-container{padding:28px 18px 60px;}
}
@media (prefers-reduced-motion:reduce){
*,*::before,*::after{animation-duration:0.001ms !important;animation-iteration-count:1 !important;transition-duration:0.001ms !important;scroll-behavior:auto !important;}
html{scroll-behavior:auto;}
}
</style>
</head>
<body class="min-h-screen font-sans antialiased">
<header class="topbar">
<button class="mobile-toggle" id="tocToggle" aria-label="切换目录">目录</button>
<span class="topbar-logo redstone-text-glow">RedCircuit</span>
<span class="topbar-meta">完整开发文档 v1.0</span>
<span class="topbar-spacer"></span>
<span class="topbar-meta">2026-08-07</span>
<a class="topbar-back" href="../pages/landing.html" data-dom-id="btn-back-home">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5"/><path d="M12 19l-7-7 7-7"/></svg>
返回首页
</a>
</header>
<aside class="toc-sidebar" id="tocSidebar">
<p class="toc-title">目录 / TABLE OF CONTENTS</p>
<nav>
<a class="toc-link" href="#overview"><span class="toc-num">01</span>项目概述</a>
<a class="toc-link" href="#architecture"><span class="toc-num">02</span>技术架构</a>
<a class="toc-link" href="#tech-stack"><span class="toc-num">03</span>技术栈选型</a>
<a class="toc-link" href="#database"><span class="toc-num">04</span>数据库设计</a>
<a class="toc-link" href="#api"><span class="toc-num">05</span>API设计</a>
<a class="toc-link" href="#simulation"><span class="toc-num">06</span>信号仿真引擎</a>
<a class="toc-link" href="#components"><span class="toc-num">07</span>元器件规格手册</a>
<a class="toc-link" href="#game-modes"><span class="toc-num">08</span>游戏模式规则</a>
<a class="toc-link" href="#economy"><span class="toc-num">09</span>货币与经济系统</a>
<a class="toc-link" href="#user-system"><span class="toc-num">10</span>用户系统</a>
<a class="toc-link" href="#milestones"><span class="toc-num">11</span>开发里程碑</a>
<a class="toc-link" href="#deployment"><span class="toc-num">12</span>部署与运维</a>
<a class="toc-link" href="#risks"><span class="toc-num">13</span>风险评估</a>
<a class="toc-link" href="#sprint-plan"><span class="toc-num">15</span>Sprint分解与排期</a>
<a class="toc-link" href="#team"><span class="toc-num">16</span>团队组织与职责</a>
<a class="toc-link" href="#client-modules"><span class="toc-num">17</span>客户端模块详设</a>
<a class="toc-link" href="#server-services"><span class="toc-num">18</span>服务端微服务详设</a>
<a class="toc-link" href="#relay-server"><span class="toc-num">18.5</span>联机中转站开发</a>
<a class="toc-link" href="#testing"><span class="toc-num">19</span>测试与质量保障</a>
<a class="toc-link" href="#performance"><span class="toc-num">20</span>性能优化方案</a>
<a class="toc-link" href="#security"><span class="toc-num">21</span>安全实施方案</a>
<a class="toc-link" href="#cicd"><span class="toc-num">22</span>CI/CD流水线</a>
<a class="toc-link" href="#budget"><span class="toc-num">23</span>预算与成本估算</a>
<a class="toc-link" href="#rollout"><span class="toc-num">24</span>上线发布策略</a>
<a class="toc-link" href="#appendix"><span class="toc-num">25</span>附录</a>
</nav>
</aside>
<main class="doc-main">
<div class="doc-container circuit-grid-dots">
<!-- ===== Section 1 ===== -->
<section class="doc-section" id="overview">
<p class="section-eyebrow">01 / OVERVIEW</p>
<h2 class="section-title">项目概述</h2>
<p class="section-desc">RedCircuit · 红石回路是一款融合电路图、Minecraft 像素方块与红石逻辑的桌面客户端游戏,配备完整货币经济与用户体系。</p>
<p class="body-text">RedCircuit 将<strong>电路图工程</strong>的严谨性、<strong>像素方块</strong>的视觉表现力与<strong>Minecraft 红石逻辑</strong>的创造性玩法结合为一款原生桌面客户端游戏。玩家在 PCB 风格的网格画布上放置元器件、搭建信号回路、解谜闯关、自动化生产,或在多人模式中与他人对战协作。游戏内置红石币与金币双货币体系,支持用户注册登录、等级成长与成就解锁。</p>
<div class="info-card">
<p class="info-card-title">核心定位</p>
<div class="kv-grid">
<div class="kv-item"><div class="kv-label">目标平台</div><div class="kv-value">Windows / macOS 桌面客户端</div></div>
<div class="kv-item"><div class="kv-label">发行渠道</div><div class="kv-value">官网独立安装包 + 自动更新</div></div>
<div class="kv-item"><div class="kv-label">目标受众</div><div class="kv-value">红石工程师 / 电路爱好者 / 解谜玩家</div></div>
<div class="kv-item"><div class="kv-label">商业模式</div><div class="kv-value">免费游玩 + 内购 + 创意工坊分成</div></div>
</div>
</div>
<h3 class="subsection-title">核心价值主张</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>维度</th><th>价值主张</th><th>差异化优势</th></tr></thead>
<tbody>
<tr><td>玩法深度</td><td>完整还原红石信号强度、衰减、延迟与 BUD 更新机制</td><td>市面同类产品多简化逻辑,本作保留硬核仿真</td></tr>
<tr><td>视觉风格</td><td>PCB 电路板 × 像素方块混搭美学</td><td>区别于纯像素或纯电路模拟器</td></tr>
<tr><td>内容体量</td><td>80 种元器件、240 个解谜关卡、4 大模式</td><td>单机+联机兼顾,内容耐玩度高</td></tr>
<tr><td>经济闭环</td><td>红石币产出消耗平衡 + 金币充值 + 创意工坊交易</td><td>UGC 生态自循环,降低内容更新成本</td></tr>
<tr><td>社交竞技</td><td>多人对战排位赛季 + 协作建造 + 蓝图分享</td><td>红石领域稀缺的竞技化设计</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">关键指标目标</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>指标</th><th>上线首月目标</th><th>稳定期目标 (M12)</th><th>说明</th></tr></thead>
<tbody>
<tr><td>DAU</td><td class="num">15,000</td><td class="num">60,000</td><td>日活跃用户</td></tr>
<tr><td>MAU</td><td class="num">80,000</td><td class="num">300,000</td><td>月活跃用户</td></tr>
<tr><td>次日留存</td><td class="num">42%</td><td class="num">50%</td><td>新手引导优化后提升</td></tr>
<tr><td>七日留存</td><td class="num">22%</td><td class="num">30%</td><td>关卡内容驱动</td></tr>
<tr><td>付费率</td><td class="num">3.5%</td><td class="num">6%</td><td>金币充值 + 创意工坊</td></tr>
<tr><td>ARPPU</td><td class="num">¥28</td><td class="num">¥45</td><td>每付费用户平均收益</td></tr>
<tr><td>蓝图上传量</td><td class="num">2,000</td><td class="num">20,000/月</td><td>UGC 生态健康度</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 2 ===== -->
<section class="doc-section" id="architecture">
<p class="section-eyebrow">02 / ARCHITECTURE</p>
<h2 class="section-title">技术架构</h2>
<p class="section-desc">客户端-服务端分离架构,桌面客户端负责渲染与本地仿真,服务端负责账户、经济、联机与内容分发。</p>
<h3 class="subsection-title">2.1 客户端架构</h3>
<p class="body-text">客户端基于 <strong>Unity 2024 LTS (C#)</strong> 构建,采用 2D 瓦片网格渲染器配合自定义红石信号辉光着色器。UI 层使用 Unity UI Toolkit (UXML/USS) 处理数据密集型界面(商店、背包、排行榜),编辑器画布使用 IMGUI 实现高性能即时绘制。电路仿真引擎为自定义基于 ECS 的信号传播系统,本地存储采用 SQLite 存档、蓝图与设置。</p>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>模块</th><th>技术方案</th><th>职责</th></tr></thead>
<tbody>
<tr><td>游戏引擎</td><td>Unity 2024 LTS (C#)</td><td>主循环、渲染、资源管理、跨平台打包</td></tr>
<tr><td>渲染层</td><td>2D Tile 网格渲染器 + 自定义辉光 Shader</td><td>方块绘制、红石信号高亮、粒子效果</td></tr>
<tr><td>UI 框架</td><td>Unity UI Toolkit (UXML/USS)</td><td>商店、背包、排行榜等数据界面</td></tr>
<tr><td>编辑器画布</td><td>IMGUI 即时模式</td><td>电路编辑画布高频重绘</td></tr>
<tr><td>仿真引擎</td><td>自定义 ECS 信号传播系统</td><td>红石信号强度、衰减、延迟、BUD 计算</td></tr>
<tr><td>本地存储</td><td>SQLite</td><td>存档、蓝图、设置、离线缓存</td></tr>
<tr><td>网络层</td><td>Unity Netcode for GameObjects / Photon</td><td>多人实时同步、房间管理</td></tr>
<tr><td>反作弊</td><td>客户端预测 + 服务端校验</td><td>多人模式经济与比赛结果验证</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">2.2 服务端架构</h3>
<p class="body-text">服务端采用 <strong>Go (Gin 框架)</strong> 构建 REST API 与 WebSocket 网关,按业务域拆分为五个微服务。主数据库使用 PostgreSQL 存储用户与交易数据,Redis 承担会话缓存、匹配队列与排行榜。文件存储使用 MinIO/S3 存放蓝图与回放,RabbitMQ 处理异步任务(经济结算、成就检查)。</p>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>微服务</th><th>职责</th><th>主要依赖</th></tr></thead>
<tbody>
<tr><td>auth-service</td><td>注册、登录、Token 签发与刷新、会话管理</td><td>PostgreSQL、Redis</td></tr>
<tr><td>economy-service</td><td>红石币/金币余额、交易流水、商店购买、充值核销</td><td>PostgreSQL、RabbitMQ</td></tr>
<tr><td>blueprint-service</td><td>蓝图上传、检索、购买、下载、评分、分类</td><td>PostgreSQL、MinIO</td></tr>
<tr><td>match-service</td><td>多人匹配、房间状态、对局结果、赛季排位</td><td>Redis、RabbitMQ</td></tr>
<tr><td>social-service</td><td>好友、聊天、公会、成就、动态</td><td>PostgreSQL、Redis</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">2.3 网络协议</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>协议</th><th>数据格式</th><th>适用场景</th></tr></thead>
<tbody>
<tr><td>REST API</td><td>JSON</td><td>用户认证、商店、蓝图 CRUD、排行榜查询</td></tr>
<tr><td>WebSocket</td><td>JSON 帧</td><td>多人实时同步、聊天、在线状态</td></tr>
<tr><td>二进制协议</td><td>Protobuf</td><td>电路编辑器实时协作(增量 Delta 同步)</td></tr>
<tr><td>消息队列</td><td>AMQP (RabbitMQ)</td><td>经济结算、成就检查等异步任务</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">2.4 系统架构图</h3>
<div class="arch-diagram">
<div class="arch-layer">
<div class="arch-node client">桌面客户端 (Unity 2024 LTS)<span class="arch-node-sub">渲染 / 本地仿真 / 离线存档</span></div>
</div>
<div class="arch-connector"><span class="line"></span><span class="label">HTTPS / WSS</span><span class="line"></span></div>
<div class="arch-layer">
<div class="arch-node gateway">API 网关 (Go / Gin)<span class="arch-node-sub">鉴权 / 路由 / 限流</span></div>
</div>
<div class="arch-connector"><span class="line"></span><span class="label">gRPC / 内部调用</span><span class="line"></span></div>
<div class="arch-layer">
<div class="arch-node">auth-service<span class="arch-node-sub">认证</span></div>
<div class="arch-node">economy-service<span class="arch-node-sub">经济</span></div>
<div class="arch-node">blueprint-service<span class="arch-node-sub">蓝图</span></div>
<div class="arch-node">match-service<span class="arch-node-sub">匹配</span></div>
<div class="arch-node">social-service<span class="arch-node-sub">社交</span></div>
</div>
<div class="arch-connector"><span class="line"></span><span class="label">持久化 / 缓存 / 对象存储 / 异步</span><span class="line"></span></div>
<div class="arch-layer">
<div class="arch-node data">PostgreSQL<span class="arch-node-sub">用户 / 交易</span></div>
<div class="arch-node data">Redis<span class="arch-node-sub">会话 / 排行</span></div>
<div class="arch-node data">MinIO / S3<span class="arch-node-sub">蓝图 / 回放</span></div>
<div class="arch-node data">RabbitMQ<span class="arch-node-sub">异步任务</span></div>
</div>
</div>
<h3 class="subsection-title">分层职责总览</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>层级</th><th>技术</th><th>职责</th></tr></thead>
<tbody>
<tr><td>表现层</td><td>Unity 2024 LTS + UI Toolkit</td><td>渲染、交互、本地仿真展示</td></tr>
<tr><td>网关层</td><td>Go / Gin + Nginx</td><td>请求路由、JWT 鉴权、限流熔断</td></tr>
<tr><td>服务层</td><td>5 个 Go 微服务</td><td>业务逻辑处理、事务编排</td></tr>
<tr><td>存储层</td><td>PostgreSQL + Redis + MinIO</td><td>持久化、缓存、对象存储</td></tr>
<tr><td>消息层</td><td>RabbitMQ</td><td>异步解耦、事件驱动</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 3 ===== -->
<section class="doc-section" id="tech-stack">
<p class="section-eyebrow">03 / TECH STACK</p>
<h2 class="section-title">技术栈选型</h2>
<p class="section-desc">各技术领域的选型方案、版本、选型理由与替代方案对照。</p>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>领域</th><th>技术选型</th><th>版本</th><th>选型理由</th><th>替代方案</th></tr></thead>
<tbody>
<tr><td>游戏引擎</td><td>Unity</td><td class="num">2024 LTS</td><td>生态成熟、跨平台打包、Asset Store 资源丰富、C# 开发效率高</td><td>Godot 4.x</td></tr>
<tr><td>客户端语言</td><td>C#</td><td class="num">12</td><td>Unity 原生语言、强类型、性能优良</td><td>GDScript (Godot)</td></tr>
<tr><td>UI 框架</td><td>Unity UI Toolkit</td><td class="num">2.0</td><td>类 Web 的 UXML/USS 体系、适合数据密集界面</td><td>UGUI、IMGUI</td></tr>
<tr><td>后端语言</td><td>Go</td><td class="num">1.22</td><td>高并发、编译快、内存占用低、适合微服务</td><td>Rust、Java</td></tr>
<tr><td>后端框架</td><td>Gin</td><td class="num">1.10</td><td>轻量高性能、中间件生态完善</td><td>Echo、Fiber</td></tr>
<tr><td>数据库</td><td>PostgreSQL</td><td class="num">16</td><td>事务可靠、JSONB 支持、扩展性强</td><td>MySQL、CockroachDB</td></tr>
<tr><td>缓存</td><td>Redis</td><td class="num">7.2</td><td>低延迟、排行榜 ZSET、会话存储</td><td>Valkey、Memcached</td></tr>
<tr><td>消息队列</td><td>RabbitMQ</td><td class="num">3.13</td><td>可靠投递、路由灵活、异步任务解耦</td><td>Kafka、NATS</td></tr>
<tr><td>文件存储</td><td>MinIO / S3</td><td class="num">-</td><td>兼容 S3 协议、可自托管或上云、成本低</td><td>Ceph、阿里云 OSS</td></tr>
<tr><td>CI/CD</td><td>GitHub Actions</td><td class="num">-</td><td>与代码仓库集成、矩阵构建、自托管 Runner</td><td>GitLab CI、Jenkins</td></tr>
<tr><td>监控</td><td>Prometheus + Grafana</td><td class="num">2.50 / 11</td><td>指标采集可视化、告警规则灵活</td><td>Datadog、Zabbix</td></tr>
<tr><td>错误追踪</td><td>Sentry</td><td class="num">24</td><td>客户端崩溃与服务端异常统一收集</td><td>Bugsnag、Crashlytics</td></tr>
<tr><td>数据分析</td><td>自建埋点 + ClickHouse</td><td class="num">24</td><td>玩家行为分析、留存漏斗、低成本海量查询</td><td>Mixpanel、Amplitude</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 4 ===== -->
<section class="doc-section" id="database">
<p class="section-eyebrow">04 / DATABASE</p>
<h2 class="section-title">数据库设计</h2>
<p class="section-desc">核心实体表结构定义,字段类型、约束与说明。</p>
<h3 class="subsection-title">users · 用户表</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>字段名</th><th>类型</th><th>约束</th><th>说明</th></tr></thead>
<tbody>
<tr><td>id</td><td>BIGSERIAL</td><td>PK</td><td>用户主键</td></tr>
<tr><td>username</td><td>VARCHAR(32)</td><td>UNIQUE NOT NULL</td><td>用户名</td></tr>
<tr><td>email</td><td>VARCHAR(128)</td><td>UNIQUE NOT NULL</td><td>邮箱</td></tr>
<tr><td>password_hash</td><td>VARCHAR(255)</td><td>NOT NULL</td><td>bcrypt 哈希</td></tr>
<tr><td>created_at</td><td>TIMESTAMPTZ</td><td>DEFAULT NOW()</td><td>注册时间</td></tr>
<tr><td>level</td><td>INT</td><td>DEFAULT 1</td><td>玩家等级</td></tr>
<tr><td>exp</td><td>INT</td><td>DEFAULT 0</td><td>经验值</td></tr>
<tr><td>redstone_coins</td><td>BIGINT</td><td>DEFAULT 0</td><td>红石币余额</td></tr>
<tr><td>gold_coins</td><td>INT</td><td>DEFAULT 0</td><td>金币余额</td></tr>
<tr><td>avatar</td><td>VARCHAR(255)</td><td>NULL</td><td>头像 URL</td></tr>
<tr><td>status</td><td>SMALLINT</td><td>DEFAULT 1</td><td>状态 1正常 0封禁</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">circuits · 电路表</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>字段名</th><th>类型</th><th>约束</th><th>说明</th></tr></thead>
<tbody>
<tr><td>id</td><td>BIGSERIAL</td><td>PK</td><td>电路主键</td></tr>
<tr><td>user_id</td><td>BIGINT</td><td>FK -> users.id</td><td>所属用户</td></tr>
<tr><td>name</td><td>VARCHAR(64)</td><td>NOT NULL</td><td>电路名称</td></tr>
<tr><td>data_json</td><td>JSONB</td><td>NOT NULL</td><td>元件布局与连线数据</td></tr>
<tr><td>grid_size</td><td>VARCHAR(16)</td><td>NOT NULL</td><td>画布尺寸 如 64x64</td></tr>
<tr><td>cost</td><td>INT</td><td>DEFAULT 0</td><td>元件总成本</td></tr>
<tr><td>mode</td><td>VARCHAR(16)</td><td>NOT NULL</td><td>模式 creative/puzzle/auto</td></tr>
<tr><td>created_at</td><td>TIMESTAMPTZ</td><td>DEFAULT NOW()</td><td>创建时间</td></tr>
<tr><td>updated_at</td><td>TIMESTAMPTZ</td><td>DEFAULT NOW()</td><td>更新时间</td></tr>
<tr><td>is_public</td><td>BOOLEAN</td><td>DEFAULT FALSE</td><td>是否公开</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">blueprints · 蓝图表</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>字段名</th><th>类型</th><th>约束</th><th>说明</th></tr></thead>
<tbody>
<tr><td>id</td><td>BIGSERIAL</td><td>PK</td><td>蓝图主键</td></tr>
<tr><td>circuit_id</td><td>BIGINT</td><td>FK -> circuits.id</td><td>关联电路</td></tr>
<tr><td>author_id</td><td>BIGINT</td><td>FK -> users.id</td><td>作者</td></tr>
<tr><td>title</td><td>VARCHAR(64)</td><td>NOT NULL</td><td>蓝图标题</td></tr>
<tr><td>description</td><td>TEXT</td><td>NULL</td><td>蓝图描述</td></tr>
<tr><td>price</td><td>INT</td><td>DEFAULT 0</td><td>售价(红石币)</td></tr>
<tr><td>download_count</td><td>INT</td><td>DEFAULT 0</td><td>下载数</td></tr>
<tr><td>rating</td><td>NUMERIC(3,2)</td><td>DEFAULT 0</td><td>评分 0-5</td></tr>
<tr><td>category</td><td>VARCHAR(32)</td><td>NOT NULL</td><td>分类</td></tr>
<tr><td>created_at</td><td>TIMESTAMPTZ</td><td>DEFAULT NOW()</td><td>发布时间</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">transactions · 交易流水表</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>字段名</th><th>类型</th><th>约束</th><th>说明</th></tr></thead>
<tbody>
<tr><td>id</td><td>BIGSERIAL</td><td>PK</td><td>流水主键</td></tr>
<tr><td>user_id</td><td>BIGINT</td><td>FK -> users.id</td><td>用户</td></tr>
<tr><td>type</td><td>VARCHAR(16)</td><td>NOT NULL</td><td>类型 earn/spend/recharge</td></tr>
<tr><td>item</td><td>VARCHAR(64)</td><td>NOT NULL</td><td>项目说明</td></tr>
<tr><td>amount</td><td>BIGINT</td><td>NOT NULL</td><td>金额</td></tr>
<tr><td>currency</td><td>VARCHAR(8)</td><td>NOT NULL</td><td>货币 redstone/gold</td></tr>
<tr><td>balance_after</td><td>BIGINT</td><td>NOT NULL</td><td>交易后余额</td></tr>
<tr><td>created_at</td><td>TIMESTAMPTZ</td><td>DEFAULT NOW()</td><td>交易时间</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">puzzle_levels · 解谜关卡表</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>字段名</th><th>类型</th><th>约束</th><th>说明</th></tr></thead>
<tbody>
<tr><td>id</td><td>BIGSERIAL</td><td>PK</td><td>关卡主键</td></tr>
<tr><td>chapter</td><td>SMALLINT</td><td>NOT NULL</td><td>章节 1-6</td></tr>
<tr><td>level_num</td><td>SMALLINT</td><td>NOT NULL</td><td>关卡序号</td></tr>
<tr><td>title</td><td>VARCHAR(64)</td><td>NOT NULL</td><td>关卡标题</td></tr>
<tr><td>description</td><td>TEXT</td><td>NULL</td><td>关卡描述</td></tr>
<tr><td>target_json</td><td>JSONB</td><td>NOT NULL</td><td>通关目标条件</td></tr>
<tr><td>constraints_json</td><td>JSONB</td><td>NOT NULL</td><td>限制规则</td></tr>
<tr><td>star_cost</td><td>SMALLINT</td><td>NOT NULL</td><td>成本星条件</td></tr>
<tr><td>star_delay</td><td>SMALLINT</td><td>NOT NULL</td><td>延迟星条件</td></tr>
<tr><td>reward</td><td>INT</td><td>NOT NULL</td><td>通关奖励红石币</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">multiplayer_matches · 多人对局表</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>字段名</th><th>类型</th><th>约束</th><th>说明</th></tr></thead>
<tbody>
<tr><td>id</td><td>BIGSERIAL</td><td>PK</td><td>对局主键</td></tr>
<tr><td>mode</td><td>VARCHAR(16)</td><td>NOT NULL</td><td>对战模式</td></tr>
<tr><td>status</td><td>VARCHAR(16)</td><td>NOT NULL</td><td>状态 waiting/playing/ended</td></tr>
<tr><td>players_json</td><td>JSONB</td><td>NOT NULL</td><td>玩家列表与分数</td></tr>
<tr><td>result_json</td><td>JSONB</td><td>NULL</td><td>对局结果</td></tr>
<tr><td>started_at</td><td>TIMESTAMPTZ</td><td>NULL</td><td>开始时间</td></tr>
<tr><td>ended_at</td><td>TIMESTAMPTZ</td><td>NULL</td><td>结束时间</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">achievements · 成就表</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>字段名</th><th>类型</th><th>约束</th><th>说明</th></tr></thead>
<tbody>
<tr><td>id</td><td>BIGSERIAL</td><td>PK</td><td>记录主键</td></tr>
<tr><td>user_id</td><td>BIGINT</td><td>FK -> users.id</td><td>用户</td></tr>
<tr><td>achievement_id</td><td>VARCHAR(32)</td><td>NOT NULL</td><td>成就标识</td></tr>
<tr><td>unlocked_at</td><td>TIMESTAMPTZ</td><td>DEFAULT NOW()</td><td>解锁时间</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 5 ===== -->
<section class="doc-section" id="api">
<p class="section-eyebrow">05 / API DESIGN</p>
<h2 class="section-title">API设计</h2>
<p class="section-desc">REST API 端点清单,涵盖认证、用户、电路、蓝图、商店、解谜、多人与排行榜。</p>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>方法</th><th>路径</th><th>说明</th><th>鉴权</th></tr></thead>
<tbody>
<tr><td>POST</td><td class="num">/api/auth/register</td><td>用户注册</td><td></td></tr>
<tr><td>POST</td><td class="num">/api/auth/login</td><td>用户登录</td><td></td></tr>
<tr><td>POST</td><td class="num">/api/auth/logout</td><td>退出登录</td><td></td></tr>
<tr><td>POST</td><td class="num">/api/auth/refresh</td><td>刷新 Token</td><td></td></tr>
<tr><td>GET</td><td class="num">/api/user/profile</td><td>获取个人资料</td><td></td></tr>
<tr><td>GET</td><td class="num">/api/user/balance</td><td>查询货币余额</td><td></td></tr>
<tr><td>GET</td><td class="num">/api/user/achievements</td><td>查询成就列表</td><td></td></tr>
<tr><td>GET</td><td class="num">/api/circuits</td><td>获取电路列表</td><td></td></tr>
<tr><td>POST</td><td class="num">/api/circuits</td><td>新建电路存档</td><td></td></tr>
<tr><td>GET</td><td class="num">/api/circuits/:id</td><td>获取电路详情</td><td></td></tr>
<tr><td>PUT</td><td class="num">/api/circuits/:id</td><td>更新电路</td><td></td></tr>
<tr><td>DELETE</td><td class="num">/api/circuits/:id</td><td>删除电路</td><td></td></tr>
<tr><td>POST</td><td class="num">/api/circuits/:id/share</td><td>分享电路为蓝图</td><td></td></tr>
<tr><td>GET</td><td class="num">/api/blueprints</td><td>浏览蓝图列表</td><td></td></tr>
<tr><td>POST</td><td class="num">/api/blueprints</td><td>上传蓝图</td><td></td></tr>
<tr><td>POST</td><td class="num">/api/blueprints/:id/buy</td><td>购买蓝图</td><td></td></tr>
<tr><td>GET</td><td class="num">/api/blueprints/:id/download</td><td>下载蓝图文件</td><td></td></tr>
<tr><td>POST</td><td class="num">/api/blueprints/:id/rate</td><td>评分</td><td></td></tr>
<tr><td>GET</td><td class="num">/api/shop/items</td><td>商店商品列表</td><td></td></tr>
<tr><td>POST</td><td class="num">/api/shop/buy</td><td>购买商品</td><td></td></tr>
<tr><td>GET</td><td class="num">/api/shop/history</td><td>购买历史</td><td></td></tr>
<tr><td>GET</td><td class="num">/api/puzzle/levels</td><td>解谜关卡列表</td><td></td></tr>
<tr><td>POST</td><td class="num">/api/puzzle/:id/submit</td><td>提交关卡答案</td><td></td></tr>
<tr><td>GET</td><td class="num">/api/puzzle/progress</td><td>关卡进度</td><td></td></tr>
<tr><td>POST</td><td class="num">/api/multiplayer/match</td><td>发起匹配</td><td></td></tr>
<tr><td>POST</td><td class="num">/api/multiplayer/join</td><td>加入房间</td><td></td></tr>
<tr><td>POST</td><td class="num">/api/multiplayer/result</td><td>提交对局结果</td><td></td></tr>
<tr><td>GET</td><td class="num">/api/leaderboard</td><td>排行榜</td><td></td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 6 ===== -->
<section class="doc-section" id="simulation">
<p class="section-eyebrow">06 / SIMULATION</p>
<h2 class="section-title">信号仿真引擎</h2>
<p class="section-desc">基于 ECS 的红石信号传播系统,完整还原强度衰减、延迟、BUD 更新等机制。</p>
<h3 class="subsection-title">仿真流程</h3>
<p class="body-text">仿真引擎每个 Tick 执行以下步骤:收集电源、重置信号网格、按强度优先级 BFS 传播、应用元件规则、处理延迟队列、更新输出元件、发射渲染事件。</p>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>步骤</th><th>操作</th><th>说明</th></tr></thead>
<tbody>
<tr><td class="num">1</td><td>收集电源</td><td>查询所有 PowerSourceComponent 且处于激活态的元件</td></tr>
<tr><td class="num">2</td><td>重置网格</td><td>将所有格子信号归零、标记未更新</td></tr>
<tr><td class="num">3</td><td>优先级入队</td><td>按信号强度降序将电源推入优先级队列</td></tr>
<tr><td class="num">4</td><td>BFS 传播</td><td>从队列取出格子,向邻居传播衰减后信号</td></tr>
<tr><td class="num">5</td><td>元件规则</td><td>对火把/中继器/比较器等应用特殊逻辑</td></tr>
<tr><td class="num">6</td><td>延迟处理</td><td>处理中继器等延迟元件的跨 Tick 输出</td></tr>
<tr><td class="num">7</td><td>输出更新</td><td>更新灯、活塞、门等输出元件状态</td></tr>
<tr><td class="num">8</td><td>渲染事件</td><td>向渲染系统发射变更差量,触发重绘</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">信号更新优先级</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>优先级</th><th>元件类型</th><th>更新顺序</th><th>说明</th></tr></thead>
<tbody>
<tr><td class="num">P0</td><td>电源类</td><td>最先计算</td><td>拉杆、按钮、压力板等直接设定信号源</td></tr>
<tr><td class="num">P1</td><td>红石火把</td><td>电源之后</td><td>反相输出,依赖输入端状态</td></tr>
<tr><td class="num">P2</td><td>比较器</td><td>火把之后</td><td>比较/减法模式,需两侧输入</td></tr>
<tr><td class="num">P3</td><td>中继器</td><td>比较器之后</td><td>延迟输出,受锁定信号影响</td></tr>
<tr><td class="num">P4</td><td>红石粉</td><td>主动元件之后</td><td>按强度衰减传播,BFS 遍历</td></tr>
<tr><td class="num">P5</td><td>输出类</td><td>最后更新</td><td>灯、活塞、门读取最终信号</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">信号属性</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>属性</th><th>取值范围</th><th>说明</th></tr></thead>
<tbody>
<tr><td>type</td><td>redstone / analog</td><td>红石数字信号或模拟比较信号</td></tr>
<tr><td>strength</td><td class="num">0 - 15</td><td>信号强度,15 为满强度</td></tr>
<tr><td>speed</td><td class="num">1 tick / 格</td><td>红石粉每格传播延迟 1 tick</td></tr>
<tr><td>direction</td><td>N / E / S / W / UP / DOWN</td><td>信号传播方向,支持六向</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">特殊规则</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>规则</th><th>触发条件</th><th>行为</th></tr></thead>
<tbody>
<tr><td>火把反相</td><td>火把附着方块被激活</td><td>火把熄灭,停止输出信号(NOT 门)</td></tr>
<tr><td>中继器锁定</td><td>侧面输入信号</td><td>中继器锁定当前输出值,不再响应输入变化</td></tr>
<tr><td>比较器检测</td><td>后方容器有物品</td><td>输出与物品填充率成正比的模拟信号</td></tr>
<tr><td>活塞链</td><td>活塞推动含活塞的方块</td><td>按顺序级联推动,最多 12 格</td></tr>
<tr><td>BUD 更新</td><td>方块状态变化未直接触发</td><td>观察者检测邻接变更并发出脉冲</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">仿真循环伪代码</h3>
<pre class="code-block"><span class="cm">// Redstone Signal Simulation Loop (ECS-based)</span>
<span class="kw">function</span> <span class="fn">simulateTick</span>(world):
<span class="cm">// 1. Collect all power sources</span>
powerSources = <span class="fn">query</span>(world, PowerSourceComponent)
<span class="cm">// 2. Reset signal grid</span>
<span class="kw">for</span> each cell <span class="kw">in</span> grid:
cell.signal = <span class="st">0</span>
cell.updated = <span class="kw">false</span>
<span class="cm">// 3. BFS propagation from sources (priority queue by strength)</span>
queue = <span class="fn">PriorityQueue</span>(descending <span class="kw">by</span> strength)
<span class="kw">for</span> source <span class="kw">in</span> powerSources:
<span class="kw">if</span> source.active:
queue.<span class="fn">push</span>(source.cell, source.strength)
<span class="cm">// 4. Propagate signals</span>
<span class="kw">while</span> queue not empty:
(cell, strength) = queue.<span class="fn">pop</span>()
<span class="kw">if</span> cell.signal >= strength: <span class="kw">continue</span> <span class="cm">// already stronger</span>
cell.signal = strength
cell.updated = <span class="kw">true</span>
<span class="cm">// Apply component-specific rules</span>
<span class="kw">switch</span> cell.component.type:
<span class="kw">case</span> WIRE: <span class="fn">propagateToNeighbors</span>(cell, strength - <span class="st">1</span>)
<span class="kw">case</span> TORCH: <span class="fn">invertAndPropagate</span>(cell, MAX_STRENGTH)
<span class="kw">case</span> REPEATER:
<span class="kw">if</span> cell.locked: <span class="kw">break</span>
<span class="fn">scheduleDelay</span>(cell, strength, <span class="st">1</span> tick)
<span class="kw">case</span> COMPARATOR:
output = <span class="fn">compare</span>(cell, strength)
<span class="fn">propagateForward</span>(cell, output)
<span class="kw">case</span> PISTON: <span class="fn">triggerPiston</span>(cell, strength > <span class="st">0</span>)
<span class="cm">// BUD (Block Update Detector) check</span>
<span class="kw">if</span> cell.component.budSensitive:
<span class="fn">notifyObservers</span>(cell)
<span class="cm">// 5. Resolve scheduled delays (repeaters, etc.)</span>
<span class="fn">processDelayedQueue</span>(world)
<span class="cm">// 6. Update outputs (lamps, pistons, doors)</span>
<span class="fn">updateOutputComponents</span>(world)
<span class="cm">// 7. Emit update events to render system</span>
<span class="fn">emitRenderUpdates</span>(world)</pre>
</section>
<!-- ===== Section 7 ===== -->
<section class="doc-section" id="components">
<p class="section-eyebrow">07 / COMPONENTS</p>
<h2 class="section-title">元器件规格手册</h2>
<p class="section-desc">全部分类元件的编号、成本、信号强度与特殊属性规格,共 8 大类 80 种元件。</p>
<h3 class="subsection-title">7.1 电源类 POWER</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>编号</th><th>元件名</th><th>成本(红石币)</th><th>信号强度</th><th>特殊属性</th></tr></thead>
<tbody>
<tr><td class="num">P-01</td><td><span class="pill pill-power">POWER</span> 红石火把</td><td class="num">50</td><td class="num">15</td><td>反相输出,可被附着方块熄灭</td></tr>
<tr><td class="num">P-02</td><td><span class="pill pill-power">POWER</span> 红石块</td><td class="num">100</td><td class="num">15</td><td>恒定满强度,不可关闭</td></tr>
<tr><td class="num">P-03</td><td><span class="pill pill-power">POWER</span> 拉杆</td><td class="num">30</td><td class="num">15</td><td>手动开关,双稳态</td></tr>
<tr><td class="num">P-04</td><td><span class="pill pill-power">POWER</span> 按钮</td><td class="num">40</td><td class="num">15</td><td>瞬时脉冲,自动复位</td></tr>
<tr><td class="num">P-05</td><td><span class="pill pill-power">POWER</span> 压力板</td><td class="num">35</td><td class="num">15</td><td>实体踩踏触发,离开复位</td></tr>
<tr><td class="num">P-06</td><td><span class="pill pill-power">POWER</span> 阳光探测器</td><td class="num">90</td><td class="num">0-15</td><td>输出随光照强度变化</td></tr>
<tr><td class="num">P-07</td><td><span class="pill pill-power">POWER</span> 阳光探测器(夜)</td><td class="num">90</td><td class="num">0-15</td><td>反向模式,夜间满强度</td></tr>
<tr><td class="num">P-08</td><td><span class="pill pill-power">POWER</span> 探测铁轨</td><td class="num">70</td><td class="num">15</td><td>矿车经过时触发脉冲</td></tr>
<tr><td class="num">P-09</td><td><span class="pill pill-power">POWER</span> 直流电源</td><td class="num">40</td><td class="num">0-15</td><td>可调稳压输出,输出强度旋钮 0-15 自由设定;适合精密电路调试供电</td></tr>
<tr><td class="num">P-10</td><td><span class="pill pill-power">POWER</span> 电池组</td><td class="num">85</td><td class="num">15</td><td>便携式移动电源,信号强度 15 恒定;可被活塞推动实现移动供电电路;电量有限需充电</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">7.2 传输类 WIRE</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>编号</th><th>元件名</th><th>成本(红石币)</th><th>信号强度</th><th>特殊属性</th></tr></thead>
<tbody>
<tr><td class="num">W-01</td><td><span class="pill pill-wire">WIRE</span> 红石粉</td><td class="num">5</td><td class="num">15->0</td><td>每格衰减 1,可爬升 1 格</td></tr>
<tr><td class="num">W-02</td><td><span class="pill pill-wire">WIRE</span> 红石中继器</td><td class="num">80</td><td class="num">15</td><td>恢复满强度,1-4 档延迟</td></tr>
<tr><td class="num">W-03</td><td><span class="pill pill-wire">WIRE</span> 红石比较器</td><td class="num">120</td><td class="num">0-15</td><td>比较/减法模式,可测容器</td></tr>
<tr><td class="num">W-04</td><td><span class="pill pill-wire">WIRE</span> 绝缘导线</td><td class="num">15</td><td class="num">15->0</td><td>不与交叉导线串扰,衰减同红石粉</td></tr>
<tr><td class="num">W-05</td><td><span class="pill pill-wire">WIRE</span> 信号桥</td><td class="num">25</td><td class="num">15</td><td>跨层传输信号,不衰减</td></tr>
<tr><td class="num">W-06</td><td><span class="pill pill-wire">WIRE</span> 铜导线</td><td class="num">12</td><td class="num">15->0</td><td>低电阻传输,每格仅衰减 0.5(每 2 格衰减 1);成本高于红石粉但传输距离翻倍</td></tr>
<tr><td class="num">W-07</td><td><span class="pill pill-wire">WIRE</span> 跳线</td><td class="num">18</td><td class="num">15</td><td>跨格架空连接,可跨越 1 格间隙直接连通两个元件;不与下方交叉导线串扰</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">信号衰减示意</h3>
<div class="signal-atten">
<div class="signal-atten-row">
<span class="signal-atten-cell" style="color:var(--rc-primary)">15</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.93">14</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.86">13</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.79">12</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.72">11</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.65">10</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.58">9</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.51">8</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.44">7</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.37">6</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.30">5</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.23">4</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.16">3</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.09">2</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.05">1</span>
<span class="signal-atten-arrow">-&gt;</span>
<span class="signal-atten-cell" style="opacity:0.02">0</span>
</div>
<p style="font-family:var(--rc-font-mono);font-size:0.6875rem;color:var(--rc-muted-foreground);margin:12px 0 0;">红石粉每传播 1 格衰减 1 点强度,中继器可恢复至满强度 15。</p>
</div>
<h3 class="subsection-title">7.3 开关/控制类 SWITCH</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>编号</th><th>元件名</th><th>成本(红石币)</th><th>信号强度</th><th>特殊属性</th></tr></thead>
<tbody>
<tr><td class="num">S-01</td><td><span class="pill pill-switch">SWITCH</span> 按钮木质</td><td class="num">40</td><td class="num">15</td><td>脉冲持续 1.5s</td></tr>
<tr><td class="num">S-02</td><td><span class="pill pill-switch">SWITCH</span> 按钮石质</td><td class="num">40</td><td class="num">15</td><td>脉冲持续 1s</td></tr>
<tr><td class="num">S-03</td><td><span class="pill pill-switch">SWITCH</span> 拉杆</td><td class="num">30</td><td class="num">15</td><td>双稳态手动开关</td></tr>
<tr><td class="num">S-04</td><td><span class="pill pill-switch">SWITCH</span> 压力板木质</td><td class="num">35</td><td class="num">15</td><td>所有实体触发</td></tr>
<tr><td class="num">S-05</td><td><span class="pill pill-switch">SWITCH</span> 压力板铁质</td><td class="num">50</td><td class="num">15</td><td>仅玩家触发</td></tr>
<tr><td class="num">S-06</td><td><span class="pill pill-switch">SWITCH</span> 压力板金质</td><td class="num">80</td><td class="num">15</td><td>仅玩家触发,信号更长</td></tr>
<tr><td class="num">S-07</td><td><span class="pill pill-switch">SWITCH</span> 绊线钩</td><td class="num">45</td><td class="num">15</td><td>绊线被触碰时触发</td></tr>
<tr><td class="num">S-08</td><td><span class="pill pill-switch">SWITCH</span> 阳光探测器</td><td class="num">90</td><td class="num">0-15</td><td>光照强度模拟输出</td></tr>
<tr><td class="num">S-09</td><td><span class="pill pill-switch">SWITCH</span> 观察者</td><td class="num">150</td><td class="num">15</td><td>检测前方方块变更,BUD 脉冲</td></tr>
<tr><td class="num">S-10</td><td><span class="pill pill-switch">SWITCH</span> 标靶</td><td class="num">60</td><td class="num">0-15</td><td>箭矢命中精度决定强度</td></tr>
<tr><td class="num">S-11</td><td><span class="pill pill-switch">SWITCH</span> 拨动开关</td><td class="num">25</td><td class="num">15</td><td>机械双稳态拨动开关,手动切换开/关;比拉杆更紧凑,可密集排列组成 DIP 开关阵列</td></tr>
<tr><td class="num">S-12</td><td><span class="pill pill-switch">SWITCH</span> 继电器</td><td class="num">120</td><td class="num">15</td><td>电磁开关,线圈通电吸合触点;支持常开/常闭双触点输出,实现电路隔离与跨域信号传递</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">7.4 输出类 OUTPUT</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>编号</th><th>元件名</th><th>成本(红石币)</th><th>信号强度</th><th>特殊属性</th></tr></thead>
<tbody>
<tr><td class="num">O-01</td><td><span class="pill pill-output">OUTPUT</span> 红石灯</td><td class="num">60</td><td class="num">>=1</td><td>接收信号即点亮</td></tr>
<tr><td class="num">O-02</td><td><span class="pill pill-output">OUTPUT</span> 活塞</td><td class="num">150</td><td class="num">>=1</td><td>推出方块,断电收回</td></tr>
<tr><td class="num">O-03</td><td><span class="pill pill-output">OUTPUT</span> 粘性活塞</td><td class="num">200</td><td class="num">>=1</td><td>推出并拉回方块</td></tr>
<tr><td class="num">O-04</td><td><span class="pill pill-output">OUTPUT</span> 发射器</td><td class="num">180</td><td class="num">>=1</td><td>脉冲触发发射物品</td></tr>
<tr><td class="num">O-05</td><td><span class="pill pill-output">OUTPUT</span> 投掷器</td><td class="num">120</td><td class="num">>=1</td><td>脉冲触发掉落物品</td></tr>
<tr><td class="num">O-06</td><td><span class="pill pill-output">OUTPUT</span> 漏斗</td><td class="num">100</td><td class="num">-</td><td>信号锁定时停止传输</td></tr>
<tr><td class="num">O-07</td><td><span class="pill pill-output">OUTPUT</span> 音符盒</td><td class="num">70</td><td class="num">>=1</td><td>脉冲触发播放音符</td></tr>
<tr><td class="num">O-08</td><td><span class="pill pill-output">OUTPUT</span> TNT</td><td class="num">300</td><td class="num">>=1</td><td>信号触发引爆</td></tr>
<tr><td class="num">O-09</td><td><span class="pill pill-output">OUTPUT</span> 门(铁)</td><td class="num">80</td><td class="num">>=1</td><td>信号开启,铁门仅受信号控制</td></tr>
<tr><td class="num">O-10</td><td><span class="pill pill-output">OUTPUT</span> 门(木)</td><td class="num">50</td><td class="num">>=1</td><td>信号开启,也可手动开关</td></tr>
<tr><td class="num">O-11</td><td><span class="pill pill-output">OUTPUT</span> 活板门</td><td class="num">60</td><td class="num">>=1</td><td>信号开启翻板</td></tr>
<tr><td class="num">O-12</td><td><span class="pill pill-output">OUTPUT</span> 灯笼</td><td class="num">55</td><td class="num">-</td><td>常亮光源,不受信号控制</td></tr>
<tr><td class="num">O-13</td><td><span class="pill pill-output">OUTPUT</span> LED</td><td class="num">15</td><td class="num">>=1</td><td>低功耗指示灯,多色可选(红/绿/蓝/黄);信号强度决定亮度,体积仅 0.5 格</td></tr>
<tr><td class="num">O-14</td><td><span class="pill pill-output">OUTPUT</span> 蜂鸣器</td><td class="num">35</td><td class="num">>=1</td><td>信号触发鸣响,频率随信号强度变化;可串联实现旋律播放,替代音符盒的精密方案</td></tr>
<tr><td class="num">O-15</td><td><span class="pill pill-output">OUTPUT</span> 数码管</td><td class="num">90</td><td class="num">0-15</td><td>7 段数码显示管,直接显示输入信号强度数值 0-15;可级联实现多位数字显示</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">7.5 逻辑门类 LOGIC</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>编号</th><th>元件名</th><th>成本(红石币)</th><th>信号强度</th><th>特殊属性</th></tr></thead>
<tbody>
<tr><td class="num">L-01</td><td><span class="pill pill-logic">LOGIC</span> NOT</td><td class="num">150</td><td class="num">15</td><td>输入反相,单输入门</td></tr>
<tr><td class="num">L-02</td><td><span class="pill pill-logic">LOGIC</span> AND</td><td class="num">200</td><td class="num">15</td><td>双输入全高才输出</td></tr>
<tr><td class="num">L-03</td><td><span class="pill pill-logic">LOGIC</span> OR</td><td class="num">200</td><td class="num">15</td><td>任一输入高即输出</td></tr>
<tr><td class="num">L-04</td><td><span class="pill pill-logic">LOGIC</span> NAND</td><td class="num">220</td><td class="num">15</td><td>AND 后取反</td></tr>
<tr><td class="num">L-05</td><td><span class="pill pill-logic">LOGIC</span> NOR</td><td class="num">220</td><td class="num">15</td><td>OR 后取反</td></tr>
<tr><td class="num">L-06</td><td><span class="pill pill-logic">LOGIC</span> XOR</td><td class="num">250</td><td class="num">15</td><td>输入不同才输出</td></tr>
<tr><td class="num">L-07</td><td><span class="pill pill-logic">LOGIC</span> XNOR</td><td class="num">250</td><td class="num">15</td><td>输入相同才输出</td></tr>
<tr><td class="num">L-08</td><td><span class="pill pill-logic">LOGIC</span> 中继器逻辑</td><td class="num">100</td><td class="num">15</td><td>延迟+缓冲,可级联</td></tr>
<tr><td class="num">L-09</td><td><span class="pill pill-logic">LOGIC</span> RS 锁存器</td><td class="num">350</td><td class="num">15</td><td>置位/复位双稳态存储</td></tr>
<tr><td class="num">L-10</td><td><span class="pill pill-logic">LOGIC</span> D 触发器</td><td class="num">400</td><td class="num">15</td><td>边沿触发数据锁存</td></tr>
<tr><td class="num">L-11</td><td><span class="pill pill-logic">LOGIC</span> 计数器</td><td class="num">500</td><td class="num">0-15</td><td>脉冲计数,溢出进位</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">逻辑门组合规则</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>组合</th><th>等效逻辑</th><th>说明</th></tr></thead>
<tbody>
<tr><td>NOT + NOT</td><td>缓冲器</td><td>无逻辑变化,仅作延迟/隔离</td></tr>
<tr><td>AND + NOT</td><td>NAND</td><td>通用门,可组合出任一逻辑</td></tr>
<tr><td>OR + NOT</td><td>NOR</td><td>通用门,可组合出任一逻辑</td></tr>
<tr><td>NAND + NAND</td><td>AND</td><td>双重否定还原与门</td></tr>
<tr><td>NOR + NOR</td><td>OR</td><td>双重否定还原或门</td></tr>
<tr><td>RS 锁存器 x N</td><td>寄存器</td><td>多 Bit 并行存储,构成数据总线</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">7.6 特殊元件类 SPECIAL</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>编号</th><th>元件名</th><th>成本(红石币)</th><th>信号强度</th><th>特殊属性</th></tr></thead>
<tbody>
<tr><td class="num">X-01</td><td><span class="pill pill-special">SPECIAL</span> 命令方块</td><td class="num">1000</td><td class="num">-</td><td>执行预设指令,仅创意/编辑模式</td></tr>
<tr><td class="num">X-02</td><td><span class="pill pill-special">SPECIAL</span> 结构方块</td><td class="num">800</td><td class="num">-</td><td>保存/加载区域结构,蓝图核心</td></tr>
<tr><td class="num">X-03</td><td><span class="pill pill-special">SPECIAL</span> 信号示波器</td><td class="num">300</td><td class="num">0-15</td><td>实时显示信号波形与延迟</td></tr>
<tr><td class="num">X-04</td><td><span class="pill pill-special">SPECIAL</span> 信号延迟器</td><td class="num">150</td><td class="num">15</td><td>可调 1-16 tick 精确延迟</td></tr>
<tr><td class="num">X-05</td><td><span class="pill pill-special">SPECIAL</span> 信号分配器</td><td class="num">120</td><td class="num">15</td><td>一入多出,不衰减分路</td></tr>
<tr><td class="num">X-06</td><td><span class="pill pill-special">SPECIAL</span> 物品过滤器</td><td class="num">250</td><td class="num">-</td><td>按物品类型筛选传输路径</td></tr>
<tr><td class="num">X-07</td><td><span class="pill pill-special">SPECIAL</span> 物品分类器</td><td class="num">400</td><td class="num">-</td><td>多通道自动分拣,自动化核心</td></tr>
<tr><td class="num">X-08</td><td><span class="pill pill-special">SPECIAL</span> ADC 模数转换器</td><td class="num">450</td><td class="num">0-15</td><td>将模拟信号(连续强度)转为数字信号(二进制 4-bit 输出);连接模拟电路与数字逻辑的桥梁</td></tr>
<tr><td class="num">X-09</td><td><span class="pill pill-special">SPECIAL</span> DAC 数模转换器</td><td class="num">450</td><td class="num">0-15</td><td>将 4-bit 数字信号转为模拟信号强度 0-15 输出;用于驱动模拟负载或生成可变亮度</td></tr>
<tr><td class="num">X-10</td><td><span class="pill pill-special">SPECIAL</span> 555 定时器</td><td class="num">350</td><td class="num">15</td><td>支持单稳态(定时器)、双稳态(锁存)、无稳态(方波振荡器)三种工作模式;外接电阻电容可调频率与占空比</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">7.7 模拟元件类 ANALOG</h3>
<p class="body-text">真实模拟电子元件,引入连续信号与线性电路概念,支持更贴近现实电路的设计体验。需在 Lv.15 解锁。</p>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>编号</th><th>元件名</th><th>成本(红石币)</th><th>信号规则</th><th>特殊属性</th></tr></thead>
<tbody>
<tr><td class="num">A-01</td><td><span class="pill pill-special">ANALOG</span> 电阻</td><td class="num">20</td><td class="num">衰减可调</td><td>串联在导线中,可调阻值 1-15,按比例衰减信号强度;用于限流保护和信号分压</td></tr>
<tr><td class="num">A-02</td><td><span class="pill pill-special">ANALOG</span> 电容</td><td class="num">60</td><td class="num">充放电</td><td>存储信号能量,输入断开后延迟释放(容量可调 1-8 tick);用于平滑脉冲、延时开关、去抖</td></tr>
<tr><td class="num">A-03</td><td><span class="pill pill-special">ANALOG</span> 电感</td><td class="num">70</td><td class="num">磁能存储</td><td>阻碍电流突变,信号突变时产生反电动势;与电容组合可构建 LC 振荡、滤波器;延迟特性与电容互补</td></tr>
<tr><td class="num">A-04</td><td><span class="pill pill-special">ANALOG</span> 二极管</td><td class="num">45</td><td class="num">单向导通</td><td>仅允许信号正向通过、反向截止;等效红石中继器但无延迟、无放大;防信号回流</td></tr>
<tr><td class="num">A-05</td><td><span class="pill pill-special">ANALOG</span> 稳压管</td><td class="num">55</td><td class="num">钳位</td><td>反向击穿后将信号钳位在固定强度(可调 1-15);用于稳压保护、电压基准源、限幅电路</td></tr>
<tr><td class="num">A-06</td><td><span class="pill pill-special">ANALOG</span> NPN 三极管</td><td class="num">180</td><td class="num">电流控制</td><td>三端元件(C/B/E);B 有信号时 C->E 导通,B 无信号时截止;可用作信号开关或放大器</td></tr>
<tr><td class="num">A-07</td><td><span class="pill pill-special">ANALOG</span> PNP 三极管</td><td class="num">180</td><td class="num">电流控制</td><td>与 NPN 互补;B 无信号时 C->E 导通,B 有信号时截止;适合高边开关设计,与 NPN 组合可搭建推挽电路</td></tr>
<tr><td class="num">A-08</td><td><span class="pill pill-special">ANALOG</span> 运算放大器</td><td class="num">280</td><td class="num">线性放大</td><td>高增益差分放大器,支持反相/同相/差分/积分/微分五种工作模式;外接电阻设定增益倍数;模拟计算核心</td></tr>
<tr><td class="num">A-09</td><td><span class="pill pill-special">ANALOG</span> 光耦</td><td class="num">160</td><td class="num">光电隔离</td><td>输入端 LED 驱动光敏管输出,实现电气隔离传输;抗干扰、防地线环路;高压与低压电路安全桥接</td></tr>
</tbody>
</table>
</div>
<h4 class="subsection-title" style="font-size:0.95rem;margin-top:24px">运算放大器工作模式</h4>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>模式</th><th>接法</th><th>输出</th><th>典型用途</th></tr></thead>
<tbody>
<tr><td>反相放大</td><td>输入接反相端,同相端接地,Rf/R1 设定增益</td><td>Vout = -Vin * (Rf/R1)</td><td>信号反相放大、加法器</td></tr>
<tr><td>同相放大</td><td>输入接同相端,反相端分压反馈</td><td>Vout = Vin * (1 + Rf/R1)</td><td>信号同相放大、缓冲器</td></tr>
<tr><td>差分放大</td><td>双端输入,差模放大共模抑制</td><td>Vout = (V+ - V-) * Gain</td><td>传感器信号放大、噪声抑制</td></tr>
<tr><td>积分器</td><td>反馈回路用电容替代电阻</td><td>Vout = -1/RC * &int;Vin dt</td><td>波形变换、斜坡发生器</td></tr>
<tr><td>比较器</td><td>开环工作,无反馈</td><td>Vout = +Vcc if V+ > V- else -Vcc</td><td>阈值检测、过零比较</td></tr>
</tbody>
</table>
</div>
<h4 class="subsection-title" style="font-size:0.95rem;margin-top:24px">三极管组合应用</h4>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>组合</th><th>结构</th><th>功能</th></tr></thead>
<tbody>
<tr><td>推挽输出</td><td>NPN + PNP 对管,基极共连</td><td>双向驱动,可拉高也可拉低,替代活塞推拉逻辑</td></tr>
<tr><td>达林顿管</td><td>两级 NPN 级联</td><td>超高增益,极弱信号可驱动大负载</td></tr>
<tr><td>差分对</td><td>双 NPN 共发射极</td><td>比较两路信号差值,运放输入级的基础结构</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">7.8 功率器件类 POWER DEVICE</h3>
<p class="body-text">高功率半导体器件,用于大电流驱动与功率控制场景。需在 Lv.20 解锁。适合自动化生产线和大型机械驱动。</p>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>编号</th><th>元件名</th><th>成本(红石币)</th><th>信号规则</th><th>特殊属性</th></tr></thead>
<tbody>
<tr><td class="num">PD-01</td><td><span class="pill pill-special">POWER_DEVICE</span> 单向可控硅 SCR</td><td class="num">220</td><td class="num">触发导通</td><td>门极脉冲触发后持续导通,直至电流降至零才关断;用于整流功率控制、过压保护;半控型器件</td></tr>
<tr><td class="num">PD-02</td><td><span class="pill pill-special">POWER_DEVICE</span> 双向可控硅 TRIAC</td><td class="num">280</td><td class="num">双向触发</td><td>双方向均可触发导通,等效两个 SCR 反并联;交流功率控制核心元件;调光、调速、温控</td></tr>
<tr><td class="num">PD-03</td><td><span class="pill pill-special">POWER_DEVICE</span> IGBT</td><td class="num">420</td><td class="num">电压驱动</td><td>结合 MOS 管高输入阻抗与三极管大电流能力;高压大电流开关核心;逆变器、电机驱动首选</td></tr>
<tr><td class="num">PD-04</td><td><span class="pill pill-special">POWER_DEVICE</span> MOS 管</td><td class="num">200</td><td class="num">电压控制</td><td>电压驱动型场效应管,导通电阻极低;开关速度快,高频功率应用核心;可并联扩流</td></tr>
<tr><td class="num">PD-05</td><td><span class="pill pill-special">POWER_DEVICE</span> 达林顿管</td><td class="num">300</td><td class="num">高增益驱动</td><td>两级三极管复合封装,电流增益达 1000+;微弱信号即可驱动大功率负载;步进电机/继电器阵列驱动</td></tr>
<tr><td class="num">PD-06</td><td><span class="pill pill-special">POWER_DEVICE</span> 继电器模组</td><td class="num">250</td><td class="num">多路隔离</td><td>4 路独立继电器集成模组,每路常开+常闭双触点;可同时控制 4 路独立高功率负载;工业自动化标配</td></tr>
</tbody>
</table>
</div>
<h4 class="subsection-title" style="font-size:0.95rem;margin-top:24px">555 定时器工作模式(X-10</h4>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>模式</th><th>接法</th><th>输出</th><th>典型用途</th></tr></thead>
<tbody>
<tr><td>单稳态</td><td>触发端输入脉冲,外接 R+C 定时</td><td>固定宽度高电平脉冲</td><td>延时开关、脉冲展宽、防抖</td></tr>
<tr><td>双稳态</td><td>触发端置位,复位端清零</td><td>锁存当前状态</td><td>RS 锁存器替代、记忆电路</td></tr>
<tr><td>无稳态</td><td>两电阻 + 电容构成振荡回路</td><td>连续方波信号</td><td>时钟发生器、PWM 调制、闪烁灯</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 8 ===== -->
<section class="doc-section" id="game-modes">
<p class="section-eyebrow">08 / GAME MODES</p>
<h2 class="section-title">游戏模式规则</h2>
<p class="section-desc">四大游戏模式的规则、限制与奖励机制定义。</p>
<h3 class="subsection-title">8.1 自由搭建模式 Creative</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>规则项</th><th>设定</th><th>说明</th></tr></thead>
<tbody>
<tr><td>资源</td><td>无限</td><td>所有元件免费无限使用</td></tr>
<tr><td>成本</td><td>不计</td><td>不消耗红石币</td></tr>
<tr><td>画布尺寸</td><td class="num">256x256</td><td>最大单电路画布</td></tr>
<tr><td>存档槽位</td><td class="num">20</td><td>本地+云端各 20 个</td></tr>
<tr><td>仿真</td><td>实时</td><td>放置即仿真,可暂停单步</td></tr>
<tr><td>分享</td><td>允许</td><td>可发布为蓝图供他人下载</td></tr>
<tr><td>目标</td><td></td><td>纯创造,无强制目标</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">8.2 解谜关卡模式 Puzzle</h3>
<p class="body-text">解谜模式提供 6 种关卡类型,通过 3 星评级衡量通关质量,每章节难度递增,共 6 章 240 关。</p>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>关卡类型</th><th>玩法说明</th><th>示例目标</th></tr></thead>
<tbody>
<tr><td>信号路由</td><td>将信号从起点传至终点</td><td>点亮指定红石灯</td></tr>
<tr><td>逻辑运算</td><td>搭建满足真值表的逻辑电路</td><td>实现 XOR 门</td></tr>
<tr><td>时序控制</td><td>按顺序触发多个输出</td><td>三盏灯依次点亮</td></tr>
<tr><td>计数挑战</td><td>统计脉冲数并输出</td><td>计满 10 次触发</td></tr>
<tr><td>资源优化</td><td>在元件数限制内通关</td><td>不超过 15 个元件</td></tr>
<tr><td>延迟竞速</td><td>在延迟上限内完成</td><td>总延迟不超过 20 tick</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">三星评级系统</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>星级</th><th>条件</th><th>奖励</th></tr></thead>
<tbody>
<tr><td>一星</td><td>完成通关目标</td><td class="num">基础红石币奖励</td></tr>
<tr><td>二星</td><td>成本不超过 star_cost 上限</td><td class="num">1.5x 红石币 + 经验</td></tr>
<tr><td>三星</td><td>成本达标且延迟不超过 star_delay</td><td class="num">2x 红石币 + 成就进度</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">限制规则</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>限制类型</th><th>说明</th></tr></thead>
<tbody>
<tr><td>元件禁用</td><td>部分关卡禁用高级元件(如命令方块、结构方块)</td></tr>
<tr><td>元件上限</td><td>限制可放置元件总数</td></tr>
<tr><td>画布缩放</td><td>缩小可用画布区域增加难度</td></tr>
<tr><td>预设锁定</td><td>部分元件位置固定不可移动</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">章节分布 (共 240 关)</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>章节</th><th>主题</th><th>关卡数</th><th>难度</th></tr></thead>
<tbody>
<tr><td>第 1 章</td><td>基础电路入门</td><td class="num">30</td><td>简单</td></tr>
<tr><td>第 2 章</td><td>逻辑门与运算</td><td class="num">40</td><td>普通</td></tr>
<tr><td>第 3 章</td><td>时序与锁存</td><td class="num">50</td><td>中等</td></tr>
<tr><td>第 4 章</td><td>复杂自动化</td><td class="num">60</td><td>困难</td></tr>
<tr><td>第 5 章</td><td>高级电路设计</td><td class="num">40</td><td>专家</td></tr>
<tr><td>第 6 章</td><td>极限挑战</td><td class="num">20</td><td>大师</td></tr>
<tr><td>合计</td><td>-</td><td class="num">240</td><td>-</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">8.3 自动化生产模式 Automation</h3>
<p class="body-text">玩家搭建生产线,将原料加工为成品出售赚取红石币。生产链从采集到精炼逐级加工。</p>
<div class="chain-flow">
<span class="chain-node">矿石采集</span>
<span class="chain-arrow">-&gt;</span>
<span class="chain-node">粉碎机</span>
<span class="chain-arrow">-&gt;</span>
<span class="chain-node">精炼炉</span>
<span class="chain-arrow">-&gt;</span>
<span class="chain-node">合成台</span>
<span class="chain-arrow">-&gt;</span>
<span class="chain-node">成品仓库</span>
<span class="chain-arrow">-&gt;</span>
<span class="chain-node">出售获利</span>
</div>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>资源类型</th><th>采购价</th><th>用途</th></tr></thead>
<tbody>
<tr><td>原矿石</td><td class="num">5</td><td>基础原料,粉碎后得矿粉</td></tr>
<tr><td>矿粉</td><td class="num">12</td><td>精炼原料,可熔炼为锭</td></tr>
<tr><td>金属锭</td><td class="num">30</td><td>合成元件壳体的核心材料</td></tr>
<tr><td>红石粉原料</td><td class="num">8</td><td>提纯为可用红石粉</td></tr>
<tr><td>红石结晶</td><td class="num">80</td><td>高级逻辑门核心材料</td></tr>
<tr><td>硅片</td><td class="num">45</td><td>集成电路板基材</td></tr>
<tr><td>电路板</td><td class="num">120</td><td>成品元件必备组件</td></tr>
<tr><td>能量核</td><td class="num">200</td><td>特殊元件能源供给</td></tr>
</tbody>
</table>
</div>
<div class="formula-box">
效率公式:E = (成品数量 / 总耗时) x 100<br>
成本回收:R = 成品售价 - (原料成本 + 元件磨损 + 电力消耗)<br>
净利润:P = R x E x 运行时长
</div>
<h3 class="subsection-title">8.4 多人对战/协作模式 Multiplayer</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>对战模式</th><th>人数</th><th>规则</th></tr></thead>
<tbody>
<tr><td>电路竞速</td><td class="num">2-4</td><td>最先完成指定电路搭建者获胜</td></tr>
<tr><td>信号攻防</td><td class="num">2</td><td>一方搭建防御电路,另一方破解</td></tr>
<tr><td>资源争夺</td><td class="num">2-4</td><td>争夺有限元件资源搭建最优电路</td></tr>
<tr><td>蓝图复刻</td><td class="num">2-4</td><td>看图复原电路,最快最准者胜</td></tr>
</tbody>
</table>
</div>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>协作模式</th><th>人数</th><th>规则</th></tr></thead>
<tbody>
<tr><td>联合建造</td><td class="num">2-4</td><td>共同完成大型电路工程</td></tr>
<tr><td>分工流水线</td><td class="num">2-4</td><td>各负责生产链一环,协同产出</td></tr>
<tr><td>解谜协作</td><td class="num">2-4</td><td>合力攻克高难度解谜关卡</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">匹配与赛季规则</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>规则项</th><th>设定</th><th>说明</th></tr></thead>
<tbody>
<tr><td>匹配机制</td><td>MMR 段位</td><td>基于隐藏分匹配相近水平玩家</td></tr>
<tr><td>匹配超时</td><td class="num">60s</td><td>超时后放宽段位范围</td></tr>
<tr><td>赛季周期</td><td class="num">4 周</td><td>每月一个赛季,结算发放奖励</td></tr>
<tr><td>段位</td><td class="num">7 级</td><td>青铜至宗师,每级 3 小段</td></tr>
<tr><td>赛季奖励</td><td>蓝图+金币</td><td>按最终段位发放限定蓝图与金币</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 9 ===== -->
<section class="doc-section" id="economy">
<p class="section-eyebrow">09 / ECONOMY</p>
<h2 class="section-title">货币与经济系统</h2>
<p class="section-desc">双货币体系设计,红石币为软货币贯穿玩法循环,金币为硬货币用于增值消费。</p>
<h3 class="subsection-title">9.1 货币类型</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>属性</th><th>红石币 (软货币)</th><th>金币 (硬货币)</th></tr></thead>
<tbody>
<tr><td>获取方式</td><td>解谜通关、自动化生产、每日任务</td><td>人民币充值、赛季奖励、成就</td></tr>
<tr><td>主要用途</td><td>购买元件、解锁关卡、购买蓝图</td><td>购买稀有皮肤、加速、高级蓝图</td></tr>
<tr><td>可交易性</td><td>不可直接交易,仅通过蓝图间接流通</td><td>不可交易</td></tr>
<tr><td>上限</td><td class="num">9,999,999</td><td class="num">99,999</td></tr>
<tr><td>汇率参考</td><td class="num">1000 红石币 ≈ ¥1</td><td class="num">10 金币 = ¥1</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">9.2 产出与消耗平衡</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>产出渠道</th><th>日预估产出</th><th>说明</th></tr></thead>
<tbody>
<tr><td>解谜通关</td><td class="num">800-1500</td><td>首次通关奖励高,重复递减</td></tr>
<tr><td>自动化生产</td><td class="num">500-2000</td><td>取决于生产线效率与在线时长</td></tr>
<tr><td>每日任务</td><td class="num">300</td><td>固定日任务奖励</td></tr>
<tr><td>蓝图销售分成</td><td class="num">0-5000</td><td>他人购买作者蓝图,作者获 70%</td></tr>
<tr><td>多人对战奖励</td><td class="num">100-600</td><td>按胜负与段位</td></tr>
</tbody>
</table>
</div>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>消耗渠道</th><th>单次消耗</th><th>说明</th></tr></thead>
<tbody>
<tr><td>购买元件(单价)</td><td class="num">5-1000</td><td>按元件类型差异定价</td></tr>
<tr><td>解锁关卡章节</td><td class="num">2000-8000</td><td>逐章递增</td></tr>
<tr><td>购买蓝图</td><td class="num">0-3000</td><td>作者定价,平台抽成 30%</td></tr>
<tr><td>商店道具</td><td class="num">100-500</td><td>消耗品与装饰品</td></tr>
<tr><td>自动化原料采购</td><td class="num">5-200</td><td>生产链原料采购成本</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">9.3 充值档位</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>档位</th><th>价格</th><th>金币</th><th>额外赠送</th></tr></thead>
<tbody>
<tr><td>新手包</td><td class="num">¥6</td><td class="num">60</td><td>首充双倍 + 新手元件包</td></tr>
<tr><td>标准包</td><td class="num">¥30</td><td class="num">300</td><td>30 金币 + 限定皮肤</td></tr>
<tr><td>超值包</td><td class="num">¥68</td><td class="num">680</td><td>120 金币 + 赛季通行证</td></tr>
<tr><td>豪华包</td><td class="num">¥168</td><td class="num">1680</td><td>400 金币 + 专属称号</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 10 ===== -->
<section class="doc-section" id="user-system">
<p class="section-eyebrow">10 / USER SYSTEM</p>
<h2 class="section-title">用户系统</h2>
<p class="section-desc">注册登录、账号安全、新手引导、等级解锁与成就系统。</p>
<h3 class="subsection-title">10.1 注册登录</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>规则项</th><th>要求</th><th>说明</th></tr></thead>
<tbody>
<tr><td>用户名</td><td>3-32 字符</td><td>字母数字下划线,唯一</td></tr>
<tr><td>邮箱</td><td>有效邮箱</td><td>用于找回密码与通知</td></tr>
<tr><td>密码</td><td>8-64 字符</td><td>需含大小写字母与数字,bcrypt 加密</td></tr>
<tr><td>第三方登录</td><td>Google / GitHub / Discord</td><td>支持 OAuth2 快捷登录</td></tr>
<tr><td>验证方式</td><td>邮箱验证码</td><td>注册与找回密码需验证</td></tr>
</tbody>
</table>
</div>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>安全措施</th><th>说明</th></tr></thead>
<tbody>
<tr><td>密码加密</td><td>bcrypt 哈希存储,不存明文</td></tr>
<tr><td>JWT Token</td><td>双 Token 机制,Access 短期 + Refresh 长期</td></tr>
<tr><td>异地登录检测</td><td>新设备登录需邮箱二次验证</td></tr>
<tr><td>登录频率限制</td><td>5 次失败锁定 15 分钟</td></tr>
<tr><td>数据传输加密</td><td>全站 HTTPS / WSS</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">新手引导流程</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>步骤</th><th>内容</th><th>奖励</th></tr></thead>
<tbody>
<tr><td class="num">1</td><td>创建账号与角色</td><td class="num">100 红石币</td></tr>
<tr><td class="num">2</td><td>基础元件放置教学</td><td class="num">150 红石币</td></tr>
<tr><td class="num">3</td><td>完成首个教程关卡</td><td class="num">200 红石币 + 经验</td></tr>
<tr><td class="num">4</td><td>商店购买教学</td><td class="num">拉杆元件 x5</td></tr>
<tr><td class="num">5</td><td>分享首个电路</td><td class="num">300 红石币 + 成就</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">10.2 等级与解锁</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>等级段</th><th>等级范围</th><th>经验要求</th><th>解锁内容</th></tr></thead>
<tbody>
<tr><td>新手</td><td class="num">1-10</td><td class="num">0-5,000</td><td>基础元件、第 1-2 章、自由搭建</td></tr>
<tr><td>进阶</td><td class="num">11-25</td><td class="num">5,000-30,000</td><td>逻辑门元件、第 3-4 章、自动化</td></tr>
<tr><td>高级</td><td class="num">26-50</td><td class="num">30,000-120,000</td><td>特殊元件、第 5-6 章、多人模式</td></tr>
<tr><td>大师</td><td class="num">51+</td><td class="num">120,000+</td><td>全部解锁、蓝图上传、赛季排位</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">10.3 成就系统</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>成就</th><th>解锁条件</th><th>奖励</th></tr></thead>
<tbody>
<tr><td>初出茅庐</td><td>完成新手引导</td><td class="num">300 红石币</td></tr>
<tr><td>电路学徒</td><td>通关 10 个解谜关卡</td><td class="num">500 红石币 + 经验</td></tr>
<tr><td>逻辑大师</td><td>用逻辑门完成 50 个关卡</td><td class="num">1000 红石币 + 称号</td></tr>
<tr><td>满星达人</td><td>累计获得 100 颗星</td><td class="num">800 金币 + 限定皮肤</td></tr>
<tr><td>蓝图创作者</td><td>上传首个蓝图</td><td class="num">200 红石币</td></tr>
<tr><td>人气作者</td><td>蓝图累计下载 1000 次</td><td class="num">2000 红石币 + 称号</td></tr>
<tr><td>赛季冠军</td><td>达到宗师段位</td><td class="num">5000 金币 + 限定蓝图</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 11 ===== -->
<section class="doc-section" id="milestones">
<p class="section-eyebrow">11 / MILESTONES</p>
<h2 class="section-title">开发里程碑</h2>
<p class="section-desc">从原型到运营的五阶段开发计划与交付物定义。</p>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>阶段</th><th>时间</th><th>交付物</th><th>团队规模</th></tr></thead>
<tbody>
<tr><td>Phase 1 原型期</td><td>M1-M2</td><td>核心仿真引擎、基础编辑器、5 种元件原型</td><td class="num">4 人</td></tr>
<tr><td>Phase 2 Alpha</td><td>M3-M5</td><td>全部 4 模式、经济系统、用户认证、前 3 章关卡</td><td class="num">8 人</td></tr>
<tr><td>Phase 3 Beta</td><td>M6-M8</td><td>多人联机、蓝图工坊、商店、全 240 关、UI 打磨</td><td class="num">12 人</td></tr>
<tr><td>Phase 4 发布</td><td>M9</td><td>官网上线、监控告警、热修复管线、客服系统</td><td class="num">12 人</td></tr>
<tr><td>Phase 5 运营</td><td>M10+</td><td>赛季内容、限时活动、平衡性补丁、数据分析</td><td class="num">10 人</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 12 ===== -->
<section class="doc-section" id="deployment">
<p class="section-eyebrow">12 / DEPLOYMENT</p>
<h2 class="section-title">部署与运维</h2>
<p class="section-desc">服务端容器化部署、客户端分发、CI/CD 流水线与监控体系。</p>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>领域</th><th>方案</th><th>说明</th></tr></thead>
<tbody>
<tr><td>服务端部署</td><td>Docker + Kubernetes</td><td>容器化微服务,HPA 自动伸缩,滚动更新</td></tr>
<tr><td>客户端分发</td><td>官网安装包 + 自动更新服务</td><td>官网提供 Windows/macOS 安装包,内置增量更新客户端</td></tr>
<tr><td>CI/CD</td><td>GitHub Actions</td><td>推送触发自动构建、单元测试、集成测试、部署</td></tr>
<tr><td>服务端监控</td><td>Prometheus + Grafana</td><td>CPU/内存/QPS/延迟指标,告警规则推送到钉钉</td></tr>
<tr><td>错误追踪</td><td>Sentry</td><td>客户端崩溃报告与服务端异常堆栈统一收集</td></tr>
<tr><td>CDN</td><td>蓝图文件 + 更新补丁</td><td>静态资源与增量更新包走 CDN 加速分发</td></tr>
<tr><td>日志收集</td><td>ELK Stack</td><td>Elasticsearch + Logstash + Kibana 日志检索</td></tr>
<tr><td>备份策略</td><td>每日全量 + 实时 WAL</td><td>PostgreSQL 每日全量备份,WAL 实时归档</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 13 ===== -->
<section class="doc-section" id="risks">
<p class="section-eyebrow">13 / RISKS</p>
<h2 class="section-title">风险评估</h2>
<p class="section-desc">技术、市场、运营与安全维度的风险识别与缓解措施。</p>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>风险项</th><th>类别</th><th>概率</th><th>影响</th><th>缓解措施</th></tr></thead>
<tbody>
<tr><td>大规模电路仿真性能瓶颈</td><td>技术</td><td></td><td></td><td>ECS 优化、分块加载、LOD 降级、多线程</td></tr>
<tr><td>红石逻辑还原度不足</td><td>技术</td><td></td><td></td><td>对照 MC 原版行为单元测试,社区反馈迭代</td></tr>
<tr><td>多人同步延迟与一致性</td><td>技术</td><td></td><td></td><td>客户端预测+服务端权威,Delta 压缩同步</td></tr>
<tr><td>同类竞品挤压市场</td><td>市场</td><td></td><td></td><td>差异化双货币+UGC 生态,社区运营前置</td></tr>
<tr><td>玩家留存不及预期</td><td>市场</td><td></td><td></td><td>数据驱动关卡调优,限时活动促活</td></tr>
<tr><td>UGC 内容审核滞后</td><td>运营</td><td></td><td></td><td>机审+人审双通道,举报快速响应机制</td></tr>
<tr><td>服务器成本超预算</td><td>运营</td><td></td><td></td><td>HPA 弹性伸缩,闲时缩容,预留缓存层</td></tr>
<tr><td>经济系统通胀失控</td><td>运营</td><td></td><td></td><td>产出消耗动态监控,定期平衡性补丁</td></tr>
<tr><td>账号盗号与黑产刷币</td><td>安全</td><td></td><td></td><td>异地登录验证、行为风控、交易限额</td></tr>
<tr><td>客户端被逆向破解</td><td>安全</td><td></td><td></td><td>代码混淆、关键逻辑服务端校验、反调试</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 15 ===== -->
<section class="doc-section" id="sprint-plan">
<p class="section-eyebrow">15 / SPRINT PLAN</p>
<h2 class="section-title">Sprint 分解与排期</h2>
<p class="section-desc">以 2 周为一个 Sprint,从 M1 到 M9 共 18 个 Sprint,每个 Sprint 明确交付物和验收标准。</p>
<h3 class="subsection-title">Phase 1 原型期 (M1-M2, Sprint 1-4)</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>Sprint</th><th>周期</th><th>交付物</th><th>验收标准</th></tr></thead>
<tbody>
<tr><td>S1</td><td>W1-2</td><td>项目骨架搭建:Unity 工程初始化、Go 项目骨架、CI 基础流水线、Git 仓库与代码规范</td><td>Unity 可编译运行空场景;Go 服务可启动并返回 health check;CI 可自动构建</td></tr>
<tr><td>S2</td><td>W3-4</td><td>网格画布渲染器 + 元件放置系统:16x16 网格、元件拖放放置、基础 8 种元件数据结构</td><td>可在画布上放置/删除/移动元件;网格坐标正确;元件数据 JSON 序列化通过</td></tr>
<tr><td>S3</td><td>W5-6</td><td>信号仿真引擎 v1:红石粉信号传播、衰减计算、电源->导线->输出基本链路</td><td>红石火把->红石粉->红石灯 链路可点亮;信号强度衰减正确;1 tick = 0.1s 时序正确</td></tr>
<tr><td>S4</td><td>W7-8</td><td>仿真引擎 v2 + 工具栏 UI:中继器/比较器/逻辑门仿真、保存/加载/运行/暂停按钮、成本计算</td><td>逻辑门输出正确(真值表验证);电路可保存为 JSON 并重新加载;成本实时计算</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">Phase 2 Alpha (M3-M5, Sprint 5-10)</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>Sprint</th><th>周期</th><th>交付物</th><th>验收标准</th></tr></thead>
<tbody>
<tr><td>S5</td><td>W9-10</td><td>用户认证系统:注册/登录 API、JWT Token、SQLite 本地存档、PostgreSQL 用户表</td><td>注册->登录->获取Token->访问受保护接口 全链路通过;密码 bcrypt 加密;Token 过期自动刷新</td></tr>
<tr><td>S6</td><td>W11-12</td><td>解谜关卡系统 v1:关卡数据结构、关卡加载器、前 30 关(第一章)、三星评级算法</td><td>30 关可游玩;输入/输出验证正确;三星评级按成本和延迟计算</td></tr>
<tr><td>S7</td><td>W13-14</td><td>自由搭建模式 + 画布扩展至 128x128 + 全部 80 种元件数据填充</td><td>128x128 画布流畅运行(>30fps);80 种元件均可放置和仿真;无限资源模式</td></tr>
<tr><td>S8</td><td>W15-16</td><td>货币系统 + 商店 UI:红石币/金币数据库表、交易流水、商店 4 标签页、购买逻辑</td><td>解谜通关奖励红石币正确入账;商店购买扣费正确;交易流水可追溯</td></tr>
<tr><td>S9</td><td>W17-18</td><td>自动化生产模式 v1:资源采集->传输->加工->出售 链路、效率计算、8 种资源</td><td>自动农场可运行产出资源;资源出售获得红石币;效率系数 0.5x-2.0x 正确</td></tr>
<tr><td>S10</td><td>W19-20</td><td>解谜第二章 40 关 + 第三章前 25 关 + 成就系统 v1 + 等级系统</td><td>累计 95 关可游玩;等级升级正确解锁元件;7 个成就可触发</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">Phase 3 Beta (M6-M8, Sprint 11-16)</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>Sprint</th><th>周期</th><th>交付物</th><th>验收标准</th></tr></thead>
<tbody>
<tr><td>S11</td><td>W21-22</td><td>多人联机核心:WebSocket 网关、客户端预测+服务端校验、实时画布同步</td><td>2 人同时编辑同一画布延迟 <200ms冲突解决正确断线重连恢复</td></tr>
<tr><td>S12</td><td>W23-24</td><td>多人对战模式:电路竞速、成本竞速、匹配系统、积分排行</td><td>4 人匹配对局可完整进行;排行榜实时更新;积分增减正确</td></tr>
<tr><td>S13</td><td>W25-26</td><td>蓝图工坊:蓝图上传/下载/评分/搜索、MinIO 文件存储、蓝图市场 UI</td><td>蓝图可上传并下载复现;评分系统正常;搜索可按名称/作者/标签过滤</td></tr>
<tr><td>S14</td><td>W27-28</td><td>解谜第三至第五章共 150 关 + 多人协作模式 + 信号攻防模式</td><td>累计 245 关可游玩;协作模式 4 人共建正常;信号攻防 2v2 可进行</td></tr>
<tr><td>S15</td><td>W29-30</td><td>全 UI 打磨:动效系统、暗色/亮色主题、响应式适配、无障碍优化</td><td>Lighthouse 评分 >85;动效 60fpsprefers-reduced-motion 生效;键盘可操作</td></tr>
<tr><td>S16</td><td>W31-32</td><td>第五章剩余 + 第六章 20 关大师关 + 性能优化 + Bug 修复 + 封闭 Beta 测试</td><td>240 关全部可游玩;512x512 画布 >30fpsP0 Bug 清零;封闭 Beta 500 人测试</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">Phase 4 发布 (M9, Sprint 17-18)</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>Sprint</th><th>周期</th><th>交付物</th><th>验收标准</th></tr></thead>
<tbody>
<tr><td>S17</td><td>W33-34</td><td>开放 Beta + 压力测试 + 热修复管线 + 客服系统 + 数据分析埋点</td><td>5000 并发用户稳定;P0 Bug 24h 内修复;数据分析看板可查看 DAU/留存</td></tr>
<tr><td>S18</td><td>W35-36</td><td>正式发布 + 监控告警 + 运营活动配置系统 + 赛季系统上线</td><td>正式环境运行稳定;告警 <5min 响应第一赛季可正常运行首周留存 >35%</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 16 ===== -->
<section class="doc-section" id="team">
<p class="section-eyebrow">16 / TEAM</p>
<h2 class="section-title">团队组织与职责</h2>
<p class="section-desc">按阶段递进的团队配置,明确角色、职责与协作流程。</p>
<h3 class="subsection-title">团队配置阶段表</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>阶段</th><th>人数</th><th>角色构成</th><th>关键职责</th></tr></thead>
<tbody>
<tr><td>Phase 1</td><td class="num">4</td><td>技术主策 1 + 客户端 1 + 服务端 1 + 美术 1</td><td>核心引擎原型、美术风格验证</td></tr>
<tr><td>Phase 2</td><td class="num">8</td><td>+ 客户端 2 + 服务端 1 + 策划 1 + QA 1</td><td>全模式开发、经济系统、认证系统</td></tr>
<tr><td>Phase 3</td><td class="num">12</td><td>+ 客户端 1 + 服务端 1 + 美术 1 + QA 1</td><td>多人联机、蓝图工坊、全关卡、UI 打磨</td></tr>
<tr><td>Phase 4-5</td><td class="num">10-12</td><td>稳定团队 + 运营 1 + 数据分析 1</td><td>发布运维、赛季内容、平衡性调优</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">角色职责矩阵</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>角色</th><th>核心职责</th><th>技术栈要求</th><th>产出物</th></tr></thead>
<tbody>
<tr><td>技术主策 / Tech Lead</td><td>架构决策、技术选型、代码审查、跨端协调</td><td>Unity C# + Go + 系统设计</td><td>架构文档、技术方案、Code Review 记录</td></tr>
<tr><td>客户端工程师 x4</td><td>Unity 渲染、UI Toolkit、仿真引擎客户端、网络层</td><td>Unity 2024 LTS, C#, UI Toolkit</td><td>客户端模块代码、性能报告</td></tr>
<tr><td>服务端工程师 x2</td><td>Go 微服务、数据库设计、WebSocket 网关、反作弊</td><td>Go, Gin, PostgreSQL, Redis</td><td>API 服务代码、数据库 Migration、接口文档</td></tr>
<tr><td>游戏策划 x1</td><td>关卡设计、数值平衡、经济系统调优、赛季规划</td><td>Excel/Python 数据分析、关卡编辑器</td><td>关卡数据 JSON、数值表、策划案</td></tr>
<tr><td>UI/UX 美术 x2</td><td>UI 设计、像素元件图标、特效、主题</td><td>Figma, Aseprite, Unity Shader</td><td>UI 切图、图标素材、特效预设</td></tr>
<tr><td>QA 测试 x2</td><td>功能测试、自动化测试、性能测试、Bug 管理</td><td>Python, Selenium, Unity Test Framework</td><td>测试用例、Bug 报告、自动化脚本</td></tr>
<tr><td>运营 / 数据 x1</td><td>活动配置、数据分析、社区运营、赛季管理</td><td>SQL, Tableau, 社区工具</td><td>运营报告、活动配置、数据看板</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">协作流程</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>流程</th><th>工具</th><th>规则</th></tr></thead>
<tbody>
<tr><td>代码管理</td><td>Git + GitHub</td><td>main 分支保护;feature/* 分支开发;PR 至少 1 人 Review 后合并;Sprint 结束打 tag</td></tr>
<tr><td>任务管理</td><td>GitHub Projects / Jira</td><td>Sprint Backlog 拆分至 2 人日以内;每日 Standup 15 分钟;Sprint Review + Retro</td></tr>
<tr><td>文档管理</td><td>Notion / Confluence</td><td>API 文档 Swagger 自动生成;设计文档 PR 附带;会议纪要 24h 内归档</td></tr>
<tr><td>CI/CD</td><td>GitHub Actions</td><td>PR 触发自动构建+测试;main 分支自动部署 StagingTag 发布 Production</td></tr>
<tr><td>沟通</td><td>飞书 / Discord</td><td>技术讨论频道;紧急问题电话优先;每周技术分享 1 小时</td></tr>
<tr><td>Bug 追踪</td><td>GitHub Issues</td><td>P0 当日修复;P1 当 Sprint 修复;P2 排入 BacklogBug 复现步骤必填</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 17 ===== -->
<section class="doc-section" id="client-modules">
<p class="section-eyebrow">17 / CLIENT MODULES</p>
<h2 class="section-title">客户端模块详设</h2>
<p class="section-desc">Unity 客户端的模块拆分、核心脚本职责与数据流设计。</p>
<h3 class="subsection-title">17.1 模块总览</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>模块</th><th>命名空间</th><th>职责</th><th>核心脚本</th></tr></thead>
<tbody>
<tr><td>GridRenderer</td><td>RedCircuit.Grid</td><td>网格画布渲染、视口裁剪、LOD</td><td>GridCanvas.cs, ChunkManager.cs, TileRenderer.cs</td></tr>
<tr><td>SimulationEngine</td><td>RedCircuit.Simulation</td><td>信号传播、元件仿真、tick 循环</td><td>SimulationLoop.cs, SignalPropagator.cs, ComponentBehavior.cs</td></tr>
<tr><td>ComponentSystem</td><td>RedCircuit.Components</td><td>80 种元件数据定义、放置/删除/旋转</td><td>ComponentRegistry.cs, PlacementController.cs, ComponentData.cs</td></tr>
<tr><td>UISystem</td><td>RedCircuit.UI</td><td>UI Toolkit 界面、工具栏、面板、弹窗</td><td>EditorWindow.cs, ToolbarController.cs, PalettePanel.cs, InspectorPanel.cs</td></tr>
<tr><td>NetworkClient</td><td>RedCircuit.Net</td><td>REST 请求、WebSocket 连接、delta 同步</td><td>ApiClient.cs, WsClient.cs, SyncManager.cs</td></tr>
<tr><td>SaveSystem</td><td>RedCircuit.Save</td><td>本地 SQLite 存档、云端同步、蓝图导出</td><td>SaveManager.cs, LocalDatabase.cs, CloudSync.cs</td></tr>
<tr><td>AudioSystem</td><td>RedCircuit.Audio</td><td>音符盒/蜂鸣器音效、UI 音效、BGM</td><td>AudioManager.cs, NotePlayer.cs</td></tr>
<tr><td>AuthSystem</td><td>RedCircuit.Auth</td><td>登录注册、Token 管理、第三方 OAuth</td><td>AuthManager.cs, TokenStore.cs, OAuthClient.cs</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">17.2 仿真引擎核心数据结构</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>类名</th><th>字段</th><th>说明</th></tr></thead>
<tbody>
<tr><td>GridCell</td><td>int x, y; Component component; int signalStrength; List&lt;GridCell&gt; neighbors</td><td>网格单元,记录坐标、元件实例、当前信号强度、四邻连接</td></tr>
<tr><td>Component</td><td>ComponentType type; int rotation; Dictionary&lt;string, int&gt; properties; bool isPowered</td><td>元件实例,类型、朝向、可调属性(阻值/延迟/模式等)、通电状态</td></tr>
<tr><td>SignalUpdate</td><td>GridCell target; int newStrength; int tick; SignalSource source</td><td>信号更新事件,BFS 队列元素,记录目标格、新强度、tick 序号、来源</td></tr>
<tr><td>CircuitGraph</td><td>Dictionary&lt;Vector2Int, GridCell&gt; cells; Queue&lt;SignalUpdate&gt; updateQueue; HashSet&lt;Vector2Int&gt; dirtyCells</td><td>电路图数据,全格字典 + 信号更新队列 + 脏标记集合</td></tr>
<tr><td>SimulationConfig</td><td>float tickDuration; int maxGridSize; bool enableShortCircuitDetection; bool stepMode</td><td>仿真配置,tick 时长、最大画布、短路检测开关、步进模式</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">17.3 渲染性能策略</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>策略</th><th>实现方式</th><th>目标</th></tr></thead>
<tbody>
<tr><td>分块加载</td><td>画布按 16x16 分 Chunk,视口内 Chunk 才实例化 GameObject</td><td>512x512 画布内存占用 <512MB</td></tr>
<tr><td>对象池</td><td>元件 GameObject 预生成 500 个池化,放置时取用而非 Instantiate</td><td>消除 GC Spike,放置延迟 <16ms</td></tr>
<tr><td>GPU Instancing</td><td>同类型元件使用 GPU Instancing 批量渲染</td><td>1000+ 元件同帧 Draw Call <50</td></tr>
<tr><td>信号轨迹 Shader</td><td>红石信号轨迹用自定义 Shader 绘制,非逐格 GameObject</td><td>信号动画 60fps,不随电路规模增长</td></tr>
<tr><td>LOD 降级</td><td>缩放 <50% 时元件图标降级为纯色方块不渲染细节</td><td>全景浏览 512x512 保持 >30fps</td></tr>
<tr><td>仿真分帧</td><td>大电路仿真 BFS 分帧执行,每帧最多处理 2000 格更新</td><td>避免大电路导致主线程卡顿</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">17.4 电路数据 JSON 格式</h3>
<pre class="code-block">{
"version": "1.0",
"canvasSize": { "width": 128, "height": 128 },
"components": [
{
"id": "comp_001",
"type": "REDSTONE_TORCH",
"x": 10, "y": 20,
"rotation": 0,
"properties": {}
},
{
"id": "comp_002",
"type": "REDSTONE_DUST",
"x": 11, "y": 20,
"rotation": 0,
"properties": {}
},
{
"id": "comp_003",
"type": "AND_GATE",
"x": 15, "y": 20,
"rotation": 0,
"properties": { "inputCount": 2 }
},
{
"id": "comp_004",
"type": "RESISTOR",
"x": 12, "y": 20,
"rotation": 0,
"properties": { "resistance": 5 }
}
],
"wires": [
{ "from": "comp_001", "to": "comp_002" },
{ "from": "comp_002", "to": "comp_004" },
{ "from": "comp_004", "to": "comp_003", "inputIndex": 0 }
],
"metadata": {
"author": "CircuitMaster",
"createdAt": "2026-08-07T12:00:00Z",
"cost": 280,
"componentCount": 4,
"wireCount": 3
}
}</pre>
</section>
<!-- ===== Section 18 ===== -->
<section class="doc-section" id="server-services">
<p class="section-eyebrow">18 / SERVER SERVICES</p>
<h2 class="section-title">服务端微服务详设</h2>
<p class="section-desc">5 个微服务的职责边界、核心接口、数据归属与通信协议。</p>
<h3 class="subsection-title">18.1 微服务总览</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>服务</th><th>语言/框架</th><th>端口</th><th>数据库</th><th>核心职责</th></tr></thead>
<tbody>
<tr><td>auth-service</td><td>Go / Gin</td><td>8081</td><td>PostgreSQL(users)</td><td>注册/登录/JWT/第三方OAuth/Token刷新</td></tr>
<tr><td>economy-service</td><td>Go / Gin</td><td>8082</td><td>PostgreSQL(transactions) + Redis(balance cache)</td><td>货币余额/交易流水/商店购买/充值回调</td></tr>
<tr><td>blueprint-service</td><td>Go / Gin</td><td>8083</td><td>PostgreSQL(blueprints) + MinIO(files)</td><td>蓝图CRUD/评分/搜索/下载/分类</td></tr>
<tr><td>match-service</td><td>Go + WebSocket</td><td>8084</td><td>Redis(matchmaking) + PostgreSQL(matches)</td><td>匹配/房间管理/实时同步/对战结算</td></tr>
<tr><td>social-service</td><td>Go / Gin</td><td>8085</td><td>PostgreSQL(achievements) + Redis(leaderboard)</td><td>成就/排行榜/好友/赛季/活动</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">18.2 auth-service 核心接口</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>接口</th><th>请求</th><th>响应</th><th>备注</th></tr></thead>
<tbody>
<tr><td>POST /register</td><td>{ username, email, password }</td><td>{ userId, token, refreshToken }</td><td>密码 bcrypt;发送验证邮件</td></tr>
<tr><td>POST /login</td><td>{ username, password }</td><td>{ userId, token, refreshToken, profile }</td><td>5 次错误锁定 15min</td></tr>
<tr><td>POST /refresh</td><td>{ refreshToken }</td><td>{ token, refreshToken }</td><td>旧 Token 黑名单</td></tr>
<tr><td>POST /oauth/callback</td><td>{ provider, code }</td><td>{ userId, token, refreshToken }</td><td>Google/GitHub/Discord</td></tr>
<tr><td>GET /profile</td><td>Header: Authorization</td><td>{ userId, username, email, level, exp, balance }</td><td>聚合 economy-service 余额</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">18.3 economy-service 交易事务</h3>
<pre class="code-block">// 购买流程伪代码 - 保证原子性和一致性
func PurchaseItem(userID string, itemID string) error {
// 1. 开启数据库事务
tx := db.Begin()
// 2. 查询商品价格 (行锁)
var item ShopItem
tx.Clauses(clause.Locking{Strength: "UPDATE"}).
First(&item, itemID)
// 3. 查询用户余额 (行锁)
var balance UserBalance
tx.Clauses(clause.Locking{Strength: "UPDATE"}).
First(&balance, "user_id = ?", userID)
// 4. 校验余额
if balance.RedstoneCoins < item.Price {
tx.Rollback()
return ErrInsufficientBalance
}
// 5. 扣减余额
balance.RedstoneCoins -= item.Price
tx.Save(&balance)
// 6. 写入交易流水
tx.Create(&Transaction{
UserID: userID,
Type: "purchase",
Item: item.Name,
Amount: -item.Price,
Currency: "redstone",
BalanceAfter: balance.RedstoneCoins,
})
// 7. 发放商品 (调用对应服务)
if item.Type == "component_pack" {
// 发放元件包到用户库存
} else if item.Type == "blueprint" {
// 标记蓝图为已购买
}
// 8. 提交事务
return tx.Commit().Error
}</pre>
<h3 class="subsection-title">18.4 数据库索引策略</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th></th><th>索引</th><th>类型</th><th>查询场景</th></tr></thead>
<tbody>
<tr><td>users</td><td>idx_users_username</td><td>UNIQUE B-Tree</td><td>登录时按用户名查询</td></tr>
<tr><td>users</td><td>idx_users_email</td><td>UNIQUE B-Tree</td><td>邮箱验证/找回密码</td></tr>
<tr><td>circuits</td><td>idx_circuits_user_id</td><td>B-Tree</td><td>查询用户所有电路</td></tr>
<tr><td>circuits</td><td>idx_circuits_updated</td><td>B-Tree DESC</td><td>按更新时间排序</td></tr>
<tr><td>blueprints</td><td>idx_bp_author</td><td>B-Tree</td><td>作者蓝图列表</td></tr>
<tr><td>blueprints</td><td>idx_bp_category_rating</td><td>Composite B-Tree</td><td>分类+评分排序</td></tr>
<tr><td>transactions</td><td>idx_tx_user_created</td><td>Composite B-Tree DESC</td><td>用户交易历史分页</td></tr>
<tr><td>puzzle_levels</td><td>idx_puzzle_chapter_level</td><td>Composite B-Tree</td><td>章节+关卡序号排序</td></tr>
<tr><td>multiplayer_matches</td><td>idx_match_status_started</td><td>Composite B-Tree</td><td>按状态+时间查询对局</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 18.5 ===== -->
<section class="doc-section" id="relay-server">
<p class="section-eyebrow">18.5 / RELAY SERVER</p>
<h2 class="section-title">联机服务器中转站开发</h2>
<p class="section-desc">独立于业务微服务的联机中转网关,负责 P2P 打洞辅助、房间管理、实时消息路由与断线重连。</p>
<h3 class="subsection-title">架构定位</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>维度</th><th>说明</th></tr></thead>
<tbody>
<tr><td>服务名称</td><td>relay-server (Go 1.22 + gorilla/websocket)</td></tr>
<tr><td>端口</td><td>TCP 8084 (WebSocket) / UDP 8086 (STUN/TURN)</td></tr>
<tr><td>部署形态</td><td>独立进程,不与 auth/economy 等业务服务混部;可水平扩展多节点 + 负载均衡</td></tr>
<tr><td>核心职责</td><td>房间生命周期管理 / WebSocket 长连接维护 / 消息路由转发 / P2P 打洞辅助 / TURN 中继兜底 / 断线重连状态恢复</td></tr>
<tr><td>不负责</td><td>用户认证(由 auth-service 签发 Tokenrelay 仅校验) / 货币结算 / 蓝图存储</td></tr>
<tr><td>设计目标</td><td>单节点支持 5000 并发 WebSocket 连接 / 200 个活跃房间 / 消息转发延迟 P99 <50ms</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">连接拓扑</h3>
<pre class="code-block">
┌──────────┐ ┌──────────────┐ ┌──────────┐
│ Player A │◄───────►│ Relay Server │◄───────►│ Player B │
│ (Client) │ WSS │ (Go + WS) │ WSS │ (Client) │
└──────────┘ └──────┬───────┘ └──────────┘
┌──────┴───────┐
│ Room Manager │
│ (内存状态机) │
└──────┬───────┘
┌─────────────┼─────────────┐
│ │ │
┌─────▼─────┐ ┌────▼────┐ ┌─────▼─────┐
│ STUN/TURN │ │ Redis │ │ Kafka │
│ (UDP) │ │ (状态) │ │ (事件) │
└───────────┘ └─────────┘ └───────────┘
连接模式优先级:
1. P2P 直连 (STUN 打洞成功) -> relay 仅做信令交换
2. TURN 中继 (打洞失败) -> relay 转发所有游戏数据
3. WebSocket 中转 (兜底) -> relay 中心化转发</pre>
<h3 class="subsection-title">消息协议定义 (Protobuf)</h3>
<pre class="code-block">syntax = "proto3";
package relay;
// 客户端 -> Relay 消息
message ClientMessage {
string msg_id = 1; // 消息唯一 ID (UUID)
int32 msg_type = 2; // 消息类型枚举
string room_id = 3; // 目标房间
string user_id = 4; // 发送者
bytes payload = 5; // 业务载荷 (电路 delta / 聊天 / 状态)
int64 timestamp = 6; // 客户端时间戳 (ms)
}
// Relay -> 客户端消息
message ServerMessage {
string msg_id = 1;
int32 msg_type = 2;
string from_user = 3; // 消息来源用户
bytes payload = 4;
int64 server_ts = 5; // 服务端时间戳
int32 seq = 6; // 房间内序号 (用于排序)
}
// 消息类型枚举
enum MessageType {
MSG_JOIN_ROOM = 0; // 加入房间
MSG_LEAVE_ROOM = 1; // 离开房间
MSG_CIRCUIT_DELTA = 2; // 电路增量同步
MSG_CIRCUIT_FULL = 3; // 电路全量同步
MSG_CHAT = 4; // 聊天消息
MSG_PRESENCE = 5; // 在线状态
MSG_CURSOR = 6; // 光标位置同步
MSG_ACTION = 7; // 游戏操作 (放置/删除元件)
MSG_GAME_STATE = 8; // 游戏状态变更 (开始/暂停/结束)
MSG_RECONNECT = 9; // 断线重连
MSG_HEARTBEAT = 10; // 心跳
MSG_KICK = 11; // 踢出
MSG_ERROR = 12; // 错误
}</pre>
<h3 class="subsection-title">房间状态机</h3>
<pre class="code-block">
┌─────────┐ create ┌──────────┐ all ready ┌─────────┐
│ CREATED │─────────►│ WAITING │────────────►│ PLAYING │
└─────────┘ └────┬─────┘ └────┬────┘
│ leave │ end
┌──────▼──────┐ ┌──────▼──────┐
│ ABANDONED │ │ FINISHED │
└─────────────┘ └─────────────┘
房间状态流转规则:
- CREATED -> WAITING: 创建者进入,等待其他玩家
- WAITING -> PLAYING: 所有玩家就绪,房主点击开始
- WAITING -> ABANDONED: 所有玩家离开
- PLAYING -> FINISHED: 游戏结束 (计时到/目标达成/房主终止)
- PLAYING -> WAITING: 回到等待 (仅协作模式)
- 任意状态 -> ABANDONED: 超时无活动 30min</pre>
<h3 class="subsection-title">核心数据结构 (Go)</h3>
<pre class="code-block">// Room 房间结构
type Room struct {
ID string `json:"id"`
Mode GameMode `json:"mode"` // free_build/puzzle/multiplayer
Status RoomStatus `json:"status"` // created/waiting/playing/finished
HostUserID string `json:"host_user_id"`
MaxPlayers int `json:"max_players"`
Players map[string]*Player `json:"players"` // userID -> Player
CircuitData []byte `json:"circuit_data"` // 当前电路快照 (全量)
DeltaQueue chan CircuitDelta `json:"-"` // 增量更新队列
SeqCounter int64 `json:"seq_counter"` // 消息序号计数器
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
mu sync.RWMutex `json:"-"`
}
// Player 玩家连接
type Player struct {
UserID string `json:"user_id"`
Username string `json:"username"`
Conn *websocket.Conn `json:"-"` // WebSocket 连接
IsReady bool `json:"is_ready"`
Cursor struct {
X int `json:"x"`
Y int `json:"y"`
} `json:"cursor"`
JoinedAt time.Time `json:"joined_at"`
LastActive time.Time `json:"last_active"`
SendQueue chan []byte `json:"-"` // 发送队列 (异步写)
}
// CircuitDelta 电路增量更新
type CircuitDelta struct {
PlayerID string `json:"player_id"`
OpType DeltaOpType `json:"op_type"` // place/delete/move/rotate/wire
Component *ComponentData `json:"component,omitempty"`
Wire *WireData `json:"wire,omitempty"`
Position *Position `json:"position,omitempty"`
Tick int64 `json:"tick"`
Seq int64 `json:"seq"`
}
// RelayServer 中转服务器
type RelayServer struct {
Rooms map[string]*Room // roomID -> Room
Players map[string]*Player // userID -> Player (全局索引)
Register chan *Player // 注册通道
Unregister chan *Player // 注销通道
Broadcast chan *BroadcastMsg // 广播通道
Redis *redis.Client // Redis (持久化房间状态)
Logger *zap.Logger
mu sync.RWMutex
}</pre>
<h3 class="subsection-title">核心处理流程伪代码</h3>
<pre class="code-block">// === WebSocket 连接处理 ===
func (s *RelayServer) HandleConnection(conn *websocket.Conn, userID string, roomID string) {
player := &Player{
UserID: userID,
Conn: conn,
SendQueue: make(chan []byte, 256),
JoinedAt: time.Now(),
}
// 1. 注册玩家
s.Register <- player
// 2. 加入房间
room := s.GetOrCreateRoom(roomID)
room.AddPlayer(player)
// 3. 通知房间内其他玩家
room.BroadcastExcept(userID, MSG_PRESENCE, &PresencePayload{
UserID: userID, Status: "joined"
})
// 4. 向新玩家发送当前电路全量快照
player.Send(MSG_CIRCUIT_FULL, room.CircuitData)
// 5. 启动读写 goroutine
go s.writePump(player)
s.readPump(player, room)
}
// === 读取客户端消息 ===
func (s *RelayServer) readPump(player *Player, room *Room) {
defer func() {
s.Unregister <- player
room.RemovePlayer(player.UserID)
room.BroadcastExcept(player.UserID, MSG_PRESENCE, &PresencePayload{
UserID: player.UserID, Status: "left"
})
player.Conn.Close()
}()
for {
_, message, err := player.Conn.ReadMessage()
if err != nil {
break // 连接断开
}
var msg ClientMessage
proto.Unmarshal(message, &msg)
switch msg.MsgType {
case MSG_CIRCUIT_DELTA:
// 应用增量到房间电路快照
delta := parseDelta(msg.Payload)
room.ApplyDelta(delta)
// 广播给房间内其他玩家
room.BroadcastExcept(msg.UserId, MSG_CIRCUIT_DELTA, msg.Payload)
case MSG_CHAT:
room.BroadcastAll(MSG_CHAT, msg.Payload)
case MSG_CURSOR:
room.BroadcastExcept(msg.UserId, MSG_CURSOR, msg.Payload)
case MSG_ACTION:
// 游戏操作需服务端校验 (多人对战模式)
if room.Mode == GameModeMultiplayer {
if !s.ValidateAction(room, msg) {
player.Send(MSG_ERROR, &ErrorPayload{Code: "invalid_action"})
continue
}
}
room.BroadcastAll(MSG_ACTION, msg.Payload)
case MSG_HEARTBEAT:
player.LastActive = time.Now()
player.Send(MSG_HEARTBEAT, &HeartbeatPayload{ServerTs: time.Now().UnixMilli()})
}
}
}
// === 断线重连 ===
func (s *RelayServer) HandleReconnect(userID string, roomID string, conn *websocket.Conn) {
room, ok := s.Rooms[roomID]
if !ok {
// 房间已不存在
conn.WriteMessage(MSG_ERROR, encodeError("room_not_found"))
return
}
player, ok := room.Players[userID]
if ok {
// 旧连接还存在,关闭旧连接
oldConn := player.Conn
player.Conn = conn
close(player.SendQueue)
player.SendQueue = make(chan []byte, 256)
oldConn.Close()
} else {
// 玩家已被清理,重新加入
player = &Player{
UserID: userID, Conn: conn,
SendQueue: make(chan []byte, 256),
}
room.AddPlayer(player)
}
// 发送重连成功 + 当前全量快照 + 最近 50 条消息
player.Send(MSG_RECONNECT, &ReconnectPayload{
Success: true,
CircuitSnapshot: room.CircuitData,
RecentMsgs: room.GetRecentMessages(50),
Players: room.GetPlayerList(),
})
go s.writePump(player)
go s.readPump(player, room)
}
// === 房间广播 ===
func (r *Room) BroadcastExcept(userID string, msgType MessageType, payload []byte) {
r.mu.RLock()
defer r.mu.RUnlock()
r.SeqCounter++
msg := &ServerMessage{
MsgType: int32(msgType),
Payload: payload,
ServerTs: time.Now().UnixMilli(),
Seq: r.SeqCounter,
}
data, _ := proto.Marshal(msg)
for _, player := range r.Players {
if player.UserID == userID {
continue
}
select {
case player.SendQueue <- data:
default:
// 队列满,关闭连接
close(player.SendQueue)
delete(r.Players, player.UserID)
}
}
}</pre>
<h3 class="subsection-title">P2P 打洞与 TURN 中继</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>阶段</th><th>行为</th><th>协议</th><th>超时</th></tr></thead>
<tbody>
<tr><td>1. ICE 候选收集</td><td>客户端收集本地/反射/中继候选地址</td><td>STUN (UDP)</td><td>5s</td></tr>
<tr><td>2. 候选交换</td><td>通过 relay-server WebSocket 交换 SDP 和 ICE 候选</td><td>WebSocket</td><td>3s</td></tr>
<tr><td>3. 连接检查</td><td>ICE 对每对候选地址进行连通性检查</td><td>STUN Binding</td><td>10s</td></tr>
<tr><td>4a. P2P 直连成功</td><td>后续游戏数据走 P2P 通道,relay 仅维持信令</td><td>UDP (P2P)</td><td>-</td></tr>
<tr><td>4b. P2P 失败 -> TURN</td><td>分配 TURN 中继地址,所有数据经 TURN 转发</td><td>TURN (UDP)</td><td>-</td></tr>
<tr><td>4c. TURN 失败 -> WSS</td><td>回退到 WebSocket 中心化转发</td><td>WebSocket</td><td>-</td></tr>
<tr><td>5. 心跳保活</td><td>P2P 模式每 15s 发 STUN Binding 保活;WSS 模式 30s 心跳</td><td>STUN / WS</td><td>60s 无响应断开</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">断线重连策略</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>断线时长</th><th>客户端行为</th><th>服务端行为</th><th>恢复方式</th></tr></thead>
<tbody>
<tr><td><5s</td><td>自动重连,缓存消息</td><td>保留房间和玩家状态</td><td>WebSocket 重连 + 增量同步</td></tr>
<tr><td>5-30s</td><td>显示"重连中..."UI</td><td>标记玩家为"暂离",保留位置</td><td>重连 + 全量快照 + 最近 50 条消息</td></tr>
<tr><td>30s-3min</td><td>重试退避 (1s/2s/4s/8s)</td><td>保留房间,玩家标记"掉线"</td><td>重连 + 全量快照</td></tr>
<tr><td>3-30min</td><td>提示"连接超时"</td><td>房间保留,玩家可手动重连</td><td>重新加入房间</td></tr>
<tr><td>>30min</td><td>-</td><td>房间超时回收,玩家移除</td><td>需重新创建/加入房间</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">水平扩展方案</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>组件</th><th>方案</th><th>说明</th></tr></thead>
<tbody>
<tr><td>负载均衡</td><td>L4 TCP 负载均衡 (HAProxy / Nginx stream)</td><td>WebSocket 长连接用最少连接策略;sticky session by userID</td></tr>
<tr><td>跨节点消息</td><td>Redis Pub/Sub</td><td>房间内玩家可能连在不同 relay 节点;消息先发 Redis channel,各节点订阅自己管理的房间</td></tr>
<tr><td>房间状态持久化</td><td>Redis Hash (room:{id})</td><td>房间元数据 + 玩家列表持久化,节点故障后可恢复</td></tr>
<tr><td>电路快照存储</td><td>Redis (热) + MinIO (冷)</td><td>活跃房间电路快照存 Redis;房间结束后归档 MinIO</td></tr>
<tr><td>连接亲和性</td><td>Consistent Hash by roomID</td><td>同一房间的玩家尽量路由到同一 relay 节点,减少跨节点转发</td></tr>
<tr><td>优雅缩容</td><td>drain 模式</td><td>节点标记 draining 后拒绝新连接,等现有连接自然结束或迁移</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">监控指标</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>指标</th><th>Prometheus Metric</th><th>告警阈值</th></tr></thead>
<tbody>
<tr><td>在线 WebSocket 连接数</td><td>relay_connections_total</td><td>>4500 (单节点)</td></tr>
<tr><td>活跃房间数</td><td>relay_rooms_active</td><td>>180</td></tr>
<tr><td>消息转发延迟 P99</td><td>relay_msg_latency_seconds (histogram)</td><td>>50ms</td></tr>
<tr><td>消息丢失率</td><td>relay_msg_drop_rate</td><td>>0.1%</td></tr>
<tr><td>P2P 打洞成功率</td><td>relay_p2p_success_rate</td><td><70%</td></tr>
<tr><td>TURN 中继流量</td><td>relay_turn_bytes_total (counter)</td><td>月预算阈值告警</td></tr>
<tr><td>断线重连成功率</td><td>relay_reconnect_success_rate</td><td><90%</td></tr>
<tr><td>goroutine 数量</td><td>go_goroutines</td><td>>10000</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">开发任务分解</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>任务</th><th>Sprint</th><th>人日</th><th>依赖</th></tr></thead>
<tbody>
<tr><td>WebSocket 连接管理 + 读写 goroutine + 心跳</td><td>S11</td><td class="num">3</td><td></td></tr>
<tr><td>房间状态机 + 玩家管理 + 广播机制</td><td>S11</td><td class="num">4</td><td>WS 连接管理</td></tr>
<tr><td>Protobuf 消息协议定义 + 编解码</td><td>S11</td><td class="num">2</td><td></td></tr>
<tr><td>电路增量同步 (delta apply + broadcast)</td><td>S11</td><td class="num">4</td><td>房间管理</td></tr>
<tr><td>断线重连 + 全量快照恢复</td><td>S12</td><td class="num">3</td><td>增量同步</td></tr>
<tr><td>STUN/TURN 服务集成 + ICE 候选交换</td><td>S12</td><td class="num">5</td><td>WS 连接管理</td></tr>
<tr><td>Redis Pub/Sub 跨节点消息</td><td>S12</td><td class="num">3</td><td>房间管理</td></tr>
<tr><td>游戏操作服务端校验 (多人对战)</td><td>S12</td><td class="num">3</td><td>增量同步</td></tr>
<tr><td>Prometheus 指标埋点 + Grafana 看板</td><td>S12</td><td class="num">2</td><td>WS 连接管理</td></tr>
<tr><td>压力测试 (5000 连接 + 200 房间)</td><td>S16</td><td class="num">3</td><td>全部功能完成</td></tr>
<tr><td>合计</td><td>-</td><td class="num">32</td><td>-</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 19 ===== -->
<section class="doc-section" id="testing">
<p class="section-eyebrow">19 / TESTING</p>
<h2 class="section-title">测试与质量保障</h2>
<p class="section-desc">四层测试体系:单元测试、集成测试、性能测试、E2E 测试,覆盖客户端与服务端。</p>
<h3 class="subsection-title">19.1 测试分层</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>层级</th><th>覆盖率目标</th><th>工具</th><th>运行频率</th><th>负责人</th></tr></thead>
<tbody>
<tr><td>单元测试</td><td>>=80%</td><td>Unity Test Framework (客户端) / Go testing (服务端)</td><td>每次 PR</td><td>开发人员</td></tr>
<tr><td>集成测试</td><td>核心链路 100%</td><td>Go test + Docker Compose / Unity PlayMode</td><td>每日 Nightly</td><td>QA + 开发</td></tr>
<tr><td>性能测试</td><td>关键指标达标</td><td>Unity Profiler / k6 / wrk</td><td>每 Sprint</td><td>QA</td></tr>
<tr><td>E2E 测试</td><td>主流程 100%</td><td>Unity PlayMode + API 自动化</td><td>每 Sprint</td><td>QA</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">19.2 仿真引擎单元测试用例</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>用例编号</th><th>测试场景</th><th>输入</th><th>预期输出</th></tr></thead>
<tbody>
<tr><td>SIM-001</td><td>红石粉信号衰减</td><td>电源(15) + 15 格红石粉</td><td>第 15 格强度=1,第 16 格=0</td></tr>
<tr><td>SIM-002</td><td>中继器重置强度</td><td>衰减至 1 的信号经中继器</td><td>中继器输出强度=15</td></tr>
<tr><td>SIM-003</td><td>AND 门真值表</td><td>4 种输入组合 (00/01/10/11)</td><td>输出 0/0/0/1</td></tr>
<tr><td>SIM-004</td><td>红石火把反相</td><td>附着方块有信号</td><td>火把熄灭,无输出</td></tr>
<tr><td>SIM-005</td><td>中继器锁存</td><td>侧面输入信号时</td><td>输出冻结在当前状态</td></tr>
<tr><td>SIM-006</td><td>活塞推动链</td><td>13 个连续方块</td><td>推动失败(超过 12 个上限)</td></tr>
<tr><td>SIM-007</td><td>短路检测</td><td>两个电源直连同一导线</td><td>触发短路警告,仿真暂停</td></tr>
<tr><td>SIM-008</td><td>555 无稳态振荡</td><td>R=10, C=4</td><td>输出方波,周期 = 0.693*(R1+R2)*C tick</td></tr>
<tr><td>SIM-009</td><td>运放反相放大</td><td>Vin=5, Rf=10, R1=5</td><td>Vout = -10</td></tr>
<tr><td>SIM-010</td><td>ADC 4-bit 转换</td><td>模拟输入强度=13</td><td>数字输出 = 1101</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">19.3 性能指标与压测目标</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>场景</th><th>指标</th><th>目标值</th><th>工具</th></tr></thead>
<tbody>
<tr><td>客户端 - 小型电路 (50 元件)</td><td>仿真 FPS</td><td>>=60 fps</td><td>Unity Profiler</td></tr>
<tr><td>客户端 - 大型电路 (500 元件)</td><td>仿真 FPS</td><td>>=30 fps</td><td>Unity Profiler</td></tr>
<tr><td>客户端 - 超大画布 (512x512)</td><td>渲染 FPS</td><td>>=30 fps</td><td>Unity Profiler</td></tr>
<tr><td>客户端 - 内存占用</td><td>峰值内存</td><td><=1GB</td><td>Unity Memory Profiler</td></tr>
<tr><td>服务端 - 登录接口</td><td>P99 延迟</td><td><=100ms</td><td>wrk</td></tr>
<tr><td>服务端 - 商店购买</td><td>P99 延迟</td><td><=200ms</td><td>wrk</td></tr>
<tr><td>服务端 - 并发用户</td><td>最大并发</td><td>>=5000</td><td>k6</td></tr>
<tr><td>多人同步 - 画布编辑</td><td>端到端延迟</td><td><=200ms</td><td>自定义压测脚本</td></tr>
<tr><td>多人同步 - 匹配等待</td><td>平均等待</td><td><=30s</td><td>日志统计</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">19.4 Bug 分级与响应 SLA</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>级别</th><th>定义</th><th>响应时间</th><th>修复时限</th></tr></thead>
<tbody>
<tr><td>P0 阻塞</td><td>崩溃/数据丢失/核心功能不可用/安全漏洞</td><td>30 分钟</td><td>24 小时内</td></tr>
<tr><td>P1 严重</td><td>核心功能异常/性能严重退化/支付错误</td><td>2 小时</td><td>当前 Sprint 内</td></tr>
<tr><td>P2 一般</td><td>非核心功能异常/UI 错位/文案错误</td><td>1 个工作日</td><td>下个 Sprint</td></tr>
<tr><td>P3 轻微</td><td>体验优化/建议类</td><td>3 个工作日</td><td>Backlog 排期</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 20 ===== -->
<section class="doc-section" id="performance">
<p class="section-eyebrow">20 / PERFORMANCE</p>
<h2 class="section-title">性能优化方案</h2>
<p class="section-desc">客户端、服务端、网络三个维度的具体优化措施与实施节点。</p>
<h3 class="subsection-title">20.1 客户端优化</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>优化项</th><th>问题</th><th>方案</th><th>实施节点</th></tr></thead>
<tbody>
<tr><td>ECS 仿真</td><td>大电路 GameObject 方式导致 GC Spike</td><td>仿真数据迁移至 ECS (Entities 1.0),元件数据用 IComponentData,信号传播用 IJobChunk</td><td>S4 仿真引擎重构</td></tr>
<tr><td>分块渲染</td><td>512x512 画布全量渲染卡顿</td><td>16x16 Chunk + 视口裁剪,仅渲染可见区域 + 1 格缓冲</td><td>S2 画布开发时</td></tr>
<tr><td>信号轨迹 GPU 绘制</td><td>每格信号线逐个 GameObject 性能差</td><td>ComputeBuffer + 自定义 Shader,全画布信号轨迹一次 DrawCall</td><td>S4 仿真引擎 v2</td></tr>
<tr><td>对象池</td><td>放置/删除元件频繁 Instantiate/Destroy</td><td>预生成 500 个元件 GameObject 池,按需取用/归还</td><td>S2 画布开发时</td></tr>
<tr><td>仿真分帧</td><td>大电路单 tick BFS 导致主线程阻塞</td><td>BFS 分帧执行,每帧最多 2000 格更新,跨帧续传</td><td>S4 仿真引擎 v2</td></tr>
<tr><td>LOD 降级</td><td>全景浏览时细节渲染浪费 GPU</td><td>缩放 <50% 时元件降级为纯色方块关闭信号动画</td><td>S15 UI 打磨</td></tr>
<tr><td>纹理图集</td><td>80 种元件图标各自纹理导致 DrawCall 多</td><td>所有元件图标打包为 1024x1024 Atlas,单次 DrawCall</td><td>S7 元件填充时</td></tr>
<tr><td>异步加载</td><td>关卡数据/蓝图加载阻塞主线程</td><td>JSON 反序列化放入 async Task,加载完成回调切换</td><td>S6 关卡系统</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">20.2 服务端优化</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>优化项</th><th>问题</th><th>方案</th><th>实施节点</th></tr></thead>
<tbody>
<tr><td>Redis 余额缓存</td><td>每次请求查 PostgreSQL 余额慢</td><td>余额写入 Redis Cache-Aside,写操作回写 DB + 失效缓存</td><td>S8 货币系统</td></tr>
<tr><td>连接池</td><td>数据库频繁建连开销大</td><td>pgxpool 连接池,最大 25 连接/服务,空闲 60s 回收</td><td>S5 认证系统</td></tr>
<tr><td>排行榜 ZSET</td><td>排行榜分页查询慢</td><td>Redis Sorted Set 存储积分排名,ZREVRANGE 分页</td><td>S12 多人对战</td></tr>
<tr><td>蓝图搜索 ES</td><td>PostgreSQL LIKE 搜索全表扫描</td><td>蓝图数据同步至 Elasticsearch,支持全文搜索+标签过滤</td><td>S13 蓝图工坊</td></tr>
<tr><td>API 限流</td><td>恶意刷接口</td><td>Nginx 层 rate_limit 100req/min/IP;关键接口令牌桶 10req/s/user</td><td>S5 认证系统</td></tr>
<tr><td>异步任务队列</td><td>成就检查/经济结算阻塞请求</td><td>RabbitMQ 消费者异步处理,请求仅入队即返回</td><td>S8 货币系统</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">20.3 网络优化</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>优化项</th><th>方案</th><th>效果</th></tr></thead>
<tbody>
<tr><td>Delta 同步</td><td>多人编辑仅同步变更的格子和元件,非全量画布</td><td>带宽减少 90%+</td></tr>
<tr><td>Protobuf 编码</td><td>实时同步消息用 Protobuf 替代 JSON</td><td>消息体积减少 60%+</td></tr>
<tr><td>WebSocket 压缩</td><td>开启 permessage-deflate 压缩</td><td>带宽减少 50%+</td></tr>
<tr><td>客户端预测</td><td>元件放置/删除本地立即生效,服务端确认后修正</td><td>操作延迟感知 <50ms</td></tr>
<tr><td>断线重连</td><td>WebSocket 断开 30s 内重连,恢复画布状态</td><td>用户体验连续</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 21 ===== -->
<section class="doc-section" id="security">
<p class="section-eyebrow">21 / SECURITY</p>
<h2 class="section-title">安全实施方案</h2>
<p class="section-desc">认证安全、数据安全、反作弊、基础设施安全四层防护体系。</p>
<h3 class="subsection-title">21.1 认证与授权</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>措施</th><th>实现方式</th><th>说明</th></tr></thead>
<tbody>
<tr><td>密码加密</td><td>bcrypt cost=12</td><td>服务端加盐哈希,不可逆</td></tr>
<tr><td>JWT Token</td><td>RS256 签名,Access 15min + Refresh 7d</td><td>Access Token 无状态;Refresh Token Redis 黑名单</td></tr>
<tr><td>登录保护</td><td>5 次错误锁定 15min + IP 限流</td><td>防止暴力破解</td></tr>
<tr><td>异地登录验证</td><td>新设备/新IP 邮箱二次验证码</td><td>6 位数字验证码,5min 有效</td></tr>
<tr><td>OAuth 第三方</td><td>Google/GitHub/Discord OAuth2</td><td>不存储第三方密码,仅存 provider+providerId</td></tr>
<tr><td>API 鉴权</td><td>Bearer Token + RBAC 权限校验</td><td>每个接口声明所需角色,中间件统一校验</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">21.2 数据安全</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>措施</th><th>实现方式</th></tr></thead>
<tbody>
<tr><td>传输加密</td><td>全站 HTTPS TLS 1.3WebSocket over TLS (wss)</td></tr>
<tr><td>敏感数据加密</td><td>邮箱/手机号 AES-256-GCM 加密存储;密钥 KMS 管理</td></tr>
<tr><td>SQL 注入防护</td><td>Go ORM 参数化查询,禁止字符串拼接 SQL</td></tr>
<tr><td>XSS 防护</td><td>蓝图描述/用户名等 UGC 内容 HTML 转义后存储</td></tr>
<tr><td>CSRF 防护</td><td>SameSite=Strict Cookie + CSRF Token 双重防护</td></tr>
<tr><td>数据备份</td><td>PostgreSQL 每日全量 + WAL 实时归档;7 日保留期</td></tr>
<tr><td>GDPR 合规</td><td>支持账号注销+数据导出;隐私政策明确告知数据用途</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">21.3 反作弊系统</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>场景</th><th>检测方式</th><th>处理措施</th></tr></thead>
<tbody>
<tr><td>解谜作弊</td><td>服务端校验电路数据合法性 + 输出验证</td><td>拒绝奖励,记录异常行为</td></tr>
<tr><td>货币刷取</td><td>产出频率监控 + 行为模式分析</td><td>异常产出冻结账户,人工审核</td></tr>
<tr><td>多人对战作弊</td><td>关键操作服务端权威校验 + 客户端预测修正</td><td>判定无效,扣除积分,封禁 7 天</td></tr>
<tr><td>蓝图抄袭</td><td>蓝图哈希比对 + 相似度算法</td><td>下架抄袭蓝图,警告作者</td></tr>
<tr><td>客户端修改</td><td>代码混淆 + 关键逻辑服务端校验 + 完整性校验</td><td>完整性校验失败拒绝登录</td></tr>
<tr><td>黑产刷币</td><td>交易频率监控 + IP 设备指纹 + 金额异常检测</td><td>冻结资产,IP 封禁,上报风控</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 22 ===== -->
<section class="doc-section" id="cicd">
<p class="section-eyebrow">22 / CI/CD</p>
<h2 class="section-title">CI/CD 流水线</h2>
<p class="section-desc">从代码提交到生产部署的自动化流水线配置。</p>
<h3 class="subsection-title">22.1 流水线阶段</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>阶段</th><th>触发</th><th>任务</th><th>预计时长</th></tr></thead>
<tbody>
<tr><td>Lint & Build</td><td>PR / Push</td><td>Go vet + golangci-lintUnity Build;编译检查</td><td>3 min</td></tr>
<tr><td>Unit Test</td><td>PR / Push</td><td>Go test -race -coverUnity EditMode + PlayMode Test</td><td>5 min</td></tr>
<tr><td>Integration Test</td><td>Push to main</td><td>Docker Compose 启动全链路;API 集成测试</td><td>8 min</td></tr>
<tr><td>Build Artifacts</td><td>Push to main / Tag</td><td>Go 二进制编译;Unity 客户端打包(Win+Mac)</td><td>15 min</td></tr>
<tr><td>Deploy Staging</td><td>Push to main</td><td>Docker 镜像推 HarborK8s 滚动更新 Staging</td><td>5 min</td></tr>
<tr><td>Smoke Test</td><td>Deploy Staging 后</td><td>核心接口可用性检查;客户端启动测试</td><td>3 min</td></tr>
<tr><td>Deploy Production</td><td>Tag v* 手动触发</td><td>人工确认 -> K8s 滚动更新 Production</td><td>5 min</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">22.2 环境配置</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>环境</th><th>用途</th><th>数据库</th><th>部署方式</th></tr></thead>
<tbody>
<tr><td>Local</td><td>开发调试</td><td>SQLite + 本地 Redis</td><td>docker-compose dev</td></tr>
<tr><td>Staging</td><td>集成测试 + QA 验收</td><td>PostgreSQL(单机) + Redis(单机)</td><td>K8s staging namespace</td></tr>
<tr><td>Beta</td><td>封闭/开放 Beta 测试</td><td>PostgreSQL(主从) + Redis(哨兵)</td><td>K8s beta namespace (2 副本)</td></tr>
<tr><td>Production</td><td>正式生产</td><td>PostgreSQL(主从+读写分离) + Redis(集群)</td><td>K8s production namespace (3+ 副本 + HPA)</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">22.3 发布与回滚</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>操作</th><th>方式</th><th>预计耗时</th></tr></thead>
<tbody>
<tr><td>正常发布</td><td>Git Tag -> CI 自动构建 -> K8s 滚动更新(零停机)</td><td>15-20 min</td></tr>
<tr><td>热修复</td><td>hotfix 分支 -> 快速 CI -> 直接部署 Production</td><td>10-15 min</td></tr>
<tr><td>紧急回滚</td><td>kubectl rollout undo deployment/xxx --to-revision=N</td><td>2 min</td></tr>
<tr><td>数据库回滚</td><td>Migration down 脚本 + WAL 恢复</td><td>15 min</td></tr>
<tr><td>客户端热更新</td><td>配置/数值/关卡 JSON 增量下发</td><td>即时</td></tr>
<tr><td>客户端全量更新</td><td>官网安装包替换 + 增量补丁</td><td>用户下次启动</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 23 ===== -->
<section class="doc-section" id="budget">
<p class="section-eyebrow">23 / BUDGET</p>
<h2 class="section-title">预算与成本估算</h2>
<p class="section-desc">9 个月开发期 + 首年运营期的成本估算(人民币)。</p>
<h3 class="subsection-title">23.1 人力成本</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>阶段</th><th>人数</th><th>月数</th><th>人均月薪</th><th>小计</th></tr></thead>
<tbody>
<tr><td>Phase 1 (M1-2)</td><td class="num">4</td><td class="num">2</td><td class="num">25,000</td><td class="num">200,000</td></tr>
<tr><td>Phase 2 (M3-5)</td><td class="num">8</td><td class="num">3</td><td class="num">25,000</td><td class="num">600,000</td></tr>
<tr><td>Phase 3 (M6-8)</td><td class="num">12</td><td class="num">3</td><td class="num">25,000</td><td class="num">900,000</td></tr>
<tr><td>Phase 4 (M9)</td><td class="num">12</td><td class="num">1</td><td class="num">25,000</td><td class="num">300,000</td></tr>
<tr><td>开发期合计</td><td>-</td><td class="num">9</td><td>-</td><td class="num">2,000,000</td></tr>
<tr><td>首年运营 (M10-12)</td><td class="num">10</td><td class="num">3</td><td class="num">25,000</td><td class="num">750,000</td></tr>
<tr><td>总计首年</td><td>-</td><td class="num">12</td><td>-</td><td class="num">2,750,000</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">23.2 基础设施成本(月度)</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>项目</th><th>规格</th><th>月费用</th><th>备注</th></tr></thead>
<tbody>
<tr><td>应用服务器</td><td>8C16G x3 (K8s 节点)</td><td class="num">3,600</td><td>阿里云 ECS</td></tr>
<tr><td>数据库</td><td>PostgreSQL 8C32G 主从</td><td class="num">4,500</td><td>RDS 高可用版</td></tr>
<tr><td>Redis</td><td>4G 集群版</td><td class="num">800</td><td>阿里云 Redis</td></tr>
<tr><td>对象存储</td><td>MinIO/OSS 500GB</td><td class="num">500</td><td>蓝图文件+截图</td></tr>
<tr><td>CDN</td><td>1TB/月 流量</td><td class="num">500</td><td>更新包+静态资源</td></tr>
<tr><td>消息队列</td><td>RabbitMQ 2C4G</td><td class="num">600</td><td>异步任务</td></tr>
<tr><td>Elasticsearch</td><td>2C8G</td><td class="num">1,200</td><td>蓝图搜索</td></tr>
<tr><td>监控+日志</td><td>Prometheus+Grafana+ELK</td><td class="num">1,500</td><td>自建+云服务混合</td></tr>
<tr><td>域名+SSL</td><td>redcircuit.game + 通配符证书</td><td class="num">100</td><td>年费摊月</td></tr>
<tr><td>月度合计</td><td>-</td><td class="num">13,300</td><td>-</td></tr>
<tr><td>首年合计</td><td>-</td><td class="num">159,600</td><td>-</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">23.3 其他成本</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>项目</th><th>费用</th><th>说明</th></tr></thead>
<tbody>
<tr><td>Unity 订阅</td><td class="num">0</td><td>Unity Personal 免费版(年收入 <20万刀Pro $204// (年收入超限后)</td></tr>
<tr><td>开发工具</td><td class="num">20,000</td><td>Figma Pro + JetBrains IDE + 其他工具年费</td></tr>
<tr><td>第三方服务</td><td class="num">15,000</td><td>邮件服务/SMS 验证码/OAuth/API 网关</td></tr>
<tr><td>美术外包</td><td class="num">80,000</td><td>部分元件图标/特效/UI 切图外包</td></tr>
<tr><td>QA 外包</td><td class="num">30,000</td><td>Beta 测试期间外包测试</td></tr>
<tr><td>营销推广</td><td class="num">100,000</td><td>首发推广+B 站/KOL 合作</td></tr>
<tr><td>其他合计</td><td class="num">245,000</td><td>-</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">23.4 总预算汇总</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>类别</th><th>金额</th><th>占比</th></tr></thead>
<tbody>
<tr><td>人力成本</td><td class="num">2,750,000</td><td class="num">87%</td></tr>
<tr><td>基础设施</td><td class="num">159,600</td><td class="num">5%</td></tr>
<tr><td>其他成本</td><td class="num">245,000</td><td class="num">8%</td></tr>
<tr><td>总计首年预算</td><td class="num">3,154,600</td><td class="num">100%</td></tr>
<tr><td>建议预留缓冲 (15%)</td><td class="num">473,190</td><td>-</td></tr>
<tr><td>建议总预算</td><td class="num">3,627,790</td><td>-</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 24 ===== -->
<section class="doc-section" id="rollout">
<p class="section-eyebrow">24 / ROLLOUT</p>
<h2 class="section-title">上线发布策略</h2>
<p class="section-desc">分阶段灰度发布、数据监控、应急预案与运营节奏。</p>
<h3 class="subsection-title">24.1 灰度发布计划</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>阶段</th><th>时间</th><th>用户量</th><th>目标</th><th>通过标准</th></tr></thead>
<tbody>
<tr><td>内测 Alpha</td><td>M5 结束</td><td>团队 20 人</td><td>核心功能验证</td><td>P0 Bug 清零</td></tr>
<tr><td>封闭 Beta</td><td>M8 结束</td><td>500 人邀请制</td><td>全功能验证 + 压力测试</td><td>P0/P1 清零;留存 >30%</td></tr>
<tr><td>开放 Beta</td><td>M9 W1-2</td><td>5,000 人公开注册</td><td>服务器压测 + 数据收集</td><td>5000 并发稳定;P0 清零</td></tr>
<tr><td>正式发布</td><td>M9 W3</td><td>全网开放</td><td>商业化运营启动</td><td>首周 DAU >5,000;留存 >35%</td></tr>
<tr><td>推广期</td><td>M10+</td><td>持续增长</td><td>KOL 推广 + 社区运营</td><td>MAU >50,000</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">24.2 发布日监控清单</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>监控项</th><th>工具</th><th>告警阈值</th><th>负责人</th></tr></thead>
<tbody>
<tr><td>服务器 CPU</td><td>Prometheus</td><td>>80% 持续 5min</td><td>服务端工程师</td></tr>
<tr><td>服务器内存</td><td>Prometheus</td><td>>85% 持续 5min</td><td>服务端工程师</td></tr>
<tr><td>API P99 延迟</td><td>Grafana</td><td>>500ms</td><td>服务端工程师</td></tr>
<tr><td>API 错误率</td><td>Sentry</td><td>>1%</td><td>服务端工程师</td></tr>
<tr><td>客户端崩溃率</td><td>Sentry</td><td>>2%</td><td>客户端工程师</td></tr>
<tr><td>WebSocket 连接数</td><td>Grafana</td><td>>4000</td><td>服务端工程师</td></tr>
<tr><td>数据库慢查询</td><td>pg_stat_statements</td><td>>1s</td><td>DBA / 服务端</td></tr>
<tr><td>登录成功率</td><td>Grafana</td><td><95%</td><td>QA</td></tr>
<tr><td>支付成功率</td><td>Grafana</td><td><98%</td><td>QA + 运营</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">24.3 应急预案</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>故障等级</th><th>触发条件</th><th>响应流程</th><th>恢复目标</th></tr></thead>
<tbody>
<tr><td>S1 严重故障</td><td>全服不可用 / 数据丢失 / 支付异常</td><td>电话通知全员 -> 紧急 War Room -> 修复 -> 事后复盘</td><td>1 小时内恢复</td></tr>
<tr><td>S2 主要故障</td><td>核心功能不可用 / 性能严重退化</td><td>飞书告警 -> 值班工程师处理 -> 升级判断</td><td>4 小时内恢复</td></tr>
<tr><td>S3 一般故障</td><td>非核心功能异常 / 少数用户受影响</td><td>工单系统 -> 工作时间内处理</td><td>24 小时内恢复</td></tr>
<tr><td>回滚预案</td><td>新版本引入严重 Bug</td><td>kubectl rollout undo -> 数据库回滚 -> 客户端提示旧版</td><td>10 分钟内回滚完成</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">24.4 首年运营节奏</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>月份</th><th>运营重点</th><th>内容更新</th><th>活动</th></tr></thead>
<tbody>
<tr><td>M9 发布月</td><td>稳定性保障 + 新手引导优化</td><td>240 关 + 80 元件首发</td><td>首发七日登录奖励</td></tr>
<tr><td>M10</td><td>数据驱动调优 + 社区建设</td><td>限时活动关卡 20 关</td><td>万圣节主题电路设计赛</td></tr>
<tr><td>M11</td><td>赛季 1 启动 + 蓝图生态</td><td>新增元件 5 种 + 赛季排行</td><td>赛季 1 排位赛 + 双倍红石币周末</td></tr>
<tr><td>M12</td><td>留存提升 + 平衡性补丁</td><td>大师关卡 +10 关 + 蓝图审核优化</td><td>圣诞/元旦限定皮肤 + 年度总结</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ===== Section 25 ===== -->
<section class="doc-section" id="appendix">
<p class="section-eyebrow">25 / APPENDIX</p>
<h2 class="section-title">附录</h2>
<p class="section-desc">元件成本速查表与常见电路设计模式参考。</p>
<h3 class="subsection-title">A. 元件成本速查表</h3>
<p class="body-text">全部元件按成本升序排列,便于快速查阅预算规划。共 80 种元件。</p>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>序号</th><th>编号</th><th>元件名</th><th>类别</th><th>成本(红石币)</th></tr></thead>
<tbody>
<tr><td class="num">1</td><td class="num">W-01</td><td>红石粉</td><td>WIRE</td><td class="num">5</td></tr>
<tr><td class="num">2</td><td class="num">O-13</td><td>LED</td><td>OUTPUT</td><td class="num">15</td></tr>
<tr><td class="num">3</td><td class="num">W-04</td><td>绝缘导线</td><td>WIRE</td><td class="num">15</td></tr>
<tr><td class="num">4</td><td class="num">W-06</td><td>铜导线</td><td>WIRE</td><td class="num">12</td></tr>
<tr><td class="num">5</td><td class="num">A-01</td><td>电阻</td><td>ANALOG</td><td class="num">20</td></tr>
<tr><td class="num">6</td><td class="num">W-07</td><td>跳线</td><td>WIRE</td><td class="num">18</td></tr>
<tr><td class="num">7</td><td class="num">W-05</td><td>信号桥</td><td>WIRE</td><td class="num">25</td></tr>
<tr><td class="num">8</td><td class="num">S-11</td><td>拨动开关</td><td>SWITCH</td><td class="num">25</td></tr>
<tr><td class="num">9</td><td class="num">P-03</td><td>拉杆</td><td>POWER</td><td class="num">30</td></tr>
<tr><td class="num">10</td><td class="num">S-03</td><td>拉杆</td><td>SWITCH</td><td class="num">30</td></tr>
<tr><td class="num">11</td><td class="num">P-05</td><td>压力板</td><td>POWER</td><td class="num">35</td></tr>
<tr><td class="num">12</td><td class="num">S-04</td><td>压力板木质</td><td>SWITCH</td><td class="num">35</td></tr>
<tr><td class="num">13</td><td class="num">O-14</td><td>蜂鸣器</td><td>OUTPUT</td><td class="num">35</td></tr>
<tr><td class="num">14</td><td class="num">P-04</td><td>按钮</td><td>POWER</td><td class="num">40</td></tr>
<tr><td class="num">15</td><td class="num">S-01</td><td>按钮木质</td><td>SWITCH</td><td class="num">40</td></tr>
<tr><td class="num">16</td><td class="num">S-02</td><td>按钮石质</td><td>SWITCH</td><td class="num">40</td></tr>
<tr><td class="num">17</td><td class="num">P-09</td><td>直流电源</td><td>POWER</td><td class="num">40</td></tr>
<tr><td class="num">18</td><td class="num">A-04</td><td>二极管</td><td>ANALOG</td><td class="num">45</td></tr>
<tr><td class="num">19</td><td class="num">S-07</td><td>绊线钩</td><td>SWITCH</td><td class="num">45</td></tr>
<tr><td class="num">20</td><td class="num">P-01</td><td>红石火把</td><td>POWER</td><td class="num">50</td></tr>
<tr><td class="num">21</td><td class="num">S-05</td><td>压力板铁质</td><td>SWITCH</td><td class="num">50</td></tr>
<tr><td class="num">22</td><td class="num">O-10</td><td>门(木)</td><td>OUTPUT</td><td class="num">50</td></tr>
<tr><td class="num">23</td><td class="num">A-05</td><td>稳压管</td><td>ANALOG</td><td class="num">55</td></tr>
<tr><td class="num">24</td><td class="num">O-12</td><td>灯笼</td><td>OUTPUT</td><td class="num">55</td></tr>
<tr><td class="num">25</td><td class="num">A-02</td><td>电容</td><td>ANALOG</td><td class="num">60</td></tr>
<tr><td class="num">26</td><td class="num">O-01</td><td>红石灯</td><td>OUTPUT</td><td class="num">60</td></tr>
<tr><td class="num">27</td><td class="num">O-11</td><td>活板门</td><td>OUTPUT</td><td class="num">60</td></tr>
<tr><td class="num">28</td><td class="num">S-10</td><td>标靶</td><td>SWITCH</td><td class="num">60</td></tr>
<tr><td class="num">29</td><td class="num">A-03</td><td>电感</td><td>ANALOG</td><td class="num">70</td></tr>
<tr><td class="num">30</td><td class="num">O-07</td><td>音符盒</td><td>OUTPUT</td><td class="num">70</td></tr>
<tr><td class="num">31</td><td class="num">P-08</td><td>探测铁轨</td><td>POWER</td><td class="num">70</td></tr>
<tr><td class="num">32</td><td class="num">P-10</td><td>电池组</td><td>POWER</td><td class="num">85</td></tr>
<tr><td class="num">33</td><td class="num">W-02</td><td>红石中继器</td><td>WIRE</td><td class="num">80</td></tr>
<tr><td class="num">34</td><td class="num">S-06</td><td>压力板金质</td><td>SWITCH</td><td class="num">80</td></tr>
<tr><td class="num">35</td><td class="num">O-09</td><td>门(铁)</td><td>OUTPUT</td><td class="num">80</td></tr>
<tr><td class="num">36</td><td class="num">O-15</td><td>数码管</td><td>OUTPUT</td><td class="num">90</td></tr>
<tr><td class="num">37</td><td class="num">P-06</td><td>阳光探测器</td><td>POWER</td><td class="num">90</td></tr>
<tr><td class="num">38</td><td class="num">P-07</td><td>阳光探测器(夜)</td><td>POWER</td><td class="num">90</td></tr>
<tr><td class="num">39</td><td class="num">S-08</td><td>阳光探测器</td><td>SWITCH</td><td class="num">90</td></tr>
<tr><td class="num">40</td><td class="num">P-02</td><td>红石块</td><td>POWER</td><td class="num">100</td></tr>
<tr><td class="num">41</td><td class="num">O-06</td><td>漏斗</td><td>OUTPUT</td><td class="num">100</td></tr>
<tr><td class="num">42</td><td class="num">L-08</td><td>中继器逻辑</td><td>LOGIC</td><td class="num">100</td></tr>
<tr><td class="num">43</td><td class="num">S-12</td><td>继电器</td><td>SWITCH</td><td class="num">120</td></tr>
<tr><td class="num">44</td><td class="num">W-03</td><td>红石比较器</td><td>WIRE</td><td class="num">120</td></tr>
<tr><td class="num">45</td><td class="num">O-05</td><td>投掷器</td><td>OUTPUT</td><td class="num">120</td></tr>
<tr><td class="num">46</td><td class="num">X-05</td><td>信号分配器</td><td>SPECIAL</td><td class="num">120</td></tr>
<tr><td class="num">47</td><td class="num">S-09</td><td>观察者</td><td>SWITCH</td><td class="num">150</td></tr>
<tr><td class="num">48</td><td class="num">O-02</td><td>活塞</td><td>OUTPUT</td><td class="num">150</td></tr>
<tr><td class="num">49</td><td class="num">L-01</td><td>NOT</td><td>LOGIC</td><td class="num">150</td></tr>
<tr><td class="num">50</td><td class="num">X-04</td><td>信号延迟器</td><td>SPECIAL</td><td class="num">150</td></tr>
<tr><td class="num">51</td><td class="num">A-09</td><td>光耦</td><td>ANALOG</td><td class="num">160</td></tr>
<tr><td class="num">52</td><td class="num">O-04</td><td>发射器</td><td>OUTPUT</td><td class="num">180</td></tr>
<tr><td class="num">53</td><td class="num">A-06</td><td>NPN 三极管</td><td>ANALOG</td><td class="num">180</td></tr>
<tr><td class="num">54</td><td class="num">A-07</td><td>PNP 三极管</td><td>ANALOG</td><td class="num">180</td></tr>
<tr><td class="num">55</td><td class="num">PD-04</td><td>MOS 管</td><td>POWER_DEVICE</td><td class="num">200</td></tr>
<tr><td class="num">56</td><td class="num">O-03</td><td>粘性活塞</td><td>OUTPUT</td><td class="num">200</td></tr>
<tr><td class="num">57</td><td class="num">L-02</td><td>AND</td><td>LOGIC</td><td class="num">200</td></tr>
<tr><td class="num">58</td><td class="num">L-03</td><td>OR</td><td>LOGIC</td><td class="num">200</td></tr>
<tr><td class="num">59</td><td class="num">PD-01</td><td>单向可控硅 SCR</td><td>POWER_DEVICE</td><td class="num">220</td></tr>
<tr><td class="num">60</td><td class="num">L-04</td><td>NAND</td><td>LOGIC</td><td class="num">220</td></tr>
<tr><td class="num">61</td><td class="num">L-05</td><td>NOR</td><td>LOGIC</td><td class="num">220</td></tr>
<tr><td class="num">62</td><td class="num">PD-06</td><td>继电器模组</td><td>POWER_DEVICE</td><td class="num">250</td></tr>
<tr><td class="num">63</td><td class="num">L-06</td><td>XOR</td><td>LOGIC</td><td class="num">250</td></tr>
<tr><td class="num">64</td><td class="num">L-07</td><td>XNOR</td><td>LOGIC</td><td class="num">250</td></tr>
<tr><td class="num">65</td><td class="num">X-06</td><td>物品过滤器</td><td>SPECIAL</td><td class="num">250</td></tr>
<tr><td class="num">66</td><td class="num">PD-02</td><td>双向可控硅 TRIAC</td><td>POWER_DEVICE</td><td class="num">280</td></tr>
<tr><td class="num">67</td><td class="num">A-08</td><td>运算放大器</td><td>ANALOG</td><td class="num">280</td></tr>
<tr><td class="num">68</td><td class="num">PD-05</td><td>达林顿管</td><td>POWER_DEVICE</td><td class="num">300</td></tr>
<tr><td class="num">69</td><td class="num">O-08</td><td>TNT</td><td>OUTPUT</td><td class="num">300</td></tr>
<tr><td class="num">70</td><td class="num">X-03</td><td>信号示波器</td><td>SPECIAL</td><td class="num">300</td></tr>
<tr><td class="num">71</td><td class="num">X-10</td><td>555 定时器</td><td>SPECIAL</td><td class="num">350</td></tr>
<tr><td class="num">72</td><td class="num">L-09</td><td>RS锁存器</td><td>LOGIC</td><td class="num">350</td></tr>
<tr><td class="num">73</td><td class="num">L-10</td><td>D触发器</td><td>LOGIC</td><td class="num">400</td></tr>
<tr><td class="num">74</td><td class="num">X-07</td><td>物品分类器</td><td>SPECIAL</td><td class="num">400</td></tr>
<tr><td class="num">75</td><td class="num">PD-03</td><td>IGBT</td><td>POWER_DEVICE</td><td class="num">420</td></tr>
<tr><td class="num">76</td><td class="num">X-08</td><td>ADC 模数转换器</td><td>SPECIAL</td><td class="num">450</td></tr>
<tr><td class="num">77</td><td class="num">X-09</td><td>DAC 数模转换器</td><td>SPECIAL</td><td class="num">450</td></tr>
<tr><td class="num">78</td><td class="num">L-11</td><td>计数器</td><td>LOGIC</td><td class="num">500</td></tr>
<tr><td class="num">79</td><td class="num">X-02</td><td>结构方块</td><td>SPECIAL</td><td class="num">800</td></tr>
<tr><td class="num">80</td><td class="num">X-01</td><td>命令方块</td><td>SPECIAL</td><td class="num">1000</td></tr>
</tbody>
</table>
</div>
<h3 class="subsection-title">B. 常见电路设计模式</h3>
<div class="table-wrap">
<table class="doc-table">
<thead><tr><th>模式</th><th>核心元件</th><th>用途</th></tr></thead>
<tbody>
<tr><td>T 触发器</td><td>RS 锁存器 + 边沿检测</td><td>按钮单次脉冲切换开关状态</td></tr>
<tr><td>时钟发生器</td><td>中继器环形振荡</td><td>产生周期性脉冲信号</td></tr>
<tr><td>脉冲缩短器</td><td>比较器 + 中继器</td><td>将长脉冲截断为单 tick 短脉冲</td></tr>
<tr><td>脉冲延长器</td><td>多级中继器链</td><td>延长脉冲持续时间</td></tr>
<tr><td>二进制计数器</td><td>D 触发器级联</td><td>多 Bit 二进制计数与溢出进位</td></tr>
<tr><td>优先编码器</td><td>OR 门阵列 + NOT</td><td>多输入中输出最高优先级</td></tr>
<tr><td>边沿检测器</td><td>比较器 + 中继器</td><td>检测信号上升沿或下降沿</td></tr>
<tr><td>数据选择器 MUX</td><td>AND + OR + NOT</td><td>按控制端选择多路输入之一输出</td></tr>
</tbody>
</table>
</div>
</section>
</div>
</main>
<footer class="doc-footer">
<p>RedCircuit · 红石回路 - 完整开发文档 v1.0</p>
<p>© 2026 RedCircuit Studio. 保留所有权利。</p>
<p>文档生成日期:2026-08-07 | 机密文档仅供内部使用</p>
</footer>
<script>
(function(){
var toggle=document.getElementById('tocToggle');
var sidebar=document.getElementById('tocSidebar');
if(toggle&&sidebar){toggle.addEventListener('click',function(){sidebar.classList.toggle('open');});}
var links=document.querySelectorAll('.toc-link');
var sections=document.querySelectorAll('.doc-section');
function onScroll(){
var cur='';
sections.forEach(function(s){if(window.scrollY>=s.offsetTop-90){cur=s.id;}});
links.forEach(function(l){
var href=l.getAttribute('href');
l.classList.toggle('active',href==='#'+cur);
});
}
window.addEventListener('scroll',onScroll,{passive:true});
onScroll();
})();
lucide.createIcons();
</script>
</body>
</html>