Files

367 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Live V8 Plugin + Plugin API 26 — What We Have, What Is Server-Side, What Is Still Possible
Detailed inventory of the **current workspace plugin** (V8 / Client Plugin SDK, `PLUGIN_API_VERSION 26`) versus what the same SDK still allows that we do **not** use yet.
> [!IMPORTANT]
> This is **not** the discarded TeamSpeak 3 commercial ClientLib/ServerLib product.
> Everything below is **retail TeamSpeak 3 Client + our DLL**.
---
## Table of contents
1. [One-sentence summary](#1-one-sentence-summary)
2. [Product and SDK identity](#2-product-and-sdk-identity)
3. [What the live plugin already does (full feature map)](#3-what-the-live-plugin-already-does-full-feature-map)
4. [What is already “server-side” today](#4-what-is-already-server-side-today)
5. [What is strictly client-side today](#5-what-is-strictly-client-side-today)
6. [APIs we already call (used subset of API 26)](#6-apis-we-already-call-used-subset-of-api-26)
7. [APIs available in API 26 that we do not use yet](#7-apis-available-in-api-26-that-we-do-not-use-yet)
8. [Realistic “send more to the server” options](#8-realistic-send-more-to-the-server-options)
9. [Hard limits — will never be Plugin-SDK server routing](#9-hard-limits--will-never-be-plugin-sdk-server-routing)
10. [Not implemented (product gaps)](#10-not-implemented-product-gaps)
11. [Recommended next steps](#11-recommended-next-steps)
---
## 1. One-sentence summary
The live plugin is a **TeamSpeak Client Plugin (API 26)** that reads Conan positions from a file, **relays them through the retail TeamSpeak server** as CEPOS plugin commands, lets each client **compute proximity locally**, and applies hearing via **PCM + 3D**. The retail server does **not** run our proximity math; it only relays commands and stores hub config in a channel description.
---
## 2. Product and SDK identity
| Item | Value in this workspace |
|---|---|
| Artifact | `conan_exiles.dll` loaded by retail TeamSpeak 3 |
| SDK | **Client Plugin SDK** (`sdk/README.md`) |
| API version | `PLUGIN_API_VERSION 26` in [`src/ts/entry/ts3_entry.c`](src/ts/entry/ts3_entry.c) |
| Headers | `sdk/include/ts3_functions.h` (`struct TS3Functions`) |
| Callbacks | `ts3plugin_*` exports in [`src/ts/entry/ts3_exports.h`](src/ts/entry/ts3_exports.h) |
| Not present | No `ts3client_*` / `ts3server_*` ServerLib/ClientLib product code |
---
## 3. What the live plugin already does (full feature map)
### 3.1 End-to-end data path
```text
Conan Exiles mod
-> writes Pos.txt (x, y, z, yaw, ...)
Plugin pos watcher (pos_file.c)
-> local position snapshot
CEPOS send (ts3_cepos.c)
-> sendPluginCommand("CEPOS:<base64>") ---via retail TS server---> all clients
CEPOS receive (onPluginCommandEvent)
-> player_table_put
Proximity recompute (callback thread)
-> distance, zones, voice mode, soundproof, reverb flags
-> publish lock-free snapshots
PCM (onEditPlaybackVoiceDataEvent)
-> gain / pan / lowpass / reverb on samples
3D (ts3_3d.c)
-> systemset3DListenerAttributes + channelset3DAttributes
Hub profile (ts3_server_profile + hub_parser)
-> read root channel description (server-admin policy)
Channel manage
-> hub <-> ingame auto move (requestClientMove)
```
### 3.2 Game / position input
| Piece | Location | Behavior |
|---|---|---|
| Position file | `src/core/mod_file/pos_file.c` | Watcher polls ~30 ms; reads local player pose |
| Path detect | `path_detect.c` | Finds Conan `Pos.txt` / saved path |
| CEPOS packet | `ts3_cepos.h` | Fixed **56-byte** packed struct, wire-compatible since V7 |
**CEPOS fields (`CeposPacket`):**
```text
float x, y, z // meters
float dirX, dirY, dirZ // look direction
float axisX,Y,Z // up vector
float voiceDistance // current mode range (meters)
char playerName[16]
```
Wire: `CEPOS:` + base64. Throttle: min interval `PLUGIN_POLL_INTERVAL_MS`, position epsilon ~0.08 m, voice-distance epsilon ~0.05 m, keepalive ~1 Hz.
### 3.3 Proximity and audio (client)
| Piece | Location | Behavior |
|---|---|---|
| Player table | `player_table.c` | Fixed table (cap 512), LRU eviction |
| Math | `proximity_math.c` | Distance → volume / mute |
| Zones | `zone_resolve.c` + hub zones | Soundproof boundaries, reverb zones, distance overrides |
| Voice modes | `voice_modes.c` | Whisper / Normal / Shout + hotkeys; distance in CEPOS |
| PCM mix | `ts3_proximity_audio.c` | `onEditPlaybackVoiceDataEvent`: gain, pan, filters |
| 3D | `ts3_3d.c` | Listener + per-client 3D; custom rolloff callback |
| Unmute | adapter | `requestUnmuteClientsTemporary` so PCM still arrives |
| Volume reset | adapter | `setClientVolumeModifier` in unmute path |
### 3.4 Hub / channels (uses TeamSpeak server as config + lobby)
| Piece | Location | Behavior |
|---|---|---|
| Hub settings parse | `hub_parser.c` | Pure parse of channel description text |
| Apply/cache | `ts3_server_profile.c` | Fetch description, apply to runtime |
| Channel move | `channel_manage.c` | Auto hub ↔ ingame with cooldown / flood protection |
| Nick anonymize | `nick_anonymize.c` | Optional random nick when ingame (hub flag) |
**Hub keys already parsed from root channel description** ([`hub_parser.h`](src/core/hub/hub_parser.h)):
**`[GLOBAL]`**
- `AudioMaxVolume`, `AudioMinDistance`
- `MinimumWisper` / `MaximumWisper` (legacy spelling)
- `MinimumNormal` / `MaximumNormal`
- `MinimumShout` / `MaximumShout`
- `ForceDistanceBasedMuting`
- `ForceAutomaticChanelSwitching` (legacy spelling)
- `NicknameRandomizer`
- `RealisticAudio`
- `FilterIntensity` / `hubAudioFilterIntensity` (parsed; **not fully wired into audio path** — known pitfall)
- `IngameChannelPassword`
**`[ZONES]` / per-zone**
- Quad corners `X1..Z4`, `GroundY` / `TopY`
- `SoundProof`, `Reverb`
- Distance overrides `Wisper` / `Normal` / `Shout`
- Optional volume / min-distance overrides
**`[RACE]`**
- Race name, `SteamID` lists, per-race whisper/normal/shout min/max, listen bonus
**`[DEFAULT_SETTINGS]`**
- First-connection default hotkeys / distances
### 3.5 UI / UX
| Piece | Behavior |
|---|---|
| F10 / Extras config | `showConfigInterface()` in `ui_main.c` (via dialog guard) |
| Overlay HUD | Voice mode / zone display |
| Hotkeys | Voice mode toggle |
| Presets | Voice distance presets UI |
| Chat/log helpers | print to chat / client log via adapter |
### 3.6 Threading (already enforced)
| Thread | Allowed | Forbidden |
|---|---|---|
| TS callback | All `TS3Functions`, CEDRAIN drain, CEPOS flush | Blocking work |
| Wakeup | Only `sendPluginCommand("CEDRAIN:1")` | Other TS API |
| PCM audio | Snapshot read + sample edit | TS API, locks |
| Pos watcher / UI | Flags + wakeup | Direct TS API |
### 3.7 Lifecycle callbacks implemented
From [`ts3_exports.h`](src/ts/entry/ts3_exports.h):
- Required: `name`, `version`, `apiVersion` (26), `author`, `description`, `setFunctionPointers`, `init`, `shutdown`, `registerPluginID`
- Config UI: `offersConfigure`, `configure`
- Events: `onConnectStatusChangeEvent`, `currentServerConnectionChanged`, `onPluginCommandEvent`, `onEditPlaybackVoiceDataEvent`, `onCustom3dRolloffCalculationClientEvent`, `onClientMoveEvent`, `onClientMoveMovedEvent`, `onChannelDescriptionUpdateEvent`, `onUpdateChannelEvent`, `onUpdateChannelEditedEvent`, `onTalkStatusChangeEvent`, `onHotkeyEvent`
---
## 4. What is already “server-side” today
Important: **“Server-side” here means “uses the retail TeamSpeak server”**, not “our code runs inside ts3server.”
| Mechanism | Where it lives | What the retail server does | What our plugin does |
|---|---|---|---|
| **CEPOS relay** | Plugin command | Relays `sendPluginCommand` to other clients | Build/parse CEPOS; store peers locally |
| **CEDRAIN** | Plugin command | Relays wakeup | Coalesce work onto callback thread |
| **Hub policy** | Root **channel description** | Stores admin text | Parse + apply ranges/zones/flags |
| **Channels** | Hub / ingame channels | Standard TS channel rules | Auto-move via `requestClientMove` |
| **Voice packets** | TS voice engine | Encode/transport/decode | Only edit playback after arrival |
```text
Server-admin writes hub config --> channel description on TS server
Plugin reads description --> policy (distances, zones, force flags)
Plugin A sends CEPOS --> TS server relays --> Plugin B/C/...
Each plugin computes proximity locally and mutes/attenuates PCM
```
**There is no server process of ours computing “A hears B.”**
---
## 5. What is strictly client-side today
- Distance / audible decision
- Soundproof / reverb application
- Voice-mode distance (after hub clamps)
- PCM gain / pan / filters
- 3D listener/speaker attributes
- Player table / recompute budgets
- Overlay HUD
- Local config (`g_config` / F10)
---
## 6. APIs we already call (used subset of API 26)
Through [`ts3_adapter.c`](src/ts/adapter/ts3_adapter.c) / wrappers:
| API | Purpose in V8 |
|---|---|
| `sendPluginCommand` | CEPOS + CEDRAIN |
| `requestUnmuteClientsTemporary` | Keep speakers unmuted for PCM hook |
| `setClientVolumeModifier` | Volume hygiene with unmute |
| `requestClientMove` | Hub ↔ ingame |
| `requestChannelDescription` / get description | Hub settings |
| Channel/client list + nickname getters | Channel manage / UI |
| `systemset3DSettings` | 3D global |
| `systemset3DListenerAttributes` | Listener pose |
| `channelset3DAttributes` | Per-speaker 3D |
| `printMessage` / `logMessage` | UX / diagnostics |
| set own nickname (self variables + flush) | Nick randomizer path |
---
## 7. APIs available in API 26 that we do not use yet
These exist in `sdk/include/ts3_functions.h` and are callable from a plugin (subject to **permissions** and server settings). None of them put Conan proximity **code** onto the retail server.
### 7.1 Strong candidates for “send/do more via TeamSpeak”
| API | What it could enable | Caveats |
|---|---|---|
| **More `sendPluginCommand` message types** | `CEAUTH`, `CEMODE`, richer state, versioned protocol | Still P2P via relay; spoofable; bandwidth |
| `requestClientSetWhisperList` | Client-requested whisper targets (admin overlay, special modes) | Not a proximity engine; whisper can disable normal channel talk; needs rights |
| `allowWhispersFrom` / whisper events | Accept whispered audio | Receiver allow-list UX |
| `setClientSelfVariableAsString` + `flushClientSelfUpdates` | Publish small self metadata (e.g. meta string) | Size limits; not a game backend; other clients must request/read |
| `requestClientVariables` | Refresh peer client variables | Still not positions unless we invent a convention |
| `requestSendPrivateTextMsg` / channel / server text | Discrete events, debug, light signaling | Noisy; not for 20 Hz positions |
| `requestMuteClients` / `requestUnmuteClients` | Persistent mute vs temporary | Heavy-handed; permissions; fights PCM design |
| `requestChannelSubscribe*` | Hear other channels | Lobby designs; not proximity |
| `requestClientPoke` | Attention / alerts | UX only |
| `requestClientKickFromChannel/Server` | Moderation helpers | Needs privileges; dangerous if abused |
| `requestConnectionInfo` | Latency/diagnostics | Ops/HUD |
### 7.2 Audio / device APIs we mostly skip
Playback/capture device enumeration, preprocessor config, wave-file playback, custom devices — possible for tools/FX, not for “server computes proximity.”
### 7.3 Channel management APIs unused
`requestChannelDelete`, `requestChannelMove`, temporary passwords, etc. — admin tooling only.
---
## 8. Realistic “send more to the server” options
Within **Plugin API 26 + retail TeamSpeak only**:
### Option A — Richer plugin-command protocol (recommended first)
Keep CEPOS; add versioned commands relayed by the TS server:
```text
CEPOS: position (existing)
CEMODE: voice mode edge events
CEZONE: zone enter/leave (optional)
CEAUTH: soft identity hint (still spoofable)
CEPING: stale detection
```
**Server role:** still only relay. **Benefit:** cleaner peer sync, less polling noise, extensibility.
### Option B — More hub policy on the TeamSpeak server (recommended)
Expand root channel description schema (versioned keys):
- Feature flags, fail-closed policy, radio defaults (if added later)
- Documented schema; clients remain readers only
**Server role:** stores authoritative **policy** (admin-written). **Benefit:** true “server owns rules” without custom backend.
### Option C — Whisper lists for special overlays (experiment)
Use `requestClientSetWhisperList` for admin/global overlays — **not** as the main proximity router.
### Option D — Hybrid external authority (only if you need central compute)
```text
Clients -> your Voice Authority (not TS ServerLib)
Authority -> audible set
Plugin still applies PCM/3D
TeamSpeak -> voice transport + optional CEPOS
```
This is **not** “TeamSpeak server computes”; it is your process. Fail closed if authority is down.
---
## 9. Hard limits — will never be Plugin-SDK server routing
| Desire | With API 26 + retail TS? |
|---|---|
| Proximity math inside `ts3server` | **No** |
| Guarantee D never receives A’s voice packets | **No** (only local mute/PCM; packets still delivered in-channel) |
| Replace TeamSpeak with custom ServerLib host | Abandoned product direction |
| Trust client position as anti-cheat truth | **No** without Conan dedicated-server feed |
V8’s “everyone gets packets; we silence locally” is the Plugin-SDK ceiling for proximity hearing.
---
## 10. Not implemented (product gaps)
| Feature | Status |
|---|---|
| Radio system | Not present |
| Server-authoritative audible sets | Not present |
| Strong auth (Steam ticket → permissions) | Not present (only hub SteamID race lists) |
| `hubAudioFilterIntensity` fully wired to PCM | Key parsed; audio path caveat remains |
| Commercial ServerLib custom app | Explicitly discarded |
---
## 11. Recommended next steps
1. **Freeze** current CEPOS + hub key inventory (this document).
2. Decide: **A-only** (better plugin commands + hub keys) vs **A + hybrid authority**.
3. Implement **one** additive change (Golden Rule): either one new plugin-command type **or** a small hub-schema extension.
4. Do **not** reopen ClientLib/ServerLib custom-app work.
---
## Quick reference: client vs server responsibilities (live V8)
```mermaid
flowchart LR
subgraph RetailTS [Retail TeamSpeak server]
Relay[Plugin-command relay]
Desc[Channel description store]
Voice[Voice packet transport]
end
subgraph PluginA [Plugin on client A]
PosA[Pos.txt]
Send[CEPOS send]
MixA[PCM + 3D]
end
subgraph PluginB [Plugin on client B]
Recv[CEPOS recv]
Math[Proximity math]
MixB[PCM + 3D]
end
PosA --> Send --> Relay --> Recv --> Math --> MixB
Desc --> PluginA
Desc --> PluginB
Voice --> MixA
Voice --> MixB
```
---
*Related planning note: Plugin-SDK “send more to server” plan (Option B discarded). This file is the capability baseline for that work.*