Initial commit: FunConnect project with server, relay, client and admin panel

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-24 20:56:36 +08:00
parent eb6e901440
commit b6891483ae
167 changed files with 16147 additions and 106 deletions

181
scripts/build-client.ps1 Normal file
View File

@@ -0,0 +1,181 @@
#
# FunMC 客户端构建脚本 (Windows)
# 用法: .\scripts\build-client.ps1 -Platform <平台> -ServerUrl <服务器URL>
#
# 示例:
# .\scripts\build-client.ps1 -Platform all -ServerUrl "http://funmc.com:3000"
# .\scripts\build-client.ps1 -Platform windows -ServerUrl "http://192.168.1.100:3000"
#
param(
[string]$Platform = "all",
[string]$ServerUrl = ""
)
$ErrorActionPreference = "Stop"
# 配置
$Version = (Get-Content "client\Cargo.toml" | Select-String 'version = "' | Select-Object -First 1) -replace '.*"([^"]+)".*', '$1'
$OutputDir = ".\dist"
# 颜色输出函数
function Write-Info($Message) { Write-Host "[INFO] $Message" -ForegroundColor Cyan }
function Write-Success($Message) { Write-Host "[✓] $Message" -ForegroundColor Green }
function Write-Warning($Message) { Write-Host "[!] $Message" -ForegroundColor Yellow }
function Write-Err($Message) { Write-Host "[✗] $Message" -ForegroundColor Red }
Write-Host ""
Write-Host "╔═══════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "║ FunMC 客户端构建脚本 v$Version" -ForegroundColor Cyan
Write-Host "║ 魔幻方开发 ║" -ForegroundColor Cyan
Write-Host "╚═══════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
Write-Host ""
# 检查依赖
function Test-Dependencies {
Write-Info "检查构建依赖..."
if (-not (Get-Command cargo -ErrorAction SilentlyContinue)) {
Write-Err "错误: 未找到 Rust/Cargo"
exit 1
}
if (-not (Get-Command node -ErrorAction SilentlyContinue)) {
Write-Err "错误: 未找到 Node.js"
exit 1
}
if (-not (Get-Command npm -ErrorAction SilentlyContinue)) {
Write-Err "错误: 未找到 npm"
exit 1
}
Write-Success "依赖检查通过"
}
# 写入服务器配置
function Write-Config {
if ($ServerUrl) {
Write-Info "写入服务器配置: $ServerUrl"
$config = @{
server_url = $ServerUrl
version = $Version
} | ConvertTo-Json
$config | Out-File -FilePath "client\ui\src\config.json" -Encoding UTF8
Write-Success "配置写入完成"
}
}
# 构建前端
function Build-Frontend {
Write-Info "构建前端..."
Push-Location "client\ui"
npm install
npm run build
Pop-Location
Write-Success "前端构建完成"
}
# 构建 Windows
function Build-Windows {
Write-Info "构建 Windows (x64)..."
Push-Location "client"
cargo tauri build
Pop-Location
New-Item -ItemType Directory -Force -Path $OutputDir | Out-Null
$msiBundles = Get-ChildItem "client\target\release\bundle\msi\*.msi" -ErrorAction SilentlyContinue
if ($msiBundles) {
Copy-Item $msiBundles[0].FullName "$OutputDir\FunMC-$Version-windows-x64.msi"
}
$nsiBundles = Get-ChildItem "client\target\release\bundle\nsis\*.exe" -ErrorAction SilentlyContinue
if ($nsiBundles) {
Copy-Item $nsiBundles[0].FullName "$OutputDir\FunMC-$Version-windows-x64.exe"
}
Write-Success "Windows 构建完成"
}
# 构建 Android
function Build-Android {
Write-Info "构建 Android..."
if (-not $env:ANDROID_HOME) {
Write-Warning "未设置 ANDROID_HOME跳过 Android 构建"
return
}
Push-Location "client"
cargo tauri android build --apk
Pop-Location
New-Item -ItemType Directory -Force -Path $OutputDir | Out-Null
$apkBundles = Get-ChildItem "client\gen\android\app\build\outputs\apk\universal\release\*.apk" -ErrorAction SilentlyContinue
if ($apkBundles) {
Copy-Item $apkBundles[0].FullName "$OutputDir\FunMC-$Version-android.apk"
}
Write-Success "Android 构建完成"
}
# 显示构建结果
function Show-Results {
Write-Host ""
Write-Host "╔═══════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "║ 构建完成! ║" -ForegroundColor Cyan
Write-Host "╚═══════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
Write-Host ""
Write-Host "输出目录: $OutputDir" -ForegroundColor Green
Write-Host ""
if (Test-Path $OutputDir) {
Write-Host "构建产物:"
Get-ChildItem $OutputDir | Format-Table Name, Length -AutoSize
}
Write-Host ""
Write-Host "部署说明:" -ForegroundColor Yellow
Write-Host "1. 将 $OutputDir 目录下的文件复制到服务器的 downloads 目录"
Write-Host "2. 用户访问 http://your-server:3000/download 即可下载"
Write-Host ""
Write-Host "魔幻方开发" -ForegroundColor Green
}
# 主流程
try {
Test-Dependencies
Write-Config
Build-Frontend
switch ($Platform) {
"windows" {
Build-Windows
}
"android" {
Build-Android
}
"all" {
Build-Windows
Build-Android
}
default {
Write-Err "未知平台: $Platform"
Write-Host "支持的平台: windows, android, all"
exit 1
}
}
Show-Results
} catch {
Write-Err "构建过程中出错: $_"
exit 1
}

246
scripts/build-client.sh Normal file
View File

@@ -0,0 +1,246 @@
#!/bin/bash
#
# FunMC 客户端构建脚本
# 用法: ./scripts/build-client.sh [平台] [服务器URL]
#
# 示例:
# ./scripts/build-client.sh all http://funmc.com:3000
# ./scripts/build-client.sh windows http://192.168.1.100:3000
# ./scripts/build-client.sh macos-arm64 https://mc.example.com
#
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
# 默认值
PLATFORM="${1:-all}"
SERVER_URL="${2:-}"
VERSION=$(grep '^version' client/Cargo.toml | head -1 | cut -d'"' -f2)
OUTPUT_DIR="./dist"
echo -e "${CYAN}"
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ FunMC 客户端构建脚本 v${VERSION}"
echo "║ 魔幻方开发 ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo -e "${NC}"
# 检查依赖
check_deps() {
echo -e "${YELLOW}检查构建依赖...${NC}"
if ! command -v cargo &> /dev/null; then
echo -e "${RED}错误: 未找到 Rust/Cargo${NC}"
exit 1
fi
if ! command -v node &> /dev/null; then
echo -e "${RED}错误: 未找到 Node.js${NC}"
exit 1
fi
if ! command -v npm &> /dev/null; then
echo -e "${RED}错误: 未找到 npm${NC}"
exit 1
fi
echo -e "${GREEN}✓ 依赖检查通过${NC}"
}
# 写入服务器配置
write_config() {
if [ -n "$SERVER_URL" ]; then
echo -e "${YELLOW}写入服务器配置: $SERVER_URL${NC}"
cat > client/ui/src/config.json << EOF
{
"server_url": "$SERVER_URL",
"version": "$VERSION"
}
EOF
echo -e "${GREEN}✓ 配置写入完成${NC}"
fi
}
# 构建前端
build_frontend() {
echo -e "${YELLOW}构建前端...${NC}"
cd client/ui
npm install
npm run build
cd ../..
echo -e "${GREEN}✓ 前端构建完成${NC}"
}
# 构建 Windows
build_windows() {
echo -e "${YELLOW}构建 Windows (x64)...${NC}"
cd client
if [[ "$OSTYPE" == "linux-gnu"* ]] || [[ "$OSTYPE" == "darwin"* ]]; then
# Cross compile
cargo tauri build --target x86_64-pc-windows-msvc
else
cargo tauri build
fi
cd ..
mkdir -p $OUTPUT_DIR
cp client/target/release/bundle/msi/*.msi "$OUTPUT_DIR/FunMC-${VERSION}-windows-x64.msi" 2>/dev/null || true
cp client/target/release/bundle/nsis/*.exe "$OUTPUT_DIR/FunMC-${VERSION}-windows-x64.exe" 2>/dev/null || true
echo -e "${GREEN}✓ Windows 构建完成${NC}"
}
# 构建 macOS
build_macos_arm64() {
echo -e "${YELLOW}构建 macOS (Apple Silicon)...${NC}"
cd client
cargo tauri build --target aarch64-apple-darwin
cd ..
mkdir -p $OUTPUT_DIR
cp client/target/aarch64-apple-darwin/release/bundle/dmg/*.dmg "$OUTPUT_DIR/FunMC-${VERSION}-macos-arm64.dmg" 2>/dev/null || true
echo -e "${GREEN}✓ macOS (ARM64) 构建完成${NC}"
}
build_macos_x64() {
echo -e "${YELLOW}构建 macOS (Intel)...${NC}"
cd client
cargo tauri build --target x86_64-apple-darwin
cd ..
mkdir -p $OUTPUT_DIR
cp client/target/x86_64-apple-darwin/release/bundle/dmg/*.dmg "$OUTPUT_DIR/FunMC-${VERSION}-macos-x64.dmg" 2>/dev/null || true
echo -e "${GREEN}✓ macOS (x64) 构建完成${NC}"
}
# 构建 Linux
build_linux() {
echo -e "${YELLOW}构建 Linux (x64)...${NC}"
cd client
cargo tauri build
cd ..
mkdir -p $OUTPUT_DIR
cp client/target/release/bundle/appimage/*.AppImage "$OUTPUT_DIR/FunMC-${VERSION}-linux-x64.AppImage" 2>/dev/null || true
cp client/target/release/bundle/deb/*.deb "$OUTPUT_DIR/FunMC-${VERSION}-linux-x64.deb" 2>/dev/null || true
echo -e "${GREEN}✓ Linux 构建完成${NC}"
}
# 构建 Android
build_android() {
echo -e "${YELLOW}构建 Android...${NC}"
if [ -z "$ANDROID_HOME" ]; then
echo -e "${RED}错误: 未设置 ANDROID_HOME${NC}"
return 1
fi
cd client
cargo tauri android build --apk
cd ..
mkdir -p $OUTPUT_DIR
cp client/gen/android/app/build/outputs/apk/universal/release/*.apk "$OUTPUT_DIR/FunMC-${VERSION}-android.apk" 2>/dev/null || true
echo -e "${GREEN}✓ Android 构建完成${NC}"
}
# 构建 iOS
build_ios() {
echo -e "${YELLOW}构建 iOS...${NC}"
if [[ "$OSTYPE" != "darwin"* ]]; then
echo -e "${RED}错误: iOS 只能在 macOS 上构建${NC}"
return 1
fi
cd client
cargo tauri ios build
cd ..
echo -e "${GREEN}✓ iOS 构建完成 (需要在 Xcode 中归档和分发)${NC}"
}
# 显示构建结果
show_results() {
echo ""
echo -e "${CYAN}╔═══════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ 构建完成! ║${NC}"
echo -e "${CYAN}╚═══════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${GREEN}输出目录: $OUTPUT_DIR${NC}"
echo ""
if [ -d "$OUTPUT_DIR" ]; then
echo "构建产物:"
ls -lh $OUTPUT_DIR/
fi
echo ""
echo -e "${YELLOW}部署说明:${NC}"
echo "1. 将 $OUTPUT_DIR 目录下的文件复制到服务器的 downloads 目录"
echo "2. 用户访问 http://your-server:3000/download 即可下载"
echo ""
echo -e "${GREEN}魔幻方开发${NC}"
}
# 主流程
main() {
check_deps
write_config
build_frontend
case $PLATFORM in
windows)
build_windows
;;
macos-arm64)
build_macos_arm64
;;
macos-x64)
build_macos_x64
;;
macos)
build_macos_arm64
build_macos_x64
;;
linux)
build_linux
;;
android)
build_android
;;
ios)
build_ios
;;
all)
build_windows || true
build_macos_arm64 || true
build_macos_x64 || true
build_linux || true
build_android || true
;;
*)
echo -e "${RED}未知平台: $PLATFORM${NC}"
echo "支持的平台: windows, macos-arm64, macos-x64, macos, linux, android, ios, all"
exit 1
;;
esac
show_results
}
main "$@"

103
scripts/build.ps1 Normal file
View File

@@ -0,0 +1,103 @@
# FunMC 构建脚本 (Windows PowerShell)
# 用于构建所有组件
param(
[ValidateSet("all", "client", "server", "relay")]
[string]$Target = "all",
[switch]$Release,
[switch]$Bundle
)
$ErrorActionPreference = "Stop"
$RootDir = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
function Write-Step {
param([string]$Message)
Write-Host "`n==> $Message" -ForegroundColor Cyan
}
function Build-Server {
Write-Step "构建主服务端..."
Push-Location "$RootDir/server"
if ($Release) {
cargo build --release
} else {
cargo build
}
Pop-Location
Write-Host "主服务端构建完成!" -ForegroundColor Green
}
function Build-Relay {
Write-Step "构建中继服务端..."
Push-Location "$RootDir/relay-server"
if ($Release) {
cargo build --release
} else {
cargo build
}
Pop-Location
Write-Host "中继服务端构建完成!" -ForegroundColor Green
}
function Build-Client {
Write-Step "构建客户端..."
Push-Location "$RootDir/client"
# 安装前端依赖
Write-Host "安装前端依赖..."
Push-Location "ui"
npm install
Pop-Location
# 构建 Tauri 应用
if ($Bundle) {
if ($Release) {
cargo tauri build
} else {
cargo tauri build --debug
}
} else {
if ($Release) {
cargo build --release
} else {
cargo build
}
}
Pop-Location
Write-Host "客户端构建完成!" -ForegroundColor Green
}
# 主逻辑
Write-Host "FunMC 构建系统" -ForegroundColor Yellow
Write-Host "===============" -ForegroundColor Yellow
switch ($Target) {
"all" {
Build-Server
Build-Relay
Build-Client
}
"client" {
Build-Client
}
"server" {
Build-Server
}
"relay" {
Build-Relay
}
}
Write-Host "`n所有构建完成!" -ForegroundColor Green
if ($Bundle -and $Target -in @("all", "client")) {
Write-Host "`n客户端安装包位置:" -ForegroundColor Yellow
Write-Host "$RootDir\client\target\release\bundle\" -ForegroundColor White
}

141
scripts/build.sh Normal file
View File

@@ -0,0 +1,141 @@
#!/bin/bash
# FunMC 构建脚本 (Linux/macOS)
# 用于构建所有组件
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
TARGET="all"
RELEASE=false
BUNDLE=false
print_usage() {
echo "用法: $0 [选项]"
echo ""
echo "选项:"
echo " -t, --target <target> 构建目标 (all, client, server, relay) [默认: all]"
echo " -r, --release 构建发布版本"
echo " -b, --bundle 打包客户端安装包"
echo " -h, --help 显示帮助信息"
}
while [[ $# -gt 0 ]]; do
case $1 in
-t|--target)
TARGET="$2"
shift 2
;;
-r|--release)
RELEASE=true
shift
;;
-b|--bundle)
BUNDLE=true
shift
;;
-h|--help)
print_usage
exit 0
;;
*)
echo "未知选项: $1"
print_usage
exit 1
;;
esac
done
log_step() {
echo -e "\n\033[36m==> $1\033[0m"
}
log_success() {
echo -e "\033[32m$1\033[0m"
}
build_server() {
log_step "构建主服务端..."
cd "$ROOT_DIR/server"
if $RELEASE; then
cargo build --release
else
cargo build
fi
log_success "主服务端构建完成!"
}
build_relay() {
log_step "构建中继服务端..."
cd "$ROOT_DIR/relay-server"
if $RELEASE; then
cargo build --release
else
cargo build
fi
log_success "中继服务端构建完成!"
}
build_client() {
log_step "构建客户端..."
cd "$ROOT_DIR/client"
# 安装前端依赖
echo "安装前端依赖..."
cd ui
npm install
cd ..
# 构建 Tauri 应用
if $BUNDLE; then
if $RELEASE; then
cargo tauri build
else
cargo tauri build --debug
fi
else
if $RELEASE; then
cargo build --release
else
cargo build
fi
fi
log_success "客户端构建完成!"
}
echo -e "\033[33mFunMC 构建系统\033[0m"
echo "==============="
case $TARGET in
all)
build_server
build_relay
build_client
;;
client)
build_client
;;
server)
build_server
;;
relay)
build_relay
;;
*)
echo "无效的构建目标: $TARGET"
exit 1
;;
esac
echo -e "\n\033[32m所有构建完成!\033[0m"
if $BUNDLE && [[ "$TARGET" == "all" || "$TARGET" == "client" ]]; then
echo -e "\n\033[33m客户端安装包位置:\033[0m"
echo "$ROOT_DIR/client/target/release/bundle/"
fi

View File

@@ -0,0 +1,43 @@
# FunMC 图标生成脚本 (Windows)
# 需要安装 ImageMagick 或使用 cargo tauri icon 命令
$ErrorActionPreference = "Stop"
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$RootDir = Split-Path -Parent $ScriptDir
$IconsDir = "$RootDir\client\icons"
$SvgPath = "$IconsDir\icon.svg"
Write-Host "FunMC 图标生成脚本" -ForegroundColor Yellow
Write-Host "===================" -ForegroundColor Yellow
# 检查 SVG 源文件
if (-not (Test-Path $SvgPath)) {
Write-Host "错误: 未找到 SVG 源文件: $SvgPath" -ForegroundColor Red
exit 1
}
# 方法 1: 使用 cargo tauri icon (推荐)
Write-Host "`n尝试使用 cargo tauri icon..." -ForegroundColor Cyan
Push-Location "$RootDir\client"
try {
cargo tauri icon $SvgPath
Write-Host "图标生成成功!" -ForegroundColor Green
}
catch {
Write-Host "cargo tauri icon 失败,请手动生成图标" -ForegroundColor Yellow
Write-Host "`n手动生成步骤:" -ForegroundColor White
Write-Host "1. 安装 ImageMagick: https://imagemagick.org/script/download.php"
Write-Host "2. 或使用在线工具: https://realfavicongenerator.net/"
Write-Host "3. 或使用 Figma/Photoshop 导出以下尺寸的 PNG:"
Write-Host " - 32x32.png"
Write-Host " - 128x128.png"
Write-Host " - 128x128@2x.png (256x256)"
Write-Host " - icon.ico (Windows)"
Write-Host " - icon.icns (macOS)"
}
finally {
Pop-Location
}
Write-Host "`n图标目录: $IconsDir" -ForegroundColor Cyan

84
scripts/generate-icons.sh Normal file
View File

@@ -0,0 +1,84 @@
#!/bin/bash
# FunMC 图标生成脚本 (Linux/macOS)
# 需要安装 ImageMagick 或使用 cargo tauri icon 命令
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
ICONS_DIR="$ROOT_DIR/client/icons"
SVG_PATH="$ICONS_DIR/icon.svg"
echo -e "\033[33mFunMC 图标生成脚本\033[0m"
echo "==================="
# 检查 SVG 源文件
if [ ! -f "$SVG_PATH" ]; then
echo -e "\033[31m错误: 未找到 SVG 源文件: $SVG_PATH\033[0m"
exit 1
fi
# 方法 1: 使用 cargo tauri icon (推荐)
echo -e "\n\033[36m尝试使用 cargo tauri icon...\033[0m"
cd "$ROOT_DIR/client"
if cargo tauri icon "$SVG_PATH" 2>/dev/null; then
echo -e "\033[32m图标生成成功!\033[0m"
else
echo -e "\033[33mcargo tauri icon 失败,尝试使用 ImageMagick...\033[0m"
# 方法 2: 使用 ImageMagick
if command -v convert &> /dev/null; then
echo "使用 ImageMagick 生成图标..."
mkdir -p "$ICONS_DIR"
# PNG 图标
convert -background none "$SVG_PATH" -resize 32x32 "$ICONS_DIR/32x32.png"
convert -background none "$SVG_PATH" -resize 128x128 "$ICONS_DIR/128x128.png"
convert -background none "$SVG_PATH" -resize 256x256 "$ICONS_DIR/128x128@2x.png"
# ICO (Windows)
convert -background none "$SVG_PATH" -resize 256x256 \
-define icon:auto-resize=256,128,96,64,48,32,16 \
"$ICONS_DIR/icon.ico"
# ICNS (macOS) - 需要 png2icns 或 iconutil
if command -v png2icns &> /dev/null; then
convert -background none "$SVG_PATH" -resize 1024x1024 "$ICONS_DIR/icon_1024.png"
png2icns "$ICONS_DIR/icon.icns" "$ICONS_DIR/icon_1024.png"
rm "$ICONS_DIR/icon_1024.png"
elif command -v iconutil &> /dev/null; then
ICONSET_DIR="$ICONS_DIR/icon.iconset"
mkdir -p "$ICONSET_DIR"
for size in 16 32 64 128 256 512 1024; do
convert -background none "$SVG_PATH" -resize ${size}x${size} "$ICONSET_DIR/icon_${size}x${size}.png"
done
# 生成 @2x 版本
convert -background none "$SVG_PATH" -resize 32x32 "$ICONSET_DIR/icon_16x16@2x.png"
convert -background none "$SVG_PATH" -resize 64x64 "$ICONSET_DIR/icon_32x32@2x.png"
convert -background none "$SVG_PATH" -resize 256x256 "$ICONSET_DIR/icon_128x128@2x.png"
convert -background none "$SVG_PATH" -resize 512x512 "$ICONSET_DIR/icon_256x256@2x.png"
convert -background none "$SVG_PATH" -resize 1024x1024 "$ICONSET_DIR/icon_512x512@2x.png"
iconutil -c icns "$ICONSET_DIR"
rm -rf "$ICONSET_DIR"
else
echo -e "\033[33m警告: 无法生成 .icns 文件 (需要 png2icns 或 iconutil)\033[0m"
fi
echo -e "\033[32m图标生成完成!\033[0m"
else
echo -e "\033[31m错误: 未找到 ImageMagick\033[0m"
echo "请安装 ImageMagick 后重试:"
echo " Ubuntu/Debian: sudo apt install imagemagick"
echo " macOS: brew install imagemagick"
echo " 或者使用: cargo install tauri-cli && cargo tauri icon"
exit 1
fi
fi
echo -e "\n图标目录: $ICONS_DIR"
ls -la "$ICONS_DIR"

106
scripts/test-lan.ps1 Normal file
View File

@@ -0,0 +1,106 @@
# FunMC 局域网联机测试脚本 (Windows PowerShell)
# 用于快速验证 FunMC 服务是否正常运行
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " FunMC 局域网联机测试脚本" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan
Write-Host ""
# 检查必要的工具
function Test-Command($cmd) {
return [bool](Get-Command $cmd -ErrorAction SilentlyContinue)
}
# 1. 检查 Rust 环境
Write-Host "[1/6] 检查 Rust 环境..." -ForegroundColor Yellow
if (Test-Command "cargo") {
$rustVersion = cargo --version
Write-Host " ✓ Rust 已安装: $rustVersion" -ForegroundColor Green
} else {
Write-Host " ✗ Rust 未安装,请访问 https://rustup.rs 安装" -ForegroundColor Red
exit 1
}
# 2. 检查 Node.js 环境
Write-Host "[2/6] 检查 Node.js 环境..." -ForegroundColor Yellow
if (Test-Command "node") {
$nodeVersion = node --version
Write-Host " ✓ Node.js 已安装: $nodeVersion" -ForegroundColor Green
} else {
Write-Host " ✗ Node.js 未安装,请访问 https://nodejs.org 安装" -ForegroundColor Red
exit 1
}
# 3. 检查数据库连接
Write-Host "[3/6] 检查数据库连接..." -ForegroundColor Yellow
$dbRunning = docker ps --filter "name=funmc-db" --format "{{.Names}}" 2>$null
if ($dbRunning -eq "funmc-db") {
Write-Host " ✓ PostgreSQL 容器运行中" -ForegroundColor Green
} else {
Write-Host " ! PostgreSQL 容器未运行,尝试启动..." -ForegroundColor Yellow
docker start funmc-db 2>$null
if ($LASTEXITCODE -ne 0) {
Write-Host " ! 创建新的 PostgreSQL 容器..." -ForegroundColor Yellow
docker run -d --name funmc-db -p 5432:5432 -e POSTGRES_PASSWORD=password -e POSTGRES_DB=funmc postgres:14
}
Start-Sleep -Seconds 3
Write-Host " ✓ PostgreSQL 容器已启动" -ForegroundColor Green
}
# 4. 检查端口占用
Write-Host "[4/6] 检查端口占用..." -ForegroundColor Yellow
$ports = @(3000, 3001, 7900, 5432)
$allFree = $true
foreach ($port in $ports) {
$used = netstat -an | Select-String ":$port\s"
if ($used) {
Write-Host " ! 端口 $port 已被占用" -ForegroundColor Yellow
$allFree = $false
} else {
Write-Host " ✓ 端口 $port 可用" -ForegroundColor Green
}
}
# 5. 获取本机 IP
Write-Host "[5/6] 获取本机 IP..." -ForegroundColor Yellow
$localIP = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.InterfaceAlias -notlike "*Loopback*" -and $_.IPAddress -notlike "169.*" } | Select-Object -First 1).IPAddress
if ($localIP) {
Write-Host " ✓ 本机局域网 IP: $localIP" -ForegroundColor Green
} else {
Write-Host " ✗ 无法获取本机 IP" -ForegroundColor Red
}
# 6. 显示测试说明
Write-Host "[6/6] 测试说明..." -ForegroundColor Yellow
Write-Host ""
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " 局域网联机测试步骤" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "1. 启动服务端:" -ForegroundColor White
Write-Host " cd server" -ForegroundColor Gray
Write-Host " cargo run" -ForegroundColor Gray
Write-Host ""
Write-Host "2. 启动客户端 (新终端):" -ForegroundColor White
Write-Host " cd client/ui && npm install" -ForegroundColor Gray
Write-Host " cd .. && cargo tauri dev" -ForegroundColor Gray
Write-Host ""
Write-Host "3. 配置其他电脑的客户端:" -ForegroundColor White
Write-Host " 修改 client/src/config.rs:" -ForegroundColor Gray
Write-Host " DEFAULT_SERVER_URL = `"http://${localIP}:3000`"" -ForegroundColor Gray
Write-Host ""
Write-Host "4. 测试流程:" -ForegroundColor White
Write-Host " - 主机: 启动 MC 服务器 -> FunMC 创建房间 -> 开始托管" -ForegroundColor Gray
Write-Host " - 玩家: FunMC 加入房间 -> 连接 -> 复制地址到 MC" -ForegroundColor Gray
Write-Host ""
Write-Host "============================================" -ForegroundColor Cyan
# 询问是否启动服务
Write-Host ""
$start = Read-Host "是否立即启动服务端? (y/n)"
if ($start -eq "y") {
Write-Host ""
Write-Host "启动服务端..." -ForegroundColor Green
Set-Location server
cargo run
}

124
scripts/test-lan.sh Normal file
View File

@@ -0,0 +1,124 @@
#!/bin/bash
# FunMC 局域网联机测试脚本 (Linux/macOS)
set -e
echo "============================================"
echo " FunMC 局域网联机测试脚本"
echo "============================================"
echo ""
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# 检查命令是否存在
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# 1. 检查 Rust 环境
echo -e "${YELLOW}[1/6] 检查 Rust 环境...${NC}"
if command_exists cargo; then
RUST_VERSION=$(cargo --version)
echo -e " ${GREEN}✓ Rust 已安装: $RUST_VERSION${NC}"
else
echo -e " ${RED}✗ Rust 未安装,请运行: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh${NC}"
exit 1
fi
# 2. 检查 Node.js 环境
echo -e "${YELLOW}[2/6] 检查 Node.js 环境...${NC}"
if command_exists node; then
NODE_VERSION=$(node --version)
echo -e " ${GREEN}✓ Node.js 已安装: $NODE_VERSION${NC}"
else
echo -e " ${RED}✗ Node.js 未安装,请访问 https://nodejs.org 安装${NC}"
exit 1
fi
# 3. 检查数据库连接
echo -e "${YELLOW}[3/6] 检查数据库连接...${NC}"
if command_exists docker; then
if docker ps --filter "name=funmc-db" --format "{{.Names}}" | grep -q "funmc-db"; then
echo -e " ${GREEN}✓ PostgreSQL 容器运行中${NC}"
else
echo -e " ${YELLOW}! PostgreSQL 容器未运行,尝试启动...${NC}"
docker start funmc-db 2>/dev/null || \
docker run -d --name funmc-db -p 5432:5432 \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_DB=funmc \
postgres:14
sleep 3
echo -e " ${GREEN}✓ PostgreSQL 容器已启动${NC}"
fi
else
echo -e " ${YELLOW}! Docker 未安装,请手动配置 PostgreSQL${NC}"
fi
# 4. 检查端口占用
echo -e "${YELLOW}[4/6] 检查端口占用...${NC}"
PORTS=(3000 3001 7900 5432)
for PORT in "${PORTS[@]}"; do
if lsof -i :$PORT >/dev/null 2>&1 || netstat -tuln 2>/dev/null | grep -q ":$PORT "; then
echo -e " ${YELLOW}! 端口 $PORT 已被占用${NC}"
else
echo -e " ${GREEN}✓ 端口 $PORT 可用${NC}"
fi
done
# 5. 获取本机 IP
echo -e "${YELLOW}[5/6] 获取本机 IP...${NC}"
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS
LOCAL_IP=$(ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null || echo "")
else
# Linux
LOCAL_IP=$(hostname -I 2>/dev/null | awk '{print $1}' || ip route get 1 | awk '{print $7}' 2>/dev/null || echo "")
fi
if [ -n "$LOCAL_IP" ]; then
echo -e " ${GREEN}✓ 本机局域网 IP: $LOCAL_IP${NC}"
else
echo -e " ${RED}✗ 无法获取本机 IP${NC}"
LOCAL_IP="YOUR_IP"
fi
# 6. 显示测试说明
echo -e "${YELLOW}[6/6] 测试说明...${NC}"
echo ""
echo -e "${CYAN}============================================${NC}"
echo -e "${CYAN} 局域网联机测试步骤${NC}"
echo -e "${CYAN}============================================${NC}"
echo ""
echo "1. 启动服务端:"
echo " cd server"
echo " cargo run"
echo ""
echo "2. 启动客户端 (新终端):"
echo " cd client/ui && npm install"
echo " cd .. && cargo tauri dev"
echo ""
echo "3. 配置其他电脑的客户端:"
echo " 修改 client/src/config.rs:"
echo " DEFAULT_SERVER_URL = \"http://${LOCAL_IP}:3000\""
echo ""
echo "4. 测试流程:"
echo " - 主机: 启动 MC 服务器 -> FunMC 创建房间 -> 开始托管"
echo " - 玩家: FunMC 加入房间 -> 连接 -> 复制地址到 MC"
echo ""
echo -e "${CYAN}============================================${NC}"
# 询问是否启动服务
echo ""
read -p "是否立即启动服务端? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo ""
echo -e "${GREEN}启动服务端...${NC}"
cd server
cargo run
fi