Don't Starve Together (DST) Modding Tutorial

repository·master·Indexed 42 days ago

https://github.com/atjiu/dstmod-tutorial

A comprehensive guide for developing mods for Don't Starve Together, covering beginner to advanced topics. Includes instructions on creating animations with Spriter and autocompiler.exe, implementing animated prefabs in Lua, and using the API for custom actions, recipes, characters, and world initialization hooks like AddClassPostConstruct and AddPrefabPostInit.

Tokens
57.6K
Snippets
146
Records
202
Agent score
55%

What's inside DST Modding Tutorial

  1. Overview of the DST Modding Tutorial

    master

    This repository is a collection of tutorials designed to help players learn how to develop mods for Don't Starve Together (DST). The tutorial is structured into several learning stages to guide a developer from absolute beginner to advanced modder.

    Learning Paths

    • 入门 (Beginner): Essential reading for anyone starting their modding journey.
    • 进阶 (Intermediate): A reference for when you need to understand specific function definitions, object methods, and parameter details after completing the beginner steps.
    • 高级 (Advanced): Focuses on functional programming, such as defining components, creating custom characters, creating new creatures (prefabs), and writing AI behaviors (brains).
    • 技巧 (Tips/Concepts): Conceptual deep-dives into game design principles to improve your understanding of how the game works.
    • 案例 (Case Studies): Step-by-step walkthroughs of typical modding tasks designed to ensure success by following the instructions exactly.

    Important Usage Note

    Except for specific code examples provided in the 'Case Studies' section, all other code snippets in this repository are incomplete fragments. They are intended for demonstration and are NOT suitable for direct copy-pasting into your project.

  2. What is a Brain and how do Behaviour Trees work

    master

    In this project (modeled after Don't Starve AI), a Brain represents the AI logic of an entity. The AI is structured as a Behaviour Tree (BT), where every individual behavior is a node. A collection of these nodes forms a tree that dictates the entity's actions.

    Key concepts:

    • BehaviourTree (BT): The top-level object that manages the execution of the tree for a specific instance (inst).
    • BehaviourNode: The base class for all nodes in the tree.
    • PriorityNode: A common node type that executes its children based on priority. Higher priority children have a greater chance to run. If any child node returns success, the PriorityNode itself returns success.
    • BT Object: Created by wrapping a PriorityNode (the root) and the target instance (inst).
    -- Base class for all behavior nodes
    BehaviourNode = Class(function (self, name, children) end)
    
    -- The BT object that manages the tree for an instance
    BT = Class(function(self, inst, root)
        self.inst = inst
        self.root = root
    end)
  3. Understand AnimState: Play vs Push and Animation Events

    master

    When controlling animations via AnimState, it is important to distinguish between how animations are triggered and how their completion is detected.

    Play vs Push

    • PlayAnimation: Forces the interruption of the current animation to immediately start the requested one.
    • PushAnimation: Adds the requested animation to a queue. It will not interrupt the current animation but will play once the current one finishes.

    Animation Completion Events

    • animover event: Fired when a Play animation or a Push animation finishes.
    • animqueueover event: Fired only when a Push animation sequence is completely finished (i.e., the entire queue is empty).
    • inst.AnimState:AnimDone(): A function that returns true when animations are finished. It is similar to the animqueueover event.

    Best Practice: If you are unsure whether you are dealing with a single animation or a sequence, use both the animover event and the AnimDone() function together to accurately determine the end of the animation flow.

  4. Understand the difference between RPC and Replica components

    master

    In this environment, components typically run on the Master (host) side. Clients (guests) cannot directly access data stored in a Master component via inst.components.component_name.

    To allow clients to access data, you must use Replica components.

    • Replica Components: Used to synchronize specific data from the Master to the Client. Clients access this data via inst.replica.component_name.
    • RPC (Remote Procedure Call): Used when a Client needs to trigger an action or request data from the Master. Unlike net variables, an RPC will always trigger upon being sent, regardless of whether the value has changed.
    • Net Variables: Used within Replica components to synchronize state. A key difference is that calling .set() on a net variable only triggers its associated event if the value actually changes.
  5. Difference between inventory, inventoryitem, and container

    master

    The game distinguishes between these three component types:

    • inventory: Represents an inventory (specifically the slots on a player, including equipment slots). Items currently held by the mouse also belong to the inventory.
    • container: Represents a storage container, such as a chest, pot, or fridge.
    • inventoryitem: Represents an item that can be placed inside an entity that has either an inventory or a container component.
  6. How dynamic terrain works in DST Modding

    master

    Dynamic terrain is constructed using a hierarchy of four core abstractions: room, task, taskset, and level.

    • room: The smallest unit of terrain, defining the visual ground type, tags, and resource distribution (prefabs).
    • task: A collection of rooms. It defines how many instances of specific rooms are used to build a segment of terrain.
    • taskset: A collection of tasks that defines a specific biome.
    • level: The top-level container that holds tasksets.

    Common taskset identifiers include default (Online biome), classic (Classic biome), lavaarena_taskset, and quagmire_taskset. When creating a new game, the player's choice of biome determines which taskset is used.

  7. Difference between AnimState:SetBank() and AnimState:SetBuild()

    master

    When working with animations in AnimState:

    • SetBank(): Defines a collection of animation names. The Bank determines which animations an entity is capable of playing. If an entity attempts to play an animation not present in its Bank, it will appear transparent in-game.
    • SetBuild(): Refers to the material pack (the .zip files located in the anim folder under the MOD or game data folder).

    You can use the same Bank with different Builds to represent different forms. For example, multiple characters might all use a unified "wilson" Bank, but each character has their own unique Build (typically matching their prefab name).

  8. Understand the project directory structure

    master

    The source code is organized into several functional directories. Understanding these is key to knowing where to find specific logic:

    • behavious: Contains behavior logic used by classes in the brains directory.
    • brains: Defines the AI/default behaviors for entities (e.g., wandering, eating, or attacking).
    • components: Contains various components. For large-scale modding, study these to understand how Klei defines entity properties.
    • map: Defines terrain generation (e.g., Mosaic terrain, Lunar Island).
    • prefabs: Contains all game entities (characters, flowers, birds, fish, trees, etc.).
    • scenarios: Contains easter eggs and specific game scenarios.
    • screens: Defines game UI screens (e.g., world creation, loading, main game interface).
    • stategraphs: Manages animation logic (different from behavior trees). Defines which animations play during specific states and handles state events/handlers.
    • tools/utils: Various utility functions.
    • widgets: UI elements like health bars or seasonal dials.
    • languages: Localization and translation files.
    • cameras: Engine-level camera settings (generally not required for modding).
    • prefabs: (See above) All entities are prefabs.
  9. Work with Components in Don't Starve Together

    master

    Components define the properties and capabilities of an entity. For example, an eater component manages what an entity can eat (e.g., picky eater, vegetarian).

    • Adding a component: Use the method inst:AddComponent("ComponentName") to attach a component to a prefab.
    • Finding component names: The component name corresponds directly to its filename (e.g., the eater component is found in eater.lua).
    inst:AddComponent("eater")
  10. How world and map initialization works

    master

    The API provides several hooks for managing the world (levels), terrain (tasksets), and specific areas (rooms):

    • Levels (AddLevelPreInit): Represents the world/dimension (e.g., Forest or Cave). Use AddLevelPreInit(levelid, fn) to run code before a specific level initializes.
    • Tasksets (AddTaskSetPreInit): Represents biomes or terrain sets (e.g., default or classic). Use AddTaskSetPreInit(tasksetname, fn) to modify biome generation.
    • Tasks (AddTaskPreInit): Represents specific terrain types (e.g., Grassland, Mining Area). Use AddTaskPreInit(taskname, fn) to run code before a task is initialized.
    • Rooms (AddRoomPreInit): The smallest unit of a map, often representing specific 'encounters' or layouts within a task.
  11. How player death and respawn events work

    master

    In this modding environment, player death and respawn logic is handled by the server via specific events:

    • ms_becameghost: Emitted by the server when a player dies and becomes a ghost.
    • respawnfromghost: Emitted by the server to trigger a player's respawn.

    Because these events are server-side, a client cannot listen to them directly. To trigger UI changes on the client (like showing a 'Reborn' button) when a player dies, you must listen for the event on the server and then use a Remote Procedure Call (RPC) to notify the client.

  12. Difference between replica components and RPCs

    master

    In multiplayer environments, data distribution is handled by the host.

    Replica Components

    Components ending in _replica (e.g., health_replica.lua, hunger_replica.lua) are copies of the original components used by clients to retrieve data from the host. The game engine performs special handling on these components to ensure that when the host updates a value (like hunger decreasing over time), the updated value is encapsulated in the replica component and sent to the clients.

    RPC (Remote Procedure Call)

    To communicate with the host in a mod, follow these two steps:

    1. Define AddModRPCHandler().
    2. Send data using SendModRPCToServer().

    When a player joins, they listen to all RPCHandlers. If a client triggers an RPCToServer, other clients will also receive the communication.