# SurvivalcraftSuAPI
**Repository Path**: SC-SPM/survivalcraft-su-api
## Basic Information
- **Project Name**: SurvivalcraftSuAPI
- **Description**: Survivalcraft 2 SuMod 开发框架,用于创建第三方 Mod。
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2025-10-02
- **Last Updated**: 2026-05-27
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Survivalcraft MAUI 移植指南
> 版本: 2.4.10.8
> 目标框架: net10.0-android + net10.0-windows10.0.19041.0
> 公开仓库: https://gitee.com/SC-SPM/survivalcraft-su-api
## 项目结构
```
P:\UGIT\Survivalcraft\
├── Engine/ # 引擎库(MAUI class library)
│ ├── Graphics/Bindings/
│ │ ├── GL.cs # Android DllImport 实现 (#if !WINDOWS)
│ │ └── GL.Windows.cs # Windows Silk.NET.OpenGL 代理 (#if WINDOWS)
│ ├── Input/
│ │ ├── Mouse.cs # 鼠标输入(含 PollMousePosition 轮询)
│ │ ├── Keyboard.cs # 键盘输入
│ │ ├── Touch.cs # 触摸输入
│ │ └── GamePad.cs # 手柄输入
│ ├── Platforms/
│ │ ├── Android/
│ │ │ ├── Input/ # Touch, GamePad, Mouse, Keyboard
│ │ │ ├── EngineActivity.cs # Android Activity(Dispatch 输入路由)
│ │ │ ├── Window.cs # Silk.NET 窗口 + GLES 2.0 上下文
│ │ │ └── Valve.VR/ # VR 支持(仅 Android)
│ │ └── Windows/
│ │ ├── Input/ # Keyboard, GamePad, Touch, KeyboardInput
│ │ ├── Window.cs # Silk.NET 窗口 + GL 3.2 上下文 + 鼠标事件
│ │ ├── Storage.cs # WinRT Storage API
│ │ └── Utilities.cs # WinRT 工具类
│ ├── Audio/ # OpenAL 绑定(条件编译库名)
│ └── Engine.csproj # Microsoft.NET.Sdk + 平台条件编译
├── EntitySystem/ # 实体系统库
│ ├── GameEntitySystem/ # 游戏实体系统
│ ├── TemplatesDatabase/ # 模板数据库
│ ├── XmlUtilities/ # XML 工具
│ └── Platforms/Android/ # Android 平台文件
├── Survivalcraft/ # 游戏主程序(MAUI app)
│ ├── Game/ # 游戏逻辑
│ ├── SimpleJson/ # 内置 JSON 库
│ ├── Platforms/
│ │ ├── Android/
│ │ │ ├── Game/ # Android 平台游戏代码
│ │ │ └── Valve.VR/ # VR 支持
│ │ └── Windows/
│ │ └── Game/ # Windows 平台游戏代码
│ ├── Resources/ # Content.pak 等嵌入资源
│ │ ├── AppIcon/appicon.png # SC 应用图标 (144×144)
│ │ ├── Splash/splash.png # SC 启动画面
│ │ └── Images/ # 图片资源
│ ├── Resources.icon.ico # Windows exe 图标 (9256B)
│ └── Survivalcraft.csproj # MAUI 应用 + 版本信息
└── doc/ # 项目文档
```
## 编译
### 前置条件
- Visual Studio 2022 (18.x Enterprise)
- .NET 10.0 SDK
- MAUI 工作负载
- Android SDK (API 21+)
### 编译命令
**⚠️ 必须使用 MSBuild,禁止 `dotnet build`**(与 Engine.csproj 不兼容)
```powershell
$msbuild = "d:\Program Files\Microsoft Visual Studio\18\Enterprise\MSBuild\Current\Bin\MSBuild.exe"
# Windows
& $msbuild "P:\UGIT\Survivalcraft\Survivalcraft\Survivalcraft.csproj" `
-t:Build -p:TargetFramework=net10.0-windows10.0.19041.0 -v:minimal
# Android
& $msbuild "P:\UGIT\Survivalcraft\Survivalcraft\Survivalcraft.csproj" `
-t:Build -p:TargetFramework=net10.0-android -v:minimal
```
### 版本信息
```xml
2.4.10.8
2.4.10.8
24108
com.candyrufus.survivalcraft2
```
游戏内版本号由 `VersionsManager.Version` 从程序集版本自动读取,格式 `Major.Minor.Build.Revision`。
⚠ `ApplicationDisplayVersion` 不能按平台条件设置——会导致 NU1105 `PackageVersion` 不一致错误。必须用统一的 `` 属性。
## 条件编译
| 符号 | 定义条件 | 用途 |
|------|---------|------|
| `WINDOWS` | net10.0-windows 目标框架 | GL.Windows.cs, Window.cs, 库名选择 |
| `ANDROID` | net10.0-android 目标框架 | EngineActivity, Touch, 库名选择 |
**WINDOWS 由框架自动定义**;ANDROID 需在 csproj 中手动添加 ``。
## OpenGL 绑定
### 双平台架构
| 平台 | 实现文件 | 方式 | GL 上下文版本 |
|------|---------|------|-------------|
| Android | `GL.cs` (`#if !WINDOWS`) | DllImport `libGLESv2` | GLES 2.0 |
| Windows | `GL.Windows.cs` (`#if WINDOWS`) | Silk.NET.OpenGL 代理 | GL 3.2 |
### Windows 端为什么不能 DllImport
`opengl32.dll` 只导出 GL 1.1 核心函数。`glCreateShader` 等 GL 2.0+ 函数必须通过 `wglGetProcAddress` 动态获取函数指针,DllImport 不支持此机制。Silk.NET.OpenGL 自动处理扩展加载。
### 枚举映射
| Engine 枚举 | Silk.NET 枚举 |
|-------------|--------------|
| EnableCap | GLEnum 强转 |
| ClearBufferMask | **uint**(特殊,非 GLEnum) |
| BufferTarget | BufferTargetARB |
| BufferUsageHint | BufferUsageARB |
| FramebufferSlot | FramebufferAttachment |
| ProgramParameterName | ProgramPropertyARB |
### 铁律
1. **opengl32.dll 只有 GL 1.1** — GL 2.0+ 必须 Silk.NET
2. **Clear() 接受 uint** — `G.Clear((uint)mask)`,其他大多数用 `(SGLE)cap`
3. **int↔uint 中转** — Gen/Delete 系列用 `stackalloc uint[]`
4. **ShaderSource 差异** — Silk.NET 接受 string,Engine 用 string[]+int*
5. **NativeLibrary resolver 不可行** — 函数级解析不走 resolver
6. **GLES 上下文版本必须显式指定** — `new APIVersion(2, 0)`(Android)/ `new APIVersion(3, 2)`(Windows)
## 输入系统
### Windows 鼠标输入
**核心问题**:游戏从 Android 移植,Mouse.cs 的 `SetMousePosition`/`BeforeFrame` 均为空方法。Android 不需要隐藏系统光标,Windows 第一人称模式需要。
**修复架构**:
```
Silk.NET IMouse.Position (轮询)
│
BeforeFrameAll()
│
Mouse.PollMousePosition(pos)
├── MouseMovement = pos - m_pollLastPosition
└── MousePosition = IsMouseVisible ? pos : null
Silk.NET IMouse 事件 (MouseDown/Up/Move/Scroll)
│
Window.OnSilkMouseXXX()
│
Mouse.ProcessMouseXXX()
├── ProcessMouseDown/Up → 按钮状态
├── ProcessMouseMove → MousePosition (UI光标) + MouseMove 事件
└── ProcessMouseWheel → MouseWheelMovement (累加)
BeforeFrameAll → CursorMode 切换
IsMouseVisible=true → CursorMode.Normal (系统光标可见)
IsMouseVisible=false → CursorMode.Raw (隐藏+原始输入)
```
**为什么用轮询而非纯事件**:CursorMode.Raw 下光标锁定在窗口中心,MouseMove 事件传的 position 可能始终在中心附近不变。轮询 `IMouse.Position` 则使用 Silk.NET 内部维护的位置(在 Raw 模式下通过 WM_INPUT delta 累加),值正确。
**DLL 搜索注意**:.NET DLL 元数据用 UTF-8 编码存储标识符,不是 UTF-16LE。用 `[Encoding]::Unicode.GetString()` 搜索会找不到。
### Android 输入
详见参考仓库的 Android 输入文档。核心架构:
- Dispatch 级别路由(非 On 级别)
- ConcurrentQueue 线程安全缓冲
- 源过滤(InputSourceType 位掩码)
- BeforeFrame 批量消费
### TranslateKey 修复
`Engine\Platforms\Windows\Input\Keyboard.cs` 中 `TranslateKey` switch 表达式无 default 分支。必须返回 `Key?` 加 `_ => null`,调用方用 `.HasValue` 检查。
## 运行时目录
### Windows
```
Survivalcraft\bin\Debug\net10.0-windows10.0.19041.0\
├── Survivalcraft.exe
├── Engine.dll
├── EntitySystem.dll
├── Content.pak
├── Mods/ # Mod 放置目录
└── Logs/Game.log
```
### Android
```
APK: Survivalcraft\bin\Debug\net10.0-android\com.candyrufus.survivalcraft2.apk
运行时根目录: /data/data/com.candyrufus.survivalcraft2/files/Documents/
日志: .../files/Documents/Logs/Game.log
```
## 常见陷阱
| 问题 | 根因 | 修复 |
|------|------|------|
| NU1105 PackageVersion 不一致 | ApplicationDisplayVersion 按平台条件设置 | 统一 `` 属性 |
| NETSDK1022 重复编译项 | 平台文件未 Compile Remove | 先 Remove 再条件 Include |
| Content.pak 找不到 | RootNamespace 不匹配 | 改回 `Game` |
| 鼠标视角不动/极慢 | CursorMode.Raw 下事件 delta 极小 | PollMousePosition 轮询 |
| SwitchExpressionException | TranslateKey 无 default | 返回 Key? + _ => null |
| Debug.WriteLine 卡顿 | 每帧输出 | 禁止热路径中写日志 |
| InlineArray 残留 | 反编译器生成 | 改为普通 string.Format |
| Lit.psh/vsh 加载失败 | 被识别为立陶宛语卫星程序集 | `false` |
| 静态 UnlitShader 崩溃 | GL 上下文未就绪时类初始化 | lazy-loading GetShader() |
| Windows 窗口无图标 | GLFW 不自动继承 exe 图标 | SendMessage(WM_SETICON) + LoadImage fallback |
| MAUI 模板图标残留 | 新项目未清理 SVG + dotnet_bot | 删除 SVG 替换为 PNG + 修改 csproj |
| WinUI 语言文件夹膨胀 | SatelliteResourceLanguages 不控制 .mui | Build Target PowerShell 删除 |
| GLES 1.1 SIGSEGV | APIVersion() 默认 (0,0) | 显式 `APIVersion(2, 0)` |
## 参考文档
- [PROJECT-LOG.md](PROJECT-LOG.md) — 详细修复日志
- [OPENGL-BINDING.md](OPENGL-BINDING.md) — OpenGL 绑定详解
- 公开仓库: https://gitee.com/SC-SPM/survivalcraft-su-api