dst-scripts#
Overview#
The dst-scripts repository (LetsStarveTogether/dst-scripts) contains the core game logic Lua scripts for Don't Starve Together (饥荒联机版), the multiplayer survival game developed by Klei Entertainment. It is the primary source of truth for all game systems that govern how entities behave, how the world is generated, how the player interface operates, and how the multiplayer simulation is managed.
The codebase is written entirely in Lua and spans thousands of files organized by functional domain. It implements a rich set of interleaved systems:
- Entity Systems — templates and runtime scripts that define every object in the game world
- AI Behaviors — behavior trees and state machines that drive creature and NPC intelligence
- World Generation — a procedural, hierarchical system that assembles diverse, replayable worlds
- UI Layer — screens and widgets that render the HUD, menus, and in-game interfaces
- Game Mechanics — actions, crafting, cooking, farming, equipment, events, and balance tuning
Note: This repository contains no README file. All documentation of intent and usage is embedded in the code organization, file naming conventions, and inline comments.
The repository serves as the foundation for both the base game and its downloadable content expansions, with explicit DLC support built into the task and configuration systems.
Architecture#
dst-scripts follows a Component-Based Entity Architecture aligned with the Entity Component System (ECS) pattern. Rather than using deep inheritance hierarchies, game objects (entities) are assembled at runtime by attaching modular, reusable components. This makes it easy to share behavior across wildly different entity types — a tree, a character, and a campfire can all share the same burnable component.
Architectural Layers#
Five key layers work together to describe and operate every entity in the game:
| Layer | Purpose |
|---|---|
| Prefabs | Entity templates — define what objects exist and how they are built |
| Components | Reusable behavior modules — give entities specific capabilities |
| State Graphs | Animation state machines — manage transitions and visual states |
| Brains | AI controllers — implement behavior trees for NPCs and creatures |
| Actions | Interaction definitions — specify what entities can do to each other |
Core Root Files#
The repository root contains 235+ Lua files. The most architecturally significant are:
-
main.lua— Entry point and initialization. Sets up the Lua package path, seeds the random number generator, and defines platform-detection helpers such asIsConsole(),IsSteam(),IsWin32(), andIsPS4()for conditional platform-specific behavior throughout the engine. -
gamelogic.lua— Core game initialization. Requires and bootstraps all essential subsystems including player death tracking, server preferences, profanity filtering, map utilities, constants, user commands, emotes, and the loading screen widget. Also handles platform-specific setup (e.g., PS4 memory tracking). -
brain.lua— AI brain system foundation. Implements theBrainWranglerclass, which manages the full lifecycle of AI entity brains. Brains are organized into three lists —updaters,hibernators, andtickwaiters— for efficient per-frame processing. -
entityscript.lua— Base entity script functionality. Provides the foundational ECS integration, includingEntityWatchWorldState()andComponentWatchWorldState()— subscription mechanisms that let entities and components react to global game-state changes. -
networking.lua— Multiplayer networking layer. Handles client/server communication including remote slash commands (Networking_SlashCmd), player announcements, skin announcements, and the spawning of secondary instances for multiplayer sessions. -
actions.lua— Action system definitions. Establishes the action execution framework with range-validation utilities likeMakeRangeCheckFn(),DefaultRangeCheck, andPickRangeCheck()to determine whether player interactions are spatially valid. -
constants.lua— Game-wide constant values. Defines mathematical constants (PI,SQRT2,GOLDENANGLE), frame timing (FRAMES = 1/30), resolution settings, camera visibility distances, entity pop-in/pop-out radii, and directional constants (FACING_RIGHT,FACING_UP, etc.). -
tuning.lua— Gameplay balance tuning parameters. Contains the globalTUNINGtable with all adjustable game values: day-cycle timings, character stats (wilson_attack,wilson_health,wilson_hunger,wilson_sanity), multiplayer modifiers, wildlife respawn rates, and modifier functions for dynamic balance adjustments. -
config.lua— Configuration management. Defines aConfigclass that manages platform-specific option sets with default values and per-platform overrides. The globalTheConfiginstance is applied at runtime and governs options such ashide_vignetteandforce_netbookmode.
Directory Structure#
The repository is organized by functional domain. Below is a detailed breakdown of each directory.
prefabs/ — 1,583 files #
The largest directory in the repository. Each file defines one or more entity templates — the blueprints from which runtime entities are instantiated. Every interactive or visible object in the game originates from a prefab.
Categories include:
- Player characters —
wilson.lua,wendy.lua,wolfgang.lua, and all other playable characters; each importsMakePlayerCharacterfrom a sharedplayer_commonfactory - Creatures and mobs —
beefalo.lua,spider.lua,hound.lua, etc.; creature prefabs load their corresponding brain module and configure shared loot tables - Items and tools —
axe.lua,pickaxe.lua,spear.lua, etc.; tool prefabs use parameterized factory functions (e.g.,MakeAxe()) to support variants (standard, golden, moonglass) with minimal duplication - Environmental objects — trees, rocks, grass tufts, and other terrain features
- Food items and recipes — consumables with nutrition and status-effect data
Each prefab file declares its external assets (animation banks, sounds, textures) and prefab dependencies at the top, enabling lazy-loading and explicit dependency tracking. Behavior is injected via common_postinit and master_postinit callback functions passed to the factory.
components/ — 815 files #
Reusable modules that add specific behaviors and data to entities. Components are the heart of the ECS pattern — attaching entity:AddComponent("health") gives an entity hit points; entity:AddComponent("combat") enables it to fight. Key examples:
| File | Purpose |
|---|---|
health.lua | Hit points, max health, damage handling, fire-damage state, replica sync |
combat.lua | Attack range, cooldown, target selection, panic thresholds, battle cry timing |
inventory.lua | Item slots, equipment slots, heavy-lifting capability, cleanup on death |
fueled.lua | Fuel consumption for fires and lights; primary/secondary fuel type support |
burnable.lua | Fire and smoldering state, tag management ("fire", "canlight", "smolder") |
workable.lua | Work actions (chopping trees, mining rocks), workleft vs. max-work tracking |
equippable.lua | Equipment slot assignment (HANDS, HEAD, etc.), walk-speed modifiers when worn |
Key design patterns across all components:
- Replica synchronization — critical state is mirrored to
self.inst.replica.<component>for networked client replication - Dynamic tagging — components manage runtime entity tags (e.g.,
"fire_fueled","chop_workable") for capability queries - Cross-component coordination — components reference siblings through the shared
insthandle (e.g., health checks combat panic thresholds) - Event-driven callbacks —
onpropertycallbacks respond automatically to state changes
stategraphs/ — 261 files #
State machine implementations that control animation states and behavioral transitions for entities. Files follow the naming convention SG<entityname>.lua (e.g., SGwilson.lua, SGbeefalo.lua, SGabigail.lua).
Each state graph defines:
- Named animation states (
idle,walk,attack,death,sleep, etc.) - Transition rules between states
- Event handlers that trigger state changes
- Per-state hooks for sounds, particles, and logic callbacks
The shared commonstates.lua file provides reusable state definitions that are mixed into entity-specific graphs.
brains/ — 191 files #
AI brain files that implement behavior trees for NPCs and creatures. Each file corresponds to a specific creature or character AI (e.g., beefalobrain.lua , spiderbrain.lua, pigbrain.lua).
A brain file typically:
- Requires the behavior node modules it needs (
wander,faceentity,chaseandattack,follow,attackwall) - Defines creature-specific distance and timing constants (e.g.,
SEE_PLAYER_DIST = 5,WANDER_DIST_DAY = 20,MAX_CHASE_TIME = 6) - Defines AI state constants (
GREETING,LOITERING,WANDERING) - Composes behavior nodes into a priority-ordered behavior tree
Brains are installed on entities via entity:SetBrain(brain) during prefab construction.
behaviours/ — 29 files #
The atomic behavior tree node implementations that brains compose. Each file defines a single reusable behavior class extending BehaviourNode:
| File | Behavior |
|---|---|
approach.lua | Move toward a target |
chaseandattack.lua | Pursue and attack enemies |
panic.lua | Flee from danger |
wander.lua | Random exploration |
runaway.lua | Run away from threat |
follow.lua | Follow a specific entity |
doaction.lua | Execute a discrete action |
avoidlight.lua | Stay away from light sources |
leash.lua | Constrain movement to a home point |
Each behavior implements a Visit() method containing the core execution logic that returns the current behavior status. Behaviors can also register event listeners (e.g., chaseandattack listens for "onattackother" events) .
map/ — World Generation System #
A hierarchical world generation system using four nested subdirectories:
map/levels/ — Top-level world preset definitions (forest.lua, caves.lua, lavaarena.lua, quagmire.lua). Each level specifies required set pieces and a pool of random set pieces to include. Example from forest.lua :
local survival_together = {
id = "SURVIVAL_TOGETHER",
location = "forest",
required_setpieces = { "Sculptures_1", "Maxwell5" },
numrandom_set_pieces = 4,
random_set_pieces = { "Sculptures_2", ... "Warzone_3" }
}
map/tasks/ — Node definitions for the generation graph (forest.lua, caves.lua, DLCtasks.lua, maxwell.lua, moonisland_tasks.lua, ruins.lua). Tasks use a lock/key constraint system to control which areas unlock which other areas. Example from forest.lua :
AddTask("Resource-rich Tier2", {
locks = LOCKS.NONE,
keys_given = {KEYS.PICKAXE, KEYS.AXE, KEYS.GRASS, KEYS.WOOD},
room_choices = {
["Forest"] = function() return 1 + math.random(SIZE_VARIATION) end,
["Plain"] = function() return 1 + math.random(SIZE_VARIATION) end,
},
room_bg = WORLD_TILES.GRASS,
})
map/rooms/ — Room content definitions organized by world type (forest/ with 25 files, cave/ with 16 files). Rooms define entity spawn probabilities for each biome type :
AddRoom("BGCrappyForest", {
value = WORLD_TILES.FOREST,
contents = {
distributepercent = .6,
distributeprefabs = {
pighouse = 0.015, spiderden = 0.04, gravestone = 0.01, ...
}
}
})
map/static_layouts/ — 240+ hand-crafted layout files for specific memorable locations: default_start.lua, chess_spot.lua, toadstool_arena.lua, teleportato_base_layout.lua, etc. These define exact entity placements for set pieces that appear every run.
screens/ — 64 files + redux/ (65 files) #
UI screen implementations composing multiple widget components into full-screen interfaces. Includes mainscreen.lua , lobbyscreen.lua, pausescreen.lua, optionsscreen.lua, mapscreen.lua, playerhud.lua, and specialized screens for minigames. The redux/ subdirectory (with a nested panels/ directory) contains modernized screen implementations following updated UI architecture patterns.
widgets/ — 184 files + redux/ (86 files) #
Reusable UI widget components that compose into screens. Includes foundational elements (button.lua, text.lua, image.lua), HUD elements (healthbadge.lua, hungerbadge.lua, sanitybadge.lua, inventorybar.lua), and interaction widgets (speechbubble.lua, nametagwidget.lua). The redux/ subdirectory (with nested worldsettings/) contains updated widget implementations.
languages/ — 15 files #
Localization system using .po format translation files covering Simplified Chinese, Traditional Chinese, French, German, Italian, Japanese, Korean, Polish, Brazilian Portuguese, Russian, and multiple Spanish variants. Also includes a .pot template and Lua language utilities.
scenarios/ — 50 files #
Scenario definitions covering chest loot tables, entity spawning configurations, and special game mode setups.
cameras/ #
Camera system with followcamera.lua — the main following camera controller managing movement and positioning.
nis/ #
Non-interactive sequences for in-game cinematics: maxwellintro.lua and xbnyn.lua.
tools/ and util/ #
tools/ contains 2 code-generation utility scripts. util/ contains 8 runtime helper modules covering emoji handling, hitbox utilities, profanity filtering, and save-data management.
Key Features#
1. Modular Component Design#
With 815+ components and 261 state graphs, the system enables highly flexible entity composition. A campfire, a character, and a creature can share identical burnable or health components, while the combination of components attached to each entity defines its unique behavior profile. Components synchronize critical state to replica objects for seamless multiplayer operation.
2. Behavior Tree AI#
The 29 behavior node implementations in behaviours/ compose into rich creature intelligence via 191 brain files . Rather than hard-coding creature AI, individual atomic behaviors (approach, flee, wander, attack) are combined in priority-ordered trees. Creature-specific tuning constants (distances, timings, search radii) in each brain file allow fine-grained adjustment without modifying the underlying behavior logic. The BrainWrangler in brain.lua manages all active brains across hibernation and update states for performance.
3. Procedural World Generation#
The map/ system uses a four-layer hierarchy — levels → tasks → rooms → static layouts — to produce varied yet structured worlds. Task nodes use a lock/key constraint graph to ensure logical world progression; rooms use probability distributions to scatter entities; and 240+ static layouts guarantee memorable hand-crafted locations (boss arenas, ruins, sculptures) appear in every run.
4. UI Modernization#
Both screens/ and widgets/ contain parallel redux/ subdirectories reflecting an ongoing architectural migration toward an updated, state-managed UI pattern. The original and modernized implementations coexist, enabling incremental migration without breaking existing functionality.
5. Character-Specific Content#
Seventeen speech_*.lua files provide each playable character with unique, contextual dialogue organized by action type (e.g., ACTIONFAIL.ACTIVATE.LOCKED_GATE). These files are generated from a batch toolchain (PropagateSpeech.bat via speech_tools.lua), ensuring consistency across character voice packs.
6. DLC Support Framework#
The map task system includes DLCtasks.lua , and the configuration layer in main.lua and config.lua includes explicit platform and DLC detection, making it straightforward to gate content behind expansion packs or platform capabilities.
7. Multi-Language Localization#
The languages/ directory supports 15 locales using the industry-standard .po format, covering all major languages for DST's global player base. String tables are referenced throughout UI code to ensure every text element is localizable.
Entity Composition Pattern#
Entities in dst-scripts are not pre-defined monolithic objects — they are assembled dynamically at runtime from reusable pieces. The following steps describe how a full entity comes to life, from static file to live game object.
Step 1 — Prefab Definition#
A prefab file defines the entity template. At the top of each file, two static tables are declared:
assets— external files the entity needs (animation banks, sound files, textures)prefabs— other prefab names this entity depends on (e.g., the loot it drops)
Then one or more factory functions are defined. For player characters, the shared factory is imported:
local MakePlayerCharacter = require("prefabs/player_common")
For creatures like the beefalo, a brain module is loaded and a loot table is registered:
local brain = require("brains/beefalobrain")
SetSharedLootTable('beefalo', { ... })
For tools, parameterized factories enable variant creation with minimal code duplication:
local function MakeAxe(name, common_postinit, master_postinit, data, _assets, _prefabs)
Step 2 — Component Attachment#
During the entity construction callback, components are dynamically attached using entity:AddComponent(). Each call adds a specific capability:
entity:AddComponent("health") -- hit points and damage (cite:code_file:5b9b099f)
entity:AddComponent("combat") -- fighting mechanics (cite:code_file:800c48e4)
entity:AddComponent("inventory") -- item storage (cite:code_file:4d770fc3)
entity:AddComponent("burnable") -- fire interaction (cite:code_file:1c00c8c6)
entity:AddComponent("workable") -- chop/mine actions (cite:code_file:60574071)
entity:AddComponent("equippable") -- wearable behavior (cite:code_file:b5396f8f)
Components are attached via common_postinit (runs on both client and server) and master_postinit (server-only) callbacks passed to the factory, keeping the server/client split clean. After attachment, each component may configure itself — for example, fueled sets its fuel types and workable sets its maximum work value .
Step 3 — State Graph Assignment#
Visual and animation behavior is controlled by assigning a state graph:
entity:SetStateGraph("SGwilson")
The state graph (e.g., stategraphs/SGwilson.lua) manages the entity's animation state machine — transitioning between idle, walk, attack, death, and other states in response to game events. The shared commonstates.lua provides base states that most entities reuse.
Step 4 — Brain Installation#
For NPCs and creatures, an AI brain is installed:
entity:SetBrain(brain)
The brain (e.g., beefalobrain.lua ) defines a behavior tree composed from the atomic nodes in behaviours/. The brain evaluates conditions each tick and executes the highest-priority applicable behavior. Configuration constants within the brain file tune the creature's awareness and response characteristics — for the beefalo, these include SEE_PLAYER_DIST = 5 and MAX_CHASE_TIME = 6 .
Step 5 — Action Registration#
Finally, entities participate in the action system. Actions (defined in actions.lua ) specify what interactions are possible — CHOP, MINE, ATTACK, EAT, PICKUP, DROP, etc. Components often register action handlers:
- A
workablecomponent with actionCHOPmeans a player wielding an axe can chop that entity - A
combatcomponent registers attack actions - An
ediblecomponent registers theEATaction
Range checks (MakeRangeCheckFn, DefaultRangeCheck) validate that the acting entity is close enough before the action executes .
Putting It Together#
This composition pattern allows arbitrarily complex entities to emerge from simple, individually testable pieces. A beefalo and a spider can share combat, health, and locomotor components, while differing entirely in their brain logic, state graph, loot table, and prefab assets. Adding a new entity type requires only writing a new prefab file and selecting which existing components to attach — no modification to any existing system is necessary.
Technical Details#
| Property | Value |
|---|---|
| Language | Lua |
| Architecture Pattern | Entity Component System (ECS) with Behavior Trees |
| Game | Don't Starve Together by Klei Entertainment |
| Prefabs | 1,583 files |
| Components | 815 files |
| State Graphs | 261 files |
| AI Brains | 191 files |
| Behavior Nodes | 29 files |
| Root Lua Files | 235+ |
| Total Screens | 64 + 65 redux |
| Total Widgets | 184 + 86 redux |
| Locales | 15 |
| Static Map Layouts | 240+ |
| Scenarios | 50 |
Runtime Design Patterns#
- Replica Synchronization — Components sync their authoritative server state to client-side replica objects (e.g.,
self.inst.replica.health), enabling lag-tolerant multiplayer without duplicating component logic - Dynamic Tagging — Entities carry a mutable set of string tags managed by components; other systems query tags rather than inspecting component state directly, keeping coupling low
- World-State Subscriptions —
EntityWatchWorldState()andComponentWatchWorldState()allow any entity or component to react to global state changes (day/night, season transitions, etc.) without polling - Centralized Tuning — All balance-sensitive numbers live in the
TUNINGtable intuning.lua, making balance patches a single-file change - Platform Abstraction — Platform detection helpers in
main.luaand theConfigclass inconfig.luaencapsulate all platform-specific branches, keeping game logic platform-neutral