# s2script > s2script is a TypeScript plugin runtime for Source 2 games (Counter-Strike 2 first), loaded via Metamod:Source. Plugins are npm-style packages that export named publics such as `OnPluginStart` and build to `.s2sp` archives. Types come from `@s2script/sdk` (engine-generic) and `@s2script/cs2` (CS2). Every docs page is available as Markdown by appending `.md` to its URL. The full guide text is at https://s2script.com/llms-full.txt. ## Start - [Getting started](https://s2script.com/docs/getting-started.md) - [Authoring plugins](https://s2script.com/docs/authoring.md) - [Publishing to the registry](https://s2script.com/docs/publishing.md) ## Migrating - [From SourceMod](https://s2script.com/docs/migrating/sourcemod.md) - [From CounterStrikeSharp](https://s2script.com/docs/migrating/counterstrikesharp.md) - [From ModSharp](https://s2script.com/docs/migrating/modsharp.md) - [From Swiftly](https://s2script.com/docs/migrating/swiftly.md) ## Concepts - [Entities](https://s2script.com/docs/concepts/entities.md) - [Schema fields](https://s2script.com/docs/concepts/schema-fields.md) - [Events](https://s2script.com/docs/concepts/events.md) - [SDKHooks](https://s2script.com/docs/concepts/sdkhooks.md) - [Commands](https://s2script.com/docs/concepts/commands.md) - [Translations](https://s2script.com/docs/concepts/translations.md) - [Config](https://s2script.com/docs/concepts/config.md) - [Lifecycle](https://s2script.com/docs/concepts/lifecycle.md) - [Async & networking](https://s2script.com/docs/concepts/async.md) - [Cookies](https://s2script.com/docs/concepts/cookies.md) - [Inter-plugin interfaces](https://s2script.com/docs/concepts/interfaces.md) - [Engine calls](https://s2script.com/docs/concepts/engine-calls.md) - [HUD](https://s2script.com/docs/concepts/hud.md) - [Default components](https://s2script.com/docs/concepts/hud/components.md) - [Mounting your own](https://s2script.com/docs/concepts/hud/custom.md) - [Creating a layout](https://s2script.com/docs/concepts/hud/custom/create.md) - [Custom camera](https://s2script.com/docs/concepts/camera.md) - [Crash reports](https://s2script.com/docs/concepts/crash-reports.md) ## API - [API overview](https://s2script.com/docs/api/overview.md) ## API: Platform - [@s2script/sdk/config](https://s2script.com/docs/api/modules/config.md): typed access to the plugin's materialized config. - [@s2script/sdk/console](https://s2script.com/docs/api/modules/console.md): Injected console logging for plugins. - [@s2script/sdk/unsafe](https://s2script.com/docs/api/modules/unsafe.md): Call or detour an engine function the framework does not wrap. Declare it in `gamedata/functions.jsonc` and bind with `Engine.function` — `s2s build` derives `engine:calls` / `engine:hooks`. Validated at load; optional bindings degrade with structured `status`. Operator allow-list still default-deny. - [@s2script/sdk/entity](https://s2script.com/docs/api/modules/entity.md): Liveness-gated EntityRef handles, typed reads/writes, create/spawn/teleport/remove, and entity I/O. - [@s2script/sdk/interfaces](https://s2script.com/docs/api/modules/interfaces.md): Protocol 2 contract types: Notification, Hook, Transform, Subscription, AttachmentScope. Name-inferred publish / use, bindForwards, and watchOptional. Protocol 2 `on` returns an idempotent Subscription (not a numeric id). - [@s2script/sdk/math](https://s2script.com/docs/api/modules/math.md): Vector and QAngle value types plus helpers like forwardVector. - [@s2script/sdk/plugin](https://s2script.com/docs/api/modules/plugin.md): Load-window authoring: `hook` (game-event catalog: hook.on / hook.onPre), previous(), pluginId(), publish / use / tryUse / watchOptional / bindForwards, onOutput, createScope, Scope. The artifact is export function OnPluginStart (plus optional named publics). CJS evaluation is before the load window. - [@s2script/sdk/plugins](https://s2script.com/docs/api/modules/plugins.md): runtime plugin management (the SM `sm plugins` backend). - [@s2script/sdk/timers](https://s2script.com/docs/api/modules/timers.md): Tick-integrated async timing: delay, nextTick, nextFrame, threadSleep (Promise). Overload rejects or throws AsyncQueueFull. ## API: Players & world - [@s2script/sdk/clients](https://s2script.com/docs/api/modules/clients.md): A Client is a handle to one connection lifetime. Reusing a slot never revives a saved handle. Disconnect callbacks expose a synchronous identity snapshot; stale getters and actions return safe defaults. - [@s2script/sdk/damage](https://s2script.com/docs/api/modules/damage.md): Borrowed DamageInfo view of a live damage event (throws "expired borrowed view" after the synchronous callback). Subscribe with SDKHook (OnTakeDamage / OnTakeDamagePost), provided by the selected game package. Post assignment of damage is ignored. - [@s2script/sdk/events](https://s2script.com/docs/api/modules/events.md): Typed game-event bus: fire / fireToClient, HookResult, and the block-scoped GameEvent accessor. - [@s2script/sdk/sdkhooks](https://s2script.com/docs/api/modules/sdkhooks.md): Per-entity SDKHook / SDKUnhook (SourceMod-shaped). OnTakeDamage / OnTakeDamagePost; SetTransmit AND-merges with Transmit.setVisibleTo; lifecycle virtuals (Spawn, Think, Use, …); Weapon* / Reload. - [@s2script/sdk/sound](https://s2script.com/docs/api/modules/sound.md): engine-generic sound: emit a named SoundEvent + register custom precache paths. - [@s2script/sdk/trace](https://s2script.com/docs/api/modules/trace.md): Ray / line / hull traces returning a liveness-gated hit entity. - [@s2script/sdk/transmit](https://s2script.com/docs/api/modules/transmit.md): Declarative per-client visibility masks. AND-merges with SDKHookType.SetTransmit — either API can hide; SetTransmit cannot un-hide a native mask clear. - [@s2script/sdk/usercmd](https://s2script.com/docs/api/modules/usercmd.md): a SourceMod `OnPlayerRunCmd`-equivalent: intercept, read, modify, and block a player's per-tick input (buttons, view angles, movement, impulse) before the game processes it. - [@s2script/sdk/usermessages](https://s2script.com/docs/api/modules/usermessages.md): A general protobuf user-message builder. - [@s2script/sdk/voice](https://s2script.com/docs/api/modules/voice.md): Who can hear whom: per-sender audibility rules (`Voice.setAudibleTo`) that AND-merge across plugins, plus hot-path counters (`Voice.stats`). ## API: Admin & chat - [@s2script/sdk/admin](https://s2script.com/docs/api/modules/admin.md): engine-generic admin flag model + cache API. Resolved at runtime via `globalThis.__s2pkg_admin`; no game-specific symbols. Import: `import { ADMFLAG, Admin } from "./admin";` - [@s2script/sdk/bans](https://s2script.com/docs/api/modules/bans.md): Host-global SteamID64 ban cache. `Bans.add` updates the cache then attempts persistence (void; no rollback). `Bans.remove` returns whether a cache key existed, not disk ACK. - [@s2script/sdk/chat](https://s2script.com/docs/api/modules/chat.md): print messages to player chat. - [@s2script/sdk/commands](https://s2script.com/docs/api/modules/commands.md): Load-window `command()` / `command.admin` / `command.server`. `Command` is an alias for `CommandInvocation`. Owned handlers return `HookResult.Handled`. - [@s2script/sdk/menu](https://s2script.com/docs/api/modules/menu.md): Slot-based menus. On CS2, Center and Chat paint a hudkit center sheet from the six-sheet pool (claim on first open, release when idle; Chat fallback per session if the pool is busy or the HUD open fails). activation is immediate or tab. - [@s2script/sdk/server](https://s2script.com/docs/api/modules/server.md): Server.command, cvars, and map validity. Map start is the named public `OnMapStart`. - [@s2script/sdk/topmenu](https://s2script.com/docs/api/modules/topmenu.md): Shared admin/top-menu registry. Plugins declare a tab with `addTab({ id, title })` then `addItem(tabId, item)`. Items default to the admin sheet (`sm_admin`); opt into the player hub (`sm_menu`) with `sheets: ["menu"]`. Snapshot `tabs` is `{ id, title }[]`; `categories` stays tab ids. - [@s2script/sdk/translations](https://s2script.com/docs/api/modules/translations.md): SourceMod-style i18n (per-client language, phrase files, {1} formatting). - [@s2script/sdk/votes](https://s2script.com/docs/api/modules/votes.md): Chat-ballot votes. On CS2, a right-side rail on s2script_lib (hudkit.layout — not a Menu, not a hudkit modal, not a second CustomHudLayout). VoteTally.choice is the per-slot 0-based cast. showLiveTally is ignored when a tally renderer is registered. ## API: Persistence - [@s2script/sdk/cookies](https://s2script.com/docs/api/modules/cookies.md): SM-parity client preference cookies. Cookies.set / setAuthId return boolean admission — false leaves the cache unchanged; true is host-owned until DB ACK, not a durability guarantee. - [@s2script/sdk/db](https://s2script.com/docs/api/modules/db.md): Async SQLite / SQL. query / execute reject with AsyncQueueFull or AsyncPayloadTooLarge before acceptance; oversized results reject with DatabaseResultTooLarge. ## API: Network - [@s2script/sdk/http](https://s2script.com/docs/api/modules/http.md): Off-thread fetch. Admission rejects with AsyncQueueFull / AsyncPayloadTooLarge; oversized responses reject with HttpResponseTooLarge. - [@s2script/sdk/net](https://s2script.com/docs/api/modules/net.md): Raw TCP / UDP sockets. TcpSocket.send and UdpSocket.sendTo return boolean admission — false means closed, oversized, or full; true is queued, not delivered. - [@s2script/sdk/ws](https://s2script.com/docs/api/modules/ws.md): Client WebSocket. send returns boolean admission — false means closed, oversized, or full; true is queued, not delivered. ## API: Game - [@s2script/cs2](https://s2script.com/docs/api/modules/cs2.md): CS2 player/pawn model, schema accessors, typed events overlay, menus, CustomHudLayout / hudkit, CustomPlayerCamera, Fade/Shake/HintText, and pickup gates (`items` / ItemsApi). - [@s2script/cs2](https://s2script.com/docs/api/modules/ui.md): Custom Panorama HUD: CustomHudLayout.create(spec) plus hudkit (modals, badges, toasts, callouts, banners, MOTD, dashboard). `CustomHudSpec.observable` (default false) is spectator rendering policy, not confidentiality. Use from OnPluginStart or later; pre-ctx methods throw. Modal/badge null is pool exhaustion (`tryModal` / `tryBadge` report PoolExhausted). spec/descriptor stay readable at module top-level. Retained views expose isValid(); modal/dashboard clicks dispatch from the last complete paint. `invalidate()` coalesces next-frame repaints; `refresh()` stays synchronous. tryOwn* / tryOwnDashboard claim shared surfaces (`Busy` instead of overwrite); hideAll preserves explicit claims. Unload/reload clears surfaces; `badge.release()` hides for every remaining viewer. HudLayout.subscribeClick is a disposable sibling of onClick. ui / hud() / components() are deprecated aliases. ## API: Interfaces - [@s2script/sdk/contracts/workshop](https://s2script.com/docs/api/modules/contracts/workshop.md): Type-only contract for a workshop / UGC service. The framework ships no implementation: a community plugin publishes one and consumers depend on this shape. ## Optional - [Schema classes](https://s2script.com/docs/reference/schema): generated CS2 schema field accessors - [Enums](https://s2script.com/docs/reference/enums) - [Game events](https://s2script.com/docs/reference/events): event payload shapes