SkillAgentSearch skills...

UnifierTSL

Single-process multi-world Terraria server runtime built on OTAPI USP—an alternative to proxy stacks, with per-instance consoles, hot-reloadable plugins, and seamless in-process player routing service.

Install / Use

/learn @CedaryCat/UnifierTSL

README

UnifierTSL

Languages: English | 简体中文

<p align="center"> <img src="./docs/assets/readme/hero.svg" alt="UnifierTSL" width="100%"> </p> <p align="center"> <a href="#quick-start"><img alt="Quick Start" src="https://img.shields.io/badge/Quick_Start-blue?style=flat-square"></a> <a href="https://github.com/CedaryCat/UnifierTSL/releases"><img alt="Releases" src="https://img.shields.io/badge/Releases-green?style=flat-square&logo=github"></a> <a href="./docs/dev-plugin.md"><img alt="Plugin Guide" src="https://img.shields.io/badge/Plugin_Guide-orange?style=flat-square"></a> <a href="#architecture"><img alt="Architecture" src="https://img.shields.io/badge/Architecture-purple?style=flat-square"></a> </p> <p align="center"> <a href="https://github.com/CedaryCat/UnifierTSL/actions/workflows/build.yaml"><img alt="Build" src="https://img.shields.io/github/actions/workflow/status/CedaryCat/UnifierTSL/build.yaml?branch=main&label=build&style=flat-square"></a> <a href="https://github.com/CedaryCat/UnifierTSL/actions/workflows/docs-check.yaml"><img alt="Docs Check" src="https://img.shields.io/github/actions/workflow/status/CedaryCat/UnifierTSL/docs-check.yaml?label=docs&style=flat-square"></a> <a href="./src/UnifierTSL.slnx"><img alt=".NET 9.0" src="https://img.shields.io/badge/.NET-9.0-512BD4?style=flat-square&logo=dotnet&logoColor=white"></a> <a href="./LICENSE"><img alt="License: GPL-3.0" src="https://img.shields.io/badge/License-GPL--3.0-green?style=flat-square"></a> </p> <p align="center"> <em>Run multiple Terraria worlds from one launcher,<br>keep each world in its own context, and handle routing, data sharing, and plugin-driven extension inside the same OTAPI USP runtime.</em> </p>
<p align="center"> <img src="./docs/assets/readme/quick-glance.svg" alt="Quick Overview" width="100%"> </p>

📑 Table of Contents


<a id="overview"></a>

📖 Overview

UnifierTSL wraps OTAPI Unified Server Process into a runtime you can run directly to host multiple Terraria worlds in one launcher process.

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. 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.

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, you can still expect usable example plugins to land under plugins/ over time.


<a id="core-capabilities"></a>

✨ Core Capabilities

| Feature | Description | |:--|:--| | 🖥 Multi-world coordination | Run and isolate multiple worlds in a single runtime process | | 🧱 Struct-based tile storage | World tiles use struct TileData instead of ITile for lower memory use and faster reads/writes | | 🔀 Live routing control | Set default join strategies and re-route players through coordinator events at runtime | | 🔌 Plugin hosting | Load .NET modules from plugins/ and handle config registration plus dependency extraction | | 📦 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 | 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 |


<a id="architecture-tradeoffs"></a>

⚖️ Multi-World Architecture Comparison

Here, proxy-based broadly refers to the common family of designs built around a front proxy, multiple independent backend server processes, packet-level relays or rewriting, and optional shared storage or control-plane components.

<details> <summary><strong>Deployment and Lifecycle</strong></summary>

| Dimension | UnifierTSL (single-process unified coordination) | Proxy-based (front proxy + multiple backend processes) | Stronger Fit | |:--|:--|:--|:--| | Failure isolation | Worlds share one host process; isolation between contexts exists at the thread/runtime-context level | Process-level isolation; one backend crash usually does not directly take down other backends or the proxy itself | Proxy-based | | Instance-level restart | World contexts can be started and stopped freely | A single backend can be restarted, replaced, or moved while the front entry point stays up | Depends on the operational goal | | Plugin hot reload | The runtime provides standard support; whether a plugin can hot reload depends on the plugin's own design, and players are usually unaffected | Backend plugins can be reloaded cleanly by restarting only the target backend instance, though that may require moving players to a temporary backend | Depends on the operational goal | | Horizontal elasticity | The core design targets multi-world coordination inside one host; instances can be created freely, but they still share one process resource pool | Naturally suited to cross-machine, cross-container, or cross-device scale-out | Proxy-based | | Existing plugin ecosystem reuse | Requires adaptation to the Unifier runtime model | Directly uses the existing plugin ecosystem | Proxy-based |

</details> <details> <summary><strong>Runtime Coordination and Transfer</strong></summary>

| Dimension | UnifierTSL (single-process unified coordination) | Proxy-based (front proxy + multiple backend processes) | Stronger Fit | |:--|:--|:--|:--| | World customizability | World contexts are fully customizable and can be changed dynamically at runtime | Depends on the backend implementation; in practice, most setups are relatively static after startup | UnifierTSL | | Server-side consistency | World existence, routing targets, and connection ownership are resolved directly inside one runtime, so the consistency surface is narrower | Depends on cross-process topology, registration, shared storage, or an external control plane, so the race surface is wider | UnifierTSL | | State awareness and switch orchestration | One coordinator can see source world, target world, and player connection state together, so fallback and recovery logic can be centralized | Target readiness, transfer failures, disconnect recovery, and rollback may require cross-process coordination | UnifierTSL | | Data transfer and entity migration | Temporary state, plugin-attached data, and runtime objects can be transferred or coordinated directly inside one runtime | State often has to be serialized, protocolized, or moved through shared databases or custom packets first | UnifierTSL | | Connection-state maintenance | One listener keeps ownership of the client connection throughout world switches | The proxy must maintain both client-side and backend-side connections and recover from failures on either side | UnifierTSL | | Cross-world plugin interoperability | Feels more like “one plugin working across many ServerContext instances,” with direct reuse of in-process events and APIs | Feels more like distributed-systems work, usually requiring message protocols, shared storage, or sync layers first | UnifierTSL |

</details> <details> <summary><strong>Operations and System Shape</strong></summary>

| Dimension | UnifierTSL (single-process unified coordination) | Proxy-based (front proxy + multiple backend processes) | Stronger Fit | |:--|:--|:--|:--| | Unified management cost | Entry point, world lifecycle, default join policy, and config application all live on one coordination plane | Management is usually split across the proxy,

Related Skills

View on GitHub
GitHub Stars8
CategoryDevelopment
Updated13d ago
Forks4

Languages

C#

Security Score

90/100

Audited on Mar 17, 2026

No findings