diff --git a/.github/workflows/docs-check.yaml b/.github/workflows/docs-check.yaml index ee56009..3a174be 100644 --- a/.github/workflows/docs-check.yaml +++ b/.github/workflows/docs-check.yaml @@ -1,31 +1,32 @@ name: Documentation Check -# Trigger conditions for documentation workflow on: - # Push events to docs-related paths on active branches push: branches: - main - develop - - documentation - 'release/**' - 'releases/**' paths: - '**.md' - 'docs/**' - '.github/workflows/docs-check.yaml' - # Pull requests with docs-related changes + - 'tools/sync-doc-metadata.ps1' pull_request: branches: - main - develop - - documentation - 'release/**' - 'releases/**' paths: - '**.md' - 'docs/**' - '.github/workflows/docs-check.yaml' + - 'tools/sync-doc-metadata.ps1' + +env: + DOTNET_VERSION: '9.0.x' + PROJECT_PATH: 'src/' jobs: docs-check: @@ -33,108 +34,27 @@ jobs: runs-on: ubuntu-latest steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Check for build-affecting changes in documentation branch - if: | - (github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'documentation') || - (github.event_name == 'push' && github.ref == 'refs/heads/documentation') - run: | - echo "🔍 Checking for build-affecting changes in documentation branch..." - echo "" - - # Determine the base reference for comparison - if [ "${{ github.event_name }}" == "pull_request" ]; then - # For pull requests, compare PR head with base - BASE_REF="${{ github.event.pull_request.base.sha }}" - HEAD_REF="${{ github.event.pull_request.head.sha }}" - echo "📋 Comparing PR changes:" - echo " Base: $BASE_REF" - echo " Head: $HEAD_REF" - else - # For push events, compare with the previous commit - BASE_REF="HEAD^" - HEAD_REF="HEAD" - echo "📋 Comparing push changes:" - echo " Base: $BASE_REF" - echo " Head: $HEAD_REF" - fi - echo "" - - # Get all changed files - CHANGED_FILES=$(git diff --name-only "$BASE_REF" "$HEAD_REF" 2>&1) - - if [ $? -ne 0 ]; then - echo "⚠️ Warning: git diff command failed" - echo "$CHANGED_FILES" - exit 1 - fi - - if [ -z "$CHANGED_FILES" ]; then - echo "ℹ️ No files changed" - exit 0 - fi - - echo "📝 Changed files:" - echo "$CHANGED_FILES" - echo "" - - # Define patterns for build-affecting files - # These are files that should NOT be changed in a documentation-only PR - BUILD_AFFECTING_PATTERNS=( - "^src/" - "^GitVersion\.yml$" - ) - - BLOCKED_FILES="" - while IFS= read -r file; do - [ -z "$file" ] && continue - is_blocked=false - for pattern in "${BUILD_AFFECTING_PATTERNS[@]}"; do - if echo "$file" | grep -qE "$pattern"; then - is_blocked=true - break - fi - done - - if echo "$file" | grep -qE "^\.github/workflows/" && ! echo "$file" | grep -qE "^\.github/workflows/docs-"; then - is_blocked=true - fi - - if [ "$is_blocked" = true ]; then - BLOCKED_FILES="$BLOCKED_FILES$file"$'\n' - fi - done <<< "$CHANGED_FILES" - - if [ -n "$BLOCKED_FILES" ]; then - echo "❌ ERROR: Found build-affecting changes in documentation branch!" - echo "" - echo "The following files affect the build and should not be modified in PRs to the documentation branch:" - echo "$BLOCKED_FILES" - echo "" - echo "The documentation branch should only contain:" - echo " - Markdown files (*.md)" - echo " - Files in docs/ directory" - echo " - Documentation workflow files (docs-*.yaml)" - echo "" - exit 1 - fi - - echo "✅ All changes are documentation-only" - - - name: Documentation validation - run: | - echo "📚 Documentation Check" - echo "Branch: ${{ github.ref }}" - echo "Event: ${{ github.event_name }}" - echo "" - echo "✅ Documentation files detected and validated" - echo "" - echo "Future enhancements:" - echo "- Markdown lint validation" - echo "- Link validation" - echo "- Documentation coverage checks" - echo "- Build documentation site" + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Restore dependencies + run: dotnet restore ${{ env.PROJECT_PATH }} + + - name: Check docs metadata sync + shell: pwsh + run: ./tools/sync-doc-metadata.ps1 -Mode check + + - name: Documentation validation summary + run: | + echo "📚 Documentation Check" + echo "Branch: ${{ github.ref }}" + echo "Event: ${{ github.event_name }}" + echo "" + echo "✅ Documentation metadata is in sync" diff --git a/GitVersion.yml b/GitVersion.yml index b31c063..652d44b 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -27,7 +27,7 @@ next-version: 'v0.2.1' # Branch-specific configuration branches: - # Main branch: Production releases + # Main branch: Stable promotions main: # Prevent version jumping when merging from develop # Version increments based on main's own version, not the merged branch @@ -38,7 +38,7 @@ branches: regex: ^master$|^main$ source-branches: ['develop', 'hotfix'] - # Develop branch: Integration branch for ongoing development + # Develop branch: Daily integration develop: # Allow normal version increment from merged branches prevent-increment: @@ -52,18 +52,7 @@ branches: source-branches: ['feature', 'bugfix', 'hotfix'] track-merge-target: false - # Documentation branch: Documentation maintenance - documentation: - # Don't affect main version when merging documentation - prevent-increment: - when-branch-merged: true - increment: Patch - # Docs tag for documentation releases - label: docs - regex: ^docs?$|^documentation$ - source-branches: [] - - # Feature branches: New features under development + # Feature branches: Optional short-lived feature work feature: increment: Minor # Alpha tag for feature development @@ -71,14 +60,14 @@ branches: regex: ^features?[/-](?\d+) source-branches: ['develop'] - # Bugfix branches: Bug fixes under development + # Bugfix branches: Optional short-lived bugfix work bugfix: increment: Patch label: 'bugfix.{BranchName}' regex: ^bug(fix)?[/-] source-branches: ['develop'] - # Hotfix branches: Emergency fixes from production + # Hotfix branches: Exceptional fixes based on main hotfix: increment: Patch label: hotfix @@ -93,12 +82,12 @@ branches: # Use PR number in version (e.g., 1.1.0-pr.123) regex: ^(pull|pull\-requests|pr)[/-](?\d+) - # Release branches: Release preparation + # Release branches: Release execution from main release: increment: None label: rc regex: ^releases?[/-] - source-branches: ['develop', 'main'] + source-branches: ['main'] is-main-branch: false prevent-increment: when-branch-merged: true diff --git a/README.md b/README.md index 7351fe0..a7d698e 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@

- Host multiple Terraria worlds in one launcher process,
keep worlds isolated, and keep extending behavior with plugins and publisher tooling on OTAPI USP.
+ Run multiple Terraria worlds from one launcher,
keep each world in its own context, and handle routing, data sharing, and plugin-driven extension inside the same OTAPI USP runtime.

--- @@ -51,15 +51,14 @@ UnifierTSL wraps [OTAPI Unified Server Process](https://github.com/CedaryCat/OTAPI.UnifiedServerProcess) into a runtime you can run directly to host **multiple Terraria worlds in one launcher process**. -The launcher handles world lifecycle, player join routing, and spins up a dedicated console client per world context so each world's I/O stays separate. -Those console sessions now use an ANSI-safe prompt/status protocol, so launcher and per-world consoles can keep semantic readline state, replay status frames, and recover cleanly after reconnects instead of acting like plain text pipes. -Compared with classic single-world servers or packet-routed multi-process world stacks, Unifier keeps join routing, world handoff, and extension hooks in one runtime surface instead of scattering that logic across process boundaries. +In traditional multi-process multi-world stacks, building a cluster of cooperating worlds usually means extra cross-process routing, state synchronization, and serialization design. Moving players between instances often relies on packet relays and side channels; when plugin-attached data, temporary state, or runtime objects need to cross worlds, problems that could otherwise stay in-process often have to be rewritten as protocols and synchronization flows. + +Compared with approaches that push this coordination outside process boundaries, Unifier, based on OTAPI USP, keeps join routing, world switching, and extension hooks inside the same runtime plane and treats cross-world coordination as a first-class concern from the start. The launcher manages multi-world lifecycle centrally, lets each world run independently and in parallel in its own `ServerContext`, and provides a dedicated console per world so I/O stays isolated. `UnifiedServerCoordinator` handles coordination, `UnifierApi.EventHub` carries event traffic, and `PluginHost.PluginOrchestrator` runs plugin hosting. -With shared connection and state surfaces, you can operate worlds together and build tighter cross-world interactions, while policy-based routing and transfer hooks still leave room for world-level fallback behavior. +This shared listener-and-coordination model reduces the extra overhead and complexity introduced by cross-process relays, making cross-world interaction, data interchange, and unified operations easier while still leaving enough routing control to define the default join target and take over later world-switch flows. -If you push this model further, you can build more gameplay-driven setups: fully connected multi-instance world clusters, elastic worlds that load or unload region-sized shards on demand, or private worlds tuned per player for logic and resource budgets. -These are achievable directions, not out-of-the-box defaults. -Some heavier implementations may stay outside launcher core, but you can expect practical sample plugins for these patterns to land over time in the `plugins/` ecosystem. +From the player's side, this still behaves like a normal Terraria entry point: clients connect to one shared listener port, and `UnifiedServerCoordinator` routes each connection to the selected world inside the same process. If you push this model further, you can build more gameplay-driven setups: fully connected multi-instance world clusters, elastic worlds that load or unload region-sized shards on demand, or private worlds tuned per player for logic and resource budgets. +These are reachable directions, even though the launcher does not currently ship them as default out-of-the-box features, and heavier implementations like these may stay out of the launcher core itself; you can still expect usable example plugins to land under `plugins/` over time. --- @@ -75,7 +74,7 @@ Some heavier implementations may stay outside launcher core, but you can expect | 📦 **Collectible module contexts** | `ModuleLoadContext` gives you unloadable plugin domains and staged dependency handling | | 📝 **Shared logging pipeline** | `UnifierApi.LogCore` supports custom filters, writers, and metadata injectors | | 🛡 **Bundled TShock port** | Ships with a USP-adapted TShock baseline ready for use | -| 💻 **Per-context console isolation** | Named-pipe console sessions with ANSI-safe logs, semantic readline prompts, and live status bars per world context | +| 💻 **Per-context console isolation** | Independent, auto-reconnecting console I/O windows for each world context, plus semantic readline prompts and live status bars | | 🚀 **RID-targeted publishing** | Publisher produces reproducible, runtime-specific directory trees | --- @@ -124,7 +123,7 @@ Additional dependency baselines: Architecture flow

-Actual runtime startup flow: +If you want the real boot order, it looks like this: 1. `Program.Main` initializes assembly resolver, applies pre-run CLI language overrides, and prints runtime version details. 2. `Initializer.Initialize()` prepares Terraria/USP runtime state and loads core hooks (`UnifiedNetworkPatcher`, `UnifiedServerCoordinator`, `ServerContext` setup). @@ -148,6 +147,8 @@ Actual runtime startup flow: ### Pick Your Path +If you already know why you're here, jump in from the track that matches your role: + | Role | Start Here | Why | |:--|:--|:--| | 🖥 Server operator | [Quick Start ↓](#quick-start) | Bring up a usable multi-world host with minimal setup | @@ -158,6 +159,8 @@ Actual runtime startup flow: ## 🚀 Quick Start +If your main goal is "get a launcher up and see worlds come online," start here. + ### Prerequisites Choose the requirement set that matches how you plan to run UnifierTSL: @@ -169,6 +172,8 @@ Choose the requirement set that matches how you plan to run UnifierTSL: ### Option A: Use a Release Bundle +If you just want to run it, this is the shortest path. + **1.** Download the release asset that matches your platform from [GitHub Releases](https://github.com/CedaryCat/UnifierTSL/releases): | Platform | File pattern | @@ -209,7 +214,7 @@ chmod +x UnifierTSL ### Option B: Run from Source -Use this path for local debugging, CI integration, or custom bundle output. +Take this path if you want local debugging, CI integration, or your own Publisher output. **1.** Clone and restore: @@ -253,6 +258,23 @@ dotnet run --project src/UnifierTSL/UnifierTSL.csproj -- \ 3. Switch startup project to `UnifierTSL`, choose the `Executable` launch profile, and start debugging. 4. That profile runs the published launcher from `utsl-publish` and debugs the published program directly. +### What Happens on First Boot + +- On the first successful launch, `config/config.json` is created automatically and stores the effective launcher startup snapshot. CLI arguments still win for the launch you are doing right now. +- Plugin configs live under `config//`. For the bundled TShock port, that root is `config/TShockAPI/`; it also stores other TShock runtime files such as `tshock.sqlite` when SQLite is enabled, so in practice it fills the same role as the standalone TShock `tshock/` directory. +- Published bundles start with a flat `plugins/` directory. During startup, the module loader may reshuffle modules into subfolders when dependency or core-module metadata says it should. +- If everything went well, you should see the shared listener bind, the configured worlds start, the launcher status output begin updating, and, under the default console I/O implementation, one dedicated console window appear for each world. + +### Bundled TShock Notes + +- The bundled TShock here is a migration for the UnifierTSL / OTAPI USP runtime. Its lower-level logic is reimplemented by prioritizing UTSL/USP-native runtime APIs, event surfaces, packet models, and similar built-in capabilities, without maintaining an extra compatibility layer, while still aiming to keep the behavior and operator experience of TShock's higher-level features as close to upstream TShock as possible within a multi-world, single-process runtime model. +- This port is maintained to keep tracking upstream TShock. You can inspect the current migration baseline directly in `src/Plugins/TShockAPI/TShockAPI.csproj`, especially `MainlineSyncBranch`, `MainlineSyncCommit`, and `MainlineVersion`. +- Launcher settings stay in `config/config.json`, while the bundled TShock uses its own config-and-data root under `config/TShockAPI/`, separate from the launcher root config. This is also where other TShock runtime files live, such as `tshock.sqlite` when SQLite is enabled, so this directory effectively plays the same role as the standalone TShock `tshock/` folder. +- `config/TShockAPI/config.json` holds global TShock defaults, while `config/TShockAPI/config.override.json` stores per-server override patches keyed by configured server name, for example `"S1": { "MaxSlots": 16 }`. `config/TShockAPI/sscconfig.json` remains a separate file for SSC settings. +- Because the runtime hosts multiple worlds at once, some TShock data access that is usually implicit in a single-world flow becomes explicit here; for example, warp-related code paths resolve entries with an explicit `worldId` instead of only relying on the current global world state. +- Editing `config.json` or `config.override.json` externally updates the watched config handles and reapplies runtime TShock server settings. `/reload` still matters because it additionally refreshes permissions, regions, bans, whitelist-backed state, and the classic TShock reload flow. Some changes still require a restart. +- Finally, thanks to the TShock project and its contributors for the functionality, design work, and ecosystem this migration builds upon. + --- @@ -533,6 +555,8 @@ This table reflects the currently maintained/documented packaging targets, not e |:--|:--| | Developer Overview | [docs/dev-overview.md](./docs/dev-overview.md) | | Plugin Development Guide | [docs/dev-plugin.md](./docs/dev-plugin.md) | +| Branch Workflow Guide | [docs/branch-setup-guide.md](./docs/branch-setup-guide.md) | +| Branch Workflow Quick Reference | [docs/branch-strategy-quick-reference.md](./docs/branch-strategy-quick-reference.md) | | OTAPI Unified Server Process | [GitHub](https://github.com/CedaryCat/OTAPI.UnifiedServerProcess) | | Upstream TShock | [GitHub](https://github.com/Pryaxis/TShock) | | DeepWiki AI Analysis | [deepwiki.com](https://deepwiki.com/CedaryCat/UnifierTSL) *(reference only)* | @@ -542,6 +566,3 @@ This table reflects the currently maintained/documented packaging targets, not e

Made with ❤️ by the UnifierTSL contributors · Licensed under GPL-3.0

- - - diff --git a/docs/README.zh-cn.md b/docs/README.zh-cn.md index f338526..beb2dac 100644 --- a/docs/README.zh-cn.md +++ b/docs/README.zh-cn.md @@ -1,4 +1,4 @@ -# UnifierTSL +# UnifierTSL > Languages: [English](../README.md) | [简体中文](./README.zh-cn.md) @@ -21,7 +21,7 @@

- 在一个启动器进程里运行多个 Terraria 世界,
保持世界级隔离,并基于 OTAPI USP 用插件和发布工具链持续扩展能力。
+ 在一个启动器里托管多个 Terraria 世界,
让每个世界在独立上下文里并行运行,并把路由、数据互通和插件扩展都留在同一个 OTAPI USP 运行时里处理。

--- @@ -51,15 +51,14 @@ UnifierTSL 把 [OTAPI Unified Server Process](https://github.com/CedaryCat/OTAPI.UnifiedServerProcess) 封装成可直接使用的运行时,让你在**一个启动器进程里托管多个 Terraria 世界**。 -启动器负责世界启停、玩家入服路由,并为每个世界上下文拉起独立控制台客户端,保证各世界 I/O 互不干扰。 -这些控制台会话现在通过 ANSI 安全的提示/状态协议工作,因此启动器与各世界控制台可以维护语义化 readline 状态、回放状态栏帧,并在重连后平滑恢复,而不只是简单的纯文本管道。 -和经典单世界服务器、或基于数据包路由的多进程多世界方案相比,Unifier 把入服路由、世界切换和扩展钩子都放在同一个运行时平面里,不需要把关键逻辑拆到进程边界外。 +在传统的多进程多世界架构中,构建彼此协作的世界集群通常意味着额外的跨进程路由、状态同步和序列化设计。玩家在实例间迁移往往依赖数据包中转和额外信道;当需要跨世界共享插件附加数据、临时状态或运行时对象时,也常常要把原本进程内可以直接处理的问题改写成协议和同步流程。 + +相比将这些协调逻辑放到进程边界之外的方案,Unifier 基于 OTAPI USP 把入服路由、世界切换和扩展钩子收敛在同一个运行时平面内,在设计之初就将世界间协调作为一等公民来实现。启动器负责统一管理多世界生命周期,让每个世界在各自的 `ServerContext` 中独立并行运行,并为每个世界切分出独立的控制台以保证 I/O 隔离。 `UnifiedServerCoordinator` 负责总体协调,`UnifierApi.EventHub` 传递事件流,`PluginHost.PluginOrchestrator` 负责插件宿主编排。 -这种共享连接与状态平面的方式,既方便统一运维和跨世界联动,也保留了策略化路由与转服钩子,方便按世界做兜底策略。 +这种共享监听入口与协调平面的方式,减少了跨进程中转带来的额外开销与复杂度,既方便建立跨世界联动、数据互通和统一运维,也保留了足够的路由控制空间,用于定义默认入服目标并接管后续的世界切换流程。 -如果继续把这套模型往前推,你可以做出更偏玩法的形态:完全互通的多实例世界集群、按需加载/卸载区域分片的弹性世界,或为单个玩家定制逻辑和资源预算的私人世界。 -这些是可达方向,不是开箱即用的默认能力。 -这类较重实现不一定会放进启动器核心,但后续可以期待在 `plugins/` 里陆续补上对应的可用示例插件。 +从玩家视角看,它依然像一个普通的 Terraria 服务器入口:客户端只需要连到同一个监听端口,随后由 `UnifiedServerCoordinator` 在同一进程内把连接路由到目标世界;如果继续把这套模型往前推,你可以做出更偏玩法的形态:完全互通的多实例世界集群、按需加载/卸载区域分片的弹性世界,或为单个玩家定制逻辑和资源预算的私人世界。 +这些是可达方向,尽管启动器目前并未直接提供这些开箱即用的默认能力;而这类较重实现也未必会放进启动器核心本体,但你仍可以期待后续在 `plugins/` 下逐步补上的可用示例插件。 --- @@ -75,7 +74,7 @@ UnifierTSL 把 [OTAPI Unified Server Process](https://github.com/CedaryCat/OTAPI | 📦 **可回收模块上下文** | `ModuleLoadContext` 提供可卸载插件域,并支持分阶段依赖处理 | | 📝 **统一日志管线** | `UnifierApi.LogCore` 支持自定义过滤器、写入器与元数据注入 | | 🛡 **内置 TShock 移植基线** | 内置适配 USP 的 TShock 基线,开箱可用 | -| 💻 **上下文级控制台隔离** | 通过命名管道协议为每个世界提供 ANSI 安全日志、语义化 readline 提示与实时状态栏 | +| 💻 **上下文级控制台隔离** | 默认为每个世界实例提供独立、自动重连的控制台窗口 IO,以及语义化 readline 提示与实时状态栏 | | 🚀 **按 RID 发布** | Publisher 生成可复现、面向目标运行时的目录结构 | --- @@ -124,7 +123,7 @@ UnifierTSL 把 [OTAPI Unified Server Process](https://github.com/CedaryCat/OTAPI Architecture flow

-运行时实际启动顺序如下: +如果你想先看真实启动顺序,可以直接从这里开始: 1. `Program.Main` 初始化程序集解析器,应用启动前 CLI 语言覆盖,并输出运行时版本信息。 2. `Initializer.Initialize()` 准备 Terraria/USP 运行时状态,加载核心钩子(`UnifiedNetworkPatcher`、`UnifiedServerCoordinator`、`ServerContext` 初始化)。 @@ -148,6 +147,8 @@ UnifierTSL 把 [OTAPI Unified Server Process](https://github.com/CedaryCat/OTAPI ### 角色入口 +如果你已经知道自己是来干什么的,可以直接从对应入口跳: + | 角色 | 从这里开始 | 原因 | |:--|:--|:--| | 🖥 服主/运维 | [快速开始 ↓](#quick-start) | 用最少配置把多世界宿主先跑起来 | @@ -158,6 +159,8 @@ UnifierTSL 把 [OTAPI Unified Server Process](https://github.com/CedaryCat/OTAPI ## 🚀 快速开始 +如果你的目标很简单,就是“先把启动器跑起来,看着世界上线”,那就从这里开始。 + ### 前置要求 按你的使用方式准备对应依赖: @@ -169,6 +172,8 @@ UnifierTSL 把 [OTAPI Unified Server Process](https://github.com/CedaryCat/OTAPI ### 方案 A:使用发布包 +如果你只是想先用起来,这是最短路径。 + **1.** 从 [GitHub Releases](https://github.com/CedaryCat/UnifierTSL/releases) 下载与你平台匹配的发布资产: | 平台 | 文件模式 | @@ -209,7 +214,7 @@ chmod +x UnifierTSL ### 方案 B:从源码运行 -如果你要本地调试、接 CI,或产出自定义发布包,走这个方式。 +如果你要本地调试、接 CI,或者自己控制 Publisher 产物,就走这个方式。 **1.** 克隆并还原依赖: @@ -253,6 +258,23 @@ dotnet run --project src/UnifierTSL/UnifierTSL.csproj -- \ 3. 随后把启动项目切换为 `UnifierTSL`,选择 `Executable` 启动配置并开始调试。 4. 该配置会直接从 `utsl-publish` 运行发布后的启动器,并对该已发布程序附加调试。 +### 首次启动后会发生什么 + +- 第一次成功启动后,`config/config.json` 会自动生成,并保存当前生效的启动器启动快照。不过对你这一次启动来说,CLI 参数仍然优先。 +- 插件配置统一落在 `config//` 下。对内置 TShock 来说,配置根目录是 `config/TShockAPI/`;这同时也是其他 TShock 相关运行时文件的保存位置,例如启用 SQLite 时的 `tshock.sqlite` 也会放在这里,所以实际用起来它基本就等同于原版独立 TShock 程序目录下的 `tshock/` 文件夹。 +- 发布产物一开始是平铺的 `plugins/` 目录。启动过程中如果模块声明了核心模块或依赖元数据,加载器会按需要把它们重组到子目录里。 +- 如果一切正常,你会看到共享监听端口绑定成功、目标世界启动、启动器状态输出开始刷新,并且在默认控制台 IO 实现下,每个世界都会弹出自己的独立控制台窗口。 + +### 内置 TShock 说明 + +- 这里内置的 TShock 是面向 UnifierTSL / OTAPI USP 运行时的移植实现。底层会优先使用 UTSL/USP 原生提供的运行时接口、事件系统、数据包模型等通用能力来重实现相关逻辑,不会额外维持一套兼容层,但仍会尽力让 TShock 上层功能的行为与使用体验保持和原来一致,并适配多世界同进程运行模型。 +- 这个移植会持续跟随上游 TShock 的进度进行迁移更新。当前跟踪的移植基线可以直接在 `src/Plugins/TShockAPI/TShockAPI.csproj` 里查看,例如 `MainlineSyncBranch`、`MainlineSyncCommit` 和 `MainlineVersion`。 +- 启动器设置固定在 `config/config.json`,而内置 TShock 使用 `config/TShockAPI/` 下的独立配置和数据目录,不和启动器根配置混用;这也同时是其他 TShock 相关运行时文件的保存位置,例如启用 SQLite 时的 `tshock.sqlite` 也会放在这里,所以这个目录基本就相当于原版独立 TShock 程序目录下的 `tshock/` 文件夹。 +- `config/TShockAPI/config.json` 保存全局默认值,`config/TShockAPI/config.override.json` 以已配置的服务器名为键保存分服覆盖补丁,例如 `"S1": { "MaxSlots": 16 }`;`config/TShockAPI/sscconfig.json` 仍然独立负责 SSC 设置。 +- 由于运行时会同时承载多个世界,一些在原版单世界流程里通常依赖“当前世界”隐式决定的数据访问,在这里会改成显式带上 world 上下文;例如 warp 相关代码逻辑在查找或修改条目时会显式使用 `worldId`。 +- 直接编辑 `config.json` 或 `config.override.json` 会触发配置句柄监听,并重新应用运行中的 TShock 服务器设置;`/reload` 仍然有意义,因为它还会额外刷新权限、区域、封禁、白名单等状态,并走 TShock 传统 reload 流程。部分改动依旧需要重启。 +- 最后,也感谢 TShock 项目及其贡献者长期积累下来的功能、设计和社区生态;这个移植建立在这些工作的基础之上。 + --- @@ -533,6 +555,8 @@ dotnet run --project src/UnifierTSL.Publisher/UnifierTSL.Publisher.csproj -- \ |:--|:--| | 开发者总览 | [docs/dev-overview.zh-cn.md](./dev-overview.zh-cn.md) | | 插件开发指南 | [docs/dev-plugin.zh-cn.md](./dev-plugin.zh-cn.md) | +| 分支工作流指南 | [docs/branch-setup-guide.zh-cn.md](./branch-setup-guide.zh-cn.md) | +| 分支工作流速查 | [docs/branch-strategy-quick-reference.zh-cn.md](./branch-strategy-quick-reference.zh-cn.md) | | OTAPI Unified Server Process | [GitHub](https://github.com/CedaryCat/OTAPI.UnifiedServerProcess) | | 上游 TShock | [GitHub](https://github.com/Pryaxis/TShock) | | DeepWiki AI 分析 | [deepwiki.com](https://deepwiki.com/CedaryCat/UnifierTSL) *(仅供参考)* | @@ -542,6 +566,3 @@ dotnet run --project src/UnifierTSL.Publisher/UnifierTSL.Publisher.csproj -- \

Made with ❤️ by the UnifierTSL contributors · Licensed under GPL-3.0

- - - diff --git a/docs/assets/readme/hero.svg b/docs/assets/readme/hero.svg index fc87f81..54a956e 100644 --- a/docs/assets/readme/hero.svg +++ b/docs/assets/readme/hero.svg @@ -21,12 +21,12 @@ - + - UNIFIED TERRARIA SERVER LAUNCHER + UNIFIED TERRARIA SERVER LAUNCHER UnifierTSL - Multi-world orchestration on OTAPI Unified Server Process + Multi-world orchestration on OTAPI Unified Server Process diff --git a/docs/assets/readme/quick-glance.svg b/docs/assets/readme/quick-glance.svg index 6b54b4a..b9a986f 100644 --- a/docs/assets/readme/quick-glance.svg +++ b/docs/assets/readme/quick-glance.svg @@ -1,13 +1,13 @@ - + - + - + Quick Overview @@ -15,7 +15,7 @@ - + 🖥 Multi-World Host @@ -28,7 +28,7 @@ - + 🔌 Plugin Runtime @@ -41,7 +41,7 @@ - + 📦 Publisher Tooling @@ -54,7 +54,7 @@ - + 🛡 TShock Port diff --git a/docs/branch-setup-guide.md b/docs/branch-setup-guide.md index 12acdde..8d7fb80 100644 --- a/docs/branch-setup-guide.md +++ b/docs/branch-setup-guide.md @@ -1,224 +1,91 @@ -# Branch Setup Guide +# Branch Workflow Guide -This document provides instructions for setting up the three-branch workflow strategy for UnifierTSL. +> Languages: [English](./branch-setup-guide.md) | [简体中文](./branch-setup-guide.zh-cn.md) -## Overview +## Summary -The repository uses a three-branch strategy: -- **main**: Production branch, contains stable releases -- **develop**: Development branch, integration point for new features -- **documentation**: Documentation branch, for documentation updates +UnifierTSL uses one daily integration branch and one stable promotion branch: -## Initial Setup +- `develop` receives normal code and docs changes. +- `main` only receives stable promotions from `develop`. +- `release/` is cut from `main` and is the branch family used to execute GitHub releases. -### 1. Create Required Branches +Official docs use `release/` as the branch name. CI still accepts `releases/*` as a legacy compatibility alias, but new branches should use `release/*`. -Run the following commands to create the `develop` and `documentation` branches: +## Official Branch Roles -```bash -# Create develop branch from main -git checkout main -git pull origin main -git checkout -b develop -git push -u origin develop - -# Create documentation branch from main -git checkout main -git checkout -b documentation -git push -u origin documentation - -# Return to main -git checkout main -``` - -### 2. Configure Branch Protection Rules (Recommended) - -On GitHub, configure branch protection for `main`: - -1. Go to: Settings → Branches → Add branch protection rule -2. Branch name pattern: `main` -3. Enable the following: - - ✅ Require a pull request before merging - - ✅ Require approvals (suggested: 1) - - ✅ Dismiss stale pull request approvals when new commits are pushed - - ✅ Require status checks to pass before merging - - Add required check: `Build (linux-x64)` - - Add required check: `Build (win-x64)` - - ✅ Require conversation resolution before merging - - ✅ Do not allow bypassing the above settings - -Repeat for `develop` branch with similar settings. - -### 3. Set Default Branch - -Keep `main` as the default branch for the repository. - -## Workflow Usage - -### Feature Development - -```bash -# Create a feature branch from develop -git checkout develop -git pull origin develop -git checkout -b feature/my-new-feature - -# Make changes and commit -git add . -git commit -m "Add new feature" - -# Push feature branch -git push -u origin feature/my-new-feature - -# Create PR to develop on GitHub -``` - -### Bug Fixes - -```bash -# Create a bugfix branch from develop -git checkout develop -git pull origin develop -git checkout -b bugfix/fix-issue-123 - -# Make changes and commit -git add . -git commit -m "Fix issue #123" - -# Push and create PR to develop -git push -u origin bugfix/fix-issue-123 -``` - -### Documentation Updates - -```bash -# Create a docs branch from documentation -git checkout documentation -git pull origin documentation -git checkout -b docs/update-readme - -# Make changes and commit -git add . -git commit -m "Update README documentation" - -# Push and create PR to documentation -git push -u origin docs/update-readme -``` +| Branch | Role | Notes | +|:--|:--|:--| +| `develop` | Daily integration branch | Default target for normal PRs, including docs-only updates | +| `main` | Stable promotion branch | Updated when the current `develop` state is considered stable | +| `release/` | Release execution branch | Cut from `main`; pushes publish alpha prereleases, manual dispatch creates RC or stable releases | -### Hotfix (Emergency Production Fix) +Optional short-lived working branches such as `feature/*`, `bugfix/*`, and `doc/*` are supported as convenience branches. They are not separate long-lived lanes and should merge back into `develop`. -```bash -# Create hotfix branch from main -git checkout main -git pull origin main -git checkout -b hotfix/critical-bug +## Local Setup -# Make changes and commit -git add . -git commit -m "Fix critical production bug" +1. Track `main` and `develop` locally: -# Push and create PR to main -git push -u origin hotfix/critical-bug + ```bash + git fetch origin + git checkout main + git pull --ff-only origin main + git checkout develop + git pull --ff-only origin develop + ``` -# After merging to main, merge back to develop -git checkout develop -git merge main -git push origin develop -``` +2. Keep `main` as the default branch on GitHub. +3. Protect `main` and `develop` with PR-based merges and required checks if the repository settings allow it. -### Release Process +## Day-to-Day Development -When ready to release: +Base regular work on `develop`. That includes runtime code, docs, and workflow updates. ```bash -# Ensure develop is up to date git checkout develop -git pull origin develop - -# Create PR from develop to main on GitHub -# Title: "Release v1.x.x" -# After approval and merge, GitHub Actions will: -# 1. Build all platforms -# 2. Create version tags -# 3. Generate changelog -# 4. Publish GitHub Release with artifacts +git pull --ff-only origin develop +git checkout -b feature/my-change +# work, commit, push +git push -u origin feature/my-change ``` -## Version Management - -Versions are automatically managed by GitVersion: - -- **main**: Patch increments (1.0.0 → 1.0.1) -- **develop**: Minor increments with beta tag (1.1.0-beta.1 → 1.2.0-beta.1) -- **feature/***: Alpha versions (1.1.0-alpha.feature-name.1) -- **documentation**: Docs versions (1.0.0-docs.1) -- **hotfix/***: Patch increments +Open the PR against `develop`. For small repos or direct-maintainer work, committing directly to `develop` is also fine if that already matches the repository norm. -### Manual Version Control +## Promote a Stable Snapshot -Use commit messages to control version bumps: +When `develop` reaches a stable state, open a PR from `develop` to `main`. -```bash -# For a major version bump (breaking change) -git commit -m "Refactor API +semver: major" - -# For a minor version bump (new feature) -git commit -m "Add user authentication +semver: minor" - -# For a patch version bump (bug fix) -git commit -m "Fix login issue +semver: patch" +```text +develop -> main ``` -## CI/CD Behavior - -### When pushing to `develop`: -- ✅ Runs full build for all platforms -- ✅ Uploads artifacts to GitHub Actions -- ✅ Increments develop version -- ❌ Does NOT create a GitHub Release - -### When pushing to `main`: -- ✅ Runs full build for all platforms -- ✅ Uploads artifacts to GitHub Actions -- ⚠️ Creates GitHub Release ONLY if merge from develop/hotfix -- ✅ Increments main version - -### When pushing to `documentation`: -- ✅ Runs lightweight documentation check -- ❌ Does NOT build code -- ❌ Does NOT create artifacts -- ✅ Increments documentation version +`main` should stay reviewable and releasable. Do not use it as the normal branch for day-to-day iteration. -### Pull Requests: -- ✅ Builds code to verify it compiles -- ✅ Shows version that would be generated -- ❌ Does NOT create artifacts or releases - -## Troubleshooting - -### GitVersion not calculating version correctly - -Ensure your repository has full history: -```bash -git fetch --unshallow -``` +## Execute a Release -### Branch not triggering workflow +1. Start from the current stable `main`: -Check that: -1. Branch name matches the workflow triggers -2. `.github/workflows/build.yaml` is present in the branch -3. GitHub Actions is enabled for the repository + ```bash + git checkout main + git pull --ff-only origin main + git checkout -b release/0.2.1 + git push -u origin release/0.2.1 + ``` -### Release not being created +2. If `main` receives late stable fixes during release prep, refresh the release branch from `main` before continuing. +3. Pushes to `release/` run the build matrix and automatically publish the next alpha prerelease. +4. When you are ready to publish an RC or stable build, open GitHub Actions and run `Build and Release` on the same `release/` branch: + - `release_channel=rc` creates the next `vX.Y.Z-rc.N` GitHub release. + - `release_channel=stable` creates `vX.Y.Z` unless you provide an explicit `stable_tag`. +5. After the release line is complete, keep daily development moving on `develop`; the next release branch should be cut from a newer `main`. -Verify: -1. Merge was from `develop` to `main` -2. Commit message contains "Merge" and "develop" -3. Repository has `GITHUB_TOKEN` permissions for releases +## CI and Version Notes -## Reference +| Event | Result | +|:--|:--| +| Docs-only push/PR to `main`, `develop`, or `release/*` | `docs-check.yaml` runs | +| Non-doc push/PR to `main`, `develop`, or `release/*` | `build.yaml` runs and uploads artifacts | +| Push to `release/*` | Build runs, then the alpha prerelease job creates a GitHub prerelease | +| Manual `workflow_dispatch` on `release/*` | Builds run, then Actions creates an RC or stable GitHub release | -- [GitVersion Documentation](https://gitversion.net/docs/) -- [GitHub Actions Documentation](https://docs.github.com/en/actions) -- [Branch Strategy Quick Reference](./branch-strategy-quick-reference.md) +GitVersion still understands optional short-lived branch families such as `feature/*`, `bugfix/*`, and `hotfix/*`, but the repository's documented default flow is still `develop -> main -> release/`. diff --git a/docs/branch-setup-guide.zh-cn.md b/docs/branch-setup-guide.zh-cn.md new file mode 100644 index 0000000..e77cfbc --- /dev/null +++ b/docs/branch-setup-guide.zh-cn.md @@ -0,0 +1,91 @@ +# 分支工作流指南 + +> Languages: [English](./branch-setup-guide.md) | [简体中文](./branch-setup-guide.zh-cn.md) + +## 摘要 + +UnifierTSL 当前使用一条日常集成分支和一条稳定晋升分支: + +- `develop` 承接常规代码与文档更新。 +- `main` 只承接来自 `develop` 的稳定晋升。 +- `release/` 从 `main` 切出,用于执行 GitHub 发版。 + +文档中的标准写法统一使用 `release/`。CI 仍兼容历史上的 `releases/*` 前缀,但新分支应统一使用 `release/*`。 + +## 官方分支角色 + +| 分支 | 角色 | 说明 | +|:--|:--|:--| +| `develop` | 日常集成分支 | 常规 PR 的默认目标,包括仅文档改动 | +| `main` | 稳定晋升分支 | 当 `develop` 达到稳定状态时接收晋升 | +| `release/` | 发版执行分支 | 从 `main` 切出;推送会生成 alpha 预发布,手动触发可发布 RC 或 stable | + +`feature/*`、`bugfix/*`、`doc/*` 这类短生命周期工作分支仍可作为便利分支使用,但它们不是独立的长期泳道,最终都应回到 `develop`。 + +## 本地准备 + +1. 在本地跟踪 `main` 和 `develop`: + + ```bash + git fetch origin + git checkout main + git pull --ff-only origin main + git checkout develop + git pull --ff-only origin develop + ``` + +2. GitHub 默认分支保持为 `main`。 +3. 如果仓库设置允许,建议给 `main` 和 `develop` 打开基于 PR 的合并和必需检查。 + +## 日常开发 + +常规工作统一基于 `develop`,包括运行时代码、文档和工作流更新。 + +```bash +git checkout develop +git pull --ff-only origin develop +git checkout -b feature/my-change +# work, commit, push +git push -u origin feature/my-change +``` + +PR 目标统一指向 `develop`。如果仓库维护方式本来就允许直接提交到 `develop`,小团队场景下继续保持也可以。 + +## 晋升稳定快照 + +当 `develop` 到达可稳定发布的状态时,从 `develop` 向 `main` 发起 PR: + +```text +develop -> main +``` + +`main` 应始终保持可评审、可发版,不应作为日常迭代分支使用。 + +## 执行发版 + +1. 从当前稳定的 `main` 切出发版分支: + + ```bash + git checkout main + git pull --ff-only origin main + git checkout -b release/0.2.1 + git push -u origin release/0.2.1 + ``` + +2. 如果发版准备期间 `main` 又接收了新的稳定修复,先用最新的 `main` 刷新该发版分支,再继续发版流程。 +3. 每次向 `release/` 推送,都会跑完整 build matrix,并自动创建下一个 alpha 预发布。 +4. 当你准备发布 RC 或正式版时,在 GitHub Actions 中对同一个 `release/` 分支手动运行 `Build and Release`: + - `release_channel=rc` 会创建下一个 `vX.Y.Z-rc.N` GitHub Release。 + - `release_channel=stable` 会创建 `vX.Y.Z`,除非你显式提供 `stable_tag`。 +5. 当前发版线结束后,日常开发继续留在 `develop`;下一条发版线再从更新后的 `main` 重新切出。 + +## CI 与版本说明 + +| 事件 | 结果 | +|:--|:--| +| 向 `main`、`develop`、`release/*` 提交或发起仅文档变更 PR | 运行 `docs-check.yaml` | +| 向 `main`、`develop`、`release/*` 提交或发起非文档变更 PR | 运行 `build.yaml` 并上传构建产物 | +| 向 `release/*` 推送 | 先构建,再自动创建 alpha GitHub 预发布 | +| 在 `release/*` 上手动触发 `workflow_dispatch` | 构建后创建 RC 或 stable GitHub Release | + +GitVersion 仍然支持 `feature/*`、`bugfix/*`、`hotfix/*` 这类可选短生命周期分支,但仓库文档里的默认主流程固定为 `develop -> main -> release/`。 diff --git a/docs/branch-strategy-quick-reference.md b/docs/branch-strategy-quick-reference.md index e17a3be..698d3c6 100644 --- a/docs/branch-strategy-quick-reference.md +++ b/docs/branch-strategy-quick-reference.md @@ -1,110 +1,62 @@ -# Branch Strategy Quick Reference +# Branch Workflow Quick Reference -## Branch Overview +> Languages: [English](./branch-strategy-quick-reference.md) | [简体中文](./branch-strategy-quick-reference.zh-cn.md) -| Branch | Purpose | Version Pattern | Auto Release | -|--------|---------|-----------------|--------------| -| `main` | Production | 1.0.0 | ✅ Yes (from develop/hotfix) | -| `develop` | Development | 1.1.0-beta.1 | ❌ No | -| `documentation` | Docs only | 1.0.0-docs.1 | ❌ No | -| `feature/*` | New features | 1.1.0-alpha.name.1 | ❌ No | -| `bugfix/*` | Bug fixes | 1.1.0-bugfix.name.1 | ❌ No | -| `hotfix/*` | Emergency fixes | 1.0.1-hotfix.1 | ✅ Yes (to main) | +## Branch Roles -## Common Commands +| Branch | Use it for | Default target | +|:--|:--|:--| +| `develop` | Daily integration for code and docs | Normal PR base | +| `main` | Stable promotions only | Receives `develop` when stable | +| `release/` | Release execution from `main` | GitHub release work | +| `feature/*`, `bugfix/*`, `doc/*` | Optional short-lived working branches | Merge back to `develop` | -### Start New Feature -```bash -git checkout develop && git pull -git checkout -b feature/my-feature -# work, commit, push -# PR to develop -``` +Official docs use `release/`. CI still accepts legacy `releases/*`, but do not create new branches with that prefix unless you need compatibility with older automation. -### Fix a Bug -```bash -git checkout develop && git pull -git checkout -b bugfix/fix-issue-123 -# work, commit, push -# PR to develop -``` +## Common Commands -### Update Documentation -```bash -git checkout documentation && git pull -git checkout -b docs/update-readme -# work, commit, push -# PR to documentation -``` +### Start normal work -### Emergency Hotfix ```bash -git checkout main && git pull -git checkout -b hotfix/critical-bug -# work, commit, push -# PR to main -# After merge, sync to develop: -git checkout develop && git merge main && git push +git checkout develop +git pull --ff-only origin develop +git checkout -b feature/my-change +git push -u origin feature/my-change ``` -### Create Release -```bash -# On GitHub: Create PR from develop to main -# Title: "Release v1.x.x" -# After merge → Auto-creates GitHub Release +### Promote a stable snapshot + +```text +develop -> main ``` -## Version Control via Commits +### Cut a release branch ```bash -# Major version bump (breaking change) -git commit -m "Refactor API +semver: major" - -# Minor version bump (new feature) -git commit -m "Add authentication +semver: minor" - -# Patch version bump (bug fix) -git commit -m "Fix login bug +semver: patch" +git checkout main +git pull --ff-only origin main +git checkout -b release/0.2.1 +git push -u origin release/0.2.1 ``` -## CI/CD Triggers - -| Action | Builds Code | Creates Artifacts | Creates Release | -|--------|-------------|-------------------|-----------------| -| Push to develop | ✅ | ✅ | ❌ | -| Push to main (direct) | ✅ | ✅ | ❌ | -| develop → main | ✅ | ✅ | ✅ | -| hotfix → main | ✅ | ✅ | ✅ | -| documentation → main | ❌ | ❌ | ❌ | -| PR to develop | ✅ | ✅ | ❌ | -| PR to main | ✅ | ✅ | ❌ | -| PR to documentation | ❌ | ❌ | ❌ | - -## Build Platforms +## Release Actions -All builds create artifacts for: -- Windows x64 -- macOS x64 -- Linux x64 -- Linux ARM64 -- Linux ARM - -## Quick Troubleshooting - -### "GitVersion not found" -```bash -git fetch --unshallow -``` +1. Push to `release/` to produce the next alpha prerelease automatically. +2. Open GitHub Actions, choose `Build and Release`, select the same `release/` branch, then run: + - `release_channel=rc` for the next RC release. + - `release_channel=stable` for the stable GitHub release. -### "Workflow not triggering" -Check branch name matches: `main`, `develop`, or `documentation` +## CI Trigger Summary -### "Release not created after merge" -Verify commit message contains "Merge" and "develop" or "hotfix" +| Change | Workflow result | +|:--|:--| +| Docs-only push/PR to `main`, `develop`, or `release/*` | `docs-check.yaml` | +| Non-doc push/PR to `main`, `develop`, or `release/*` | `build.yaml` + artifacts | +| Push to `release/*` | `build.yaml` + alpha prerelease | +| Manual `workflow_dispatch` on `release/*` | RC or stable GitHub release | -## File Locations +## Versioning Notes -- GitVersion config: `GitVersion.yml` -- Workflow: `.github/workflows/build.yaml` -- Full docs: `docs/branch-setup-guide.md` -- Detailed setup guide: `docs/branch-setup-guide.md` +- `develop` builds use the `beta` label. +- `release/*` builds use the `rc` release line and can also emit alpha prereleases on push. +- `main` remains the stable promotion branch. diff --git a/docs/branch-strategy-quick-reference.zh-cn.md b/docs/branch-strategy-quick-reference.zh-cn.md new file mode 100644 index 0000000..0a57031 --- /dev/null +++ b/docs/branch-strategy-quick-reference.zh-cn.md @@ -0,0 +1,62 @@ +# 分支工作流速查 + +> Languages: [English](./branch-strategy-quick-reference.md) | [简体中文](./branch-strategy-quick-reference.zh-cn.md) + +## 分支角色 + +| 分支 | 用途 | 默认目标 | +|:--|:--|:--| +| `develop` | 代码与文档的日常集成 | 常规 PR 基线 | +| `main` | 仅承接稳定晋升 | 在稳定后接收 `develop` | +| `release/` | 从 `main` 切出的发版执行分支 | GitHub 发版工作 | +| `feature/*`、`bugfix/*`、`doc/*` | 可选的短生命周期工作分支 | 最终回到 `develop` | + +文档中的标准写法统一使用 `release/`。CI 仍兼容历史上的 `releases/*`,但除非你需要兼容旧自动化,否则不要再创建这种前缀的新分支。 + +## 常用命令 + +### 开始日常工作 + +```bash +git checkout develop +git pull --ff-only origin develop +git checkout -b feature/my-change +git push -u origin feature/my-change +``` + +### 晋升稳定快照 + +```text +develop -> main +``` + +### 切发版分支 + +```bash +git checkout main +git pull --ff-only origin main +git checkout -b release/0.2.1 +git push -u origin release/0.2.1 +``` + +## 发版动作 + +1. 向 `release/` 推送,会自动产出下一个 alpha 预发布。 +2. 打开 GitHub Actions,选择 `Build and Release`,在同一个 `release/` 分支上手动运行: + - `release_channel=rc` 发布下一个 RC。 + - `release_channel=stable` 发布正式版 GitHub Release。 + +## CI 触发速览 + +| 改动类型 | 工作流结果 | +|:--|:--| +| 向 `main`、`develop`、`release/*` 推送或发起仅文档变更 PR | `docs-check.yaml` | +| 向 `main`、`develop`、`release/*` 推送或发起非文档变更 PR | `build.yaml` + 构建产物 | +| 向 `release/*` 推送 | `build.yaml` + alpha 预发布 | +| 在 `release/*` 上手动触发 `workflow_dispatch` | RC 或 stable GitHub Release | + +## 版本说明 + +- `develop` 构建使用 `beta` 标记。 +- `release/*` 走 `rc` 发版线,并且推送时还会生成 alpha 预发布。 +- `main` 保持为稳定晋升分支。