wowsims/wotlk

repository·master·Indexed 41 days ago

https://github.com/wowsims/wotlk

A high-performance DPS simulator for World of Warcraft: Wrath of the Lich King (WOTLK) Classic. It features a Go-based simulation core, a TypeScript-based UI, and a CLI tool (wowsimcli) for executing simulations, bulk item replacement testing, and link decoding. The project provides a framework for community-driven class and spec simulations and exposes a WASM API for JavaScript integration.

Tokens
14.3K
Snippets
42
Records
52
Agent score
51%

What's inside wowsims-wotlk

  1. Add a new spec to the raid sim

    master

    To add a new character specification to the raid simulator, follow these three steps. Note: Do not modify the raid sim until the individual simulator is ready for launch, as raid sim changes are publicly accessible.

    1. Update TypeScript configuration: Add a reference to the individual simulator in ui/raid/tsconfig.json. This step is critical to prevent silent TypeScript errors.
    2. Import Styles: Import the individual simulator's CSS file within ui/raid/index.scss.
    3. Update Presets: Modify ui/raid/presets.ts by:
      • Adding a constructor factory to the specSimFactories variable.
      • Adding configurations for new Players in the playerPresets variable.
  2. Setup autocompletion for APL editing in VS Code

    master

    To enable autocompletion for Action Priority List (APL) files in VS Code, you must generate a JSON schema from the project's protobuf definitions. This allows VS Code to validate your .apl.json files against the expected structure.

    1. Install the JSON schema generator: Run the following command to install protoc-gen-jsonschema via Go:

      go install github.com/chrusty/protoc-gen-jsonschema/cmd/protoc-gen-jsonschema@latest
    2. Generate the Schema: Create a jsonschema directory and use protoc to generate the schema from the APL proto file:

      mkdir jsonschema
      protoc \
        --jsonschema_out=./jsonschema \
        --proto_path=./proto/ \
        --jsonschema_opt=json_fieldnames \
        --jsonschema_opt=enforce_oneof \
        --jsonschema_opt=disallow_additional_properties \
        ./proto/apl.proto
    3. Configure VS Code: Ensure your .vscode/settings.json points to the generated jsonschema directory. The extension .apl.json will then automatically activate the schema for autocompletion.

    go install github.com/chrusty/protoc-gen-jsonschema/cmd/protoc-gen-jsonschema@latest
    
    mkdir jsonschema
    protoc \
      --jsonschema_out=./jsonschema \
      --proto_path=./proto/ \
      --jsonschema_opt=json_fieldnames \
      --jsonschema_opt=enforce_oneof \
      --jsonschema_opt=disallow_additional_properties \
      ./proto/apl.proto
  3. Install dependencies for local development (Ubuntu)

    master

    To develop locally on Ubuntu, you must install Go (>=1.21), a protobuf-compiler with Go plugins, and Node (>=14.0).

    Warning: Do not use apt to install these dependencies as the versions provided by apt are too old. Use the following script to install the correct versions via curl and nvm.

    # Standard Go installation script
    curl -O https://dl.google.com/go/go1.21.1.linux-amd64.tar.gz
    sudo rm -rf /usr/local/go 
    sudo tar -C /usr/local -xzf go1.21.1.linux-amd64.tar.gz
    echo 'export PATH=$PATH:/usr/local/go/bin' >> $HOME/.bashrc
    echo 'export GOPATH=$HOME/go' >> $HOME/.bashrc
    echo 'export PATH=$PATH:$GOPATH/bin' >> $HOME/.bashrc
    source $HOME/.bashrc
    
    cd wotlk
    
    # Install protobuf compiler and Go plugins
    sudo apt update && sudo apt upgrade
    sudo apt install protobuf-compiler
    go get -u -v google.golang.org/protobuf
    go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
    
    # Install node
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
    nvm install 19.8.0
    
    # Install the npm package dependencies using node
    npm install
  4. Launch a completed simulation for public use

    master

    Once a new simulation is complete and ready for release, you must register it in the main application to make it accessible via the dropdown menu and remove development warnings:

    1. Modify ui/core/launched_sims.ts to include the new spec value.
    2. Modify ui/index.html to include the new spec value.
  5. Download the WoW WOTLK Sim

    master

    If you want to use the simulator without developing, you can download pre-built binaries for Windows, MacOS, and Linux.

    1. Download the appropriate zip file from the latest releases.
    2. Unzip the file.
    3. Open the unzipped file to launch the simulator in your web browser.
    # Links for latest Sim build:
    - [Windows Sim](https://github.com/wowsims/wotlk/releases/latest/download/wowsimwotlk-windows.exe.zip)
    - [MacOS Sim](https://github.com/wowsims/wotlk/releases/latest/download/wowsimwotlk-amd64-darwin.zip)
    - [Linux Sim](https://github.com/wowsims/wotlk/releases/latest/download/wowsimwotlk-amd64-linux.zip)
  6. Set up development using Docker

    master

    For a containerized workflow, use Docker. This avoids manual dependency management on your host machine.

    1. Clone the repository and enter the directory.
    2. Build the image and install npm dependencies (run once).
    3. Use the WOTLK_CMD environment variable to prefix your commands for convenience.
    git clone https://github.com/wowsims/wotlk.git
    cd wotlk
    
    # Build the docker image and install npm dependencies (run once)
    docker build --tag wowsims-wotlk .
    docker run --rm -v $(pwd):/wotlk wowsims-wotlk npm install
    
    # Set convenience environment variable
    export WOTLK_CMD="docker run --rm -it -p 8080:8080 -v $(pwd):/wotlk wowsims-wotlk"
    
    # Example: Run tests
    $(echo $WOTLK_CMD) make test
    
    # Example: Host a local site
    $(echo $WOTLK_CMD) make host
  7. How to add a new Class/Spec simulation

    master

    Adding a new simulation involves three main phases: defining the data interface, implementing the UI, and implementing the simulation logic.

    1. Create the Proto Interface

    Use Protocol Buffers to define the data structure shared between Go and TypeScript:

    • Add a new value to the Spec enum in proto/common.proto. This name (e.g., elemental_shaman) is used for templating as $SPEC.
    • Create proto/YOUR_CLASS.proto with class-specific data messages.
    • Update PlayerOptions.spec in proto/api.proto to include your new message.
    • Running make will then generate the necessary .go and .ts code.

    2. Implement the UI

    • Modify ui/core/proto_utils/utils.ts to include boilerplate for your $SPEC.
    • Create a directory ui/$SPEC (e.g., ui/elemental_shaman).
    • Copy existing spec UI code as a template and modify the files.
    • Add a rule to the makefile for your new spec.
    • Run make host and visit http://localhost:8080/wotlk/$SPEC.

    3. Implement the Sim

    • sim/core/api.go: Implement the request/response messages from proto/api.proto.
    • sim/core/sim.go: Orchestrates the simulation; the main loop is in Simulation.RunOnce.
    • sim/core/agent.go: Implement the Agent interface (the 'Player' logic).
    • sim/core/character.go: Manages stats, cooldowns, and gear.
    • Registration: Add your new sim to RegisterAll() in sim/register_all.go.
    • Testing: Write unit tests and run them with make test.
  8. Create and structure APL files

    master

    APL (Action Priority List) files should use the .apl.json extension. An empty rotation file follows this structure:

    {
        "type": "TypeAPL",
        "prepullActions": [],
        "priorityList": []
    }

    Prepull Actions

    Prepull actions are executed before the main rotation. For example, to cast a spell 1 second before the rotation starts:

    {
        "action": {
            "castSpell": {
                "spellId": {
                    "spellId": 1
                }
            }
        },
        "doAt": "-1s"
    }

    Priority List Actions and Conditions

    Actions in the priorityList can include conditions using the cmp (compare) object. The cmp object uses op (operator), lhs (left hand side), and rhs (right hand side).

    Example: Checking if the remaining time on a Flame Shock dot is greater than the cast time of Lava Burst (OpGt) before casting Lava Burst:

    {
        "action": {
            "condition": {
                "cmp": {
                    "op": "OpGt",
                    "lhs": {
                        "dotRemainingTime": {
                            "spellId": {
                                "spellId": 49233
                            }
                        }
                    },
                    "rhs": {
                        "spellCastTime": {
                            "spellId": {
                                "spellId": 60043
                            }
                        }
                    }
                }
            },
            "castSpell": {
                "spellId": {
                    "spellId": 60043
                }
            }
        }
    }
    {
        "type": "TypeAPL",
        "prepullActions": [],
        "priorityList": []
    }
  9. Deploy the raid sim

    master
    Deployment is automated via GitHub Actions. Pushing changes to the master branch automatically triggers the build and deployment process for the new site. No manual deployment steps are required.
  10. Handle asynchronous progress reporting in WASM

    master

    For long-running tasks like raidSimAsync, statWeightsAsync, and bulkSimAsync, the simulator uses an asynchronous pattern to report progress back to the JavaScript environment.

    To use these functions:

    1. Pass the simulation request as the first argument (args[0]).
    2. Pass a JavaScript callback function as the second argument (args[1]).
    3. The simulator will invoke your callback function repeatedly, passing a Uint8Array containing serialized proto.ProgressMetrics for each update.
    4. The callback will be invoked one final time with the final result once the simulation completes.
    // Example: Using raidSimAsync with a progress callback
    const requestBinary = new Uint8Array([...]); // Serialized RaidSimRequest
    
    raidSimAsync(requestBinary, (progressBytes) => {
      // progressBytes is a Uint8Array containing proto.ProgressMetrics
      // You would typically decode this using protobufjs or similar
      console.log("Progress update received");
    });
  11. Run the WOTLK Simulator Web Server

    master

    The simulator can be run as a web server that hosts the user interface and provides simulation APIs via Protobuf over HTTP. You can configure the server using several command-line flags.

    CLI Flags

    • -usefs: Set to true to use the local ./dist directory for client files instead of the embedded filesystem. Useful for local development.
    • -wasm: Use WebAssembly for the simulation instead of web server APIs. Note: This requires -usefs=true to be set.
    • -sim: The name of the specific simulator to launch (e.g., balance_druid, elemental_shaman). This determines the default URL path.
    • -host: The URL/address to host the interface on (default: localhost:3333).
    • -launch: Whether to automatically open the browser (default: true).
    • -nvc: Skip the version check against GitHub releases.
    # Example: Running with local files and a specific sim name
    ./wotlk-sim -usefs=true -sim=elemental_shaman
  12. Configure the replacement items JSON file

    master

    To use the bulk command, you must provide a JSON file that follows the ItemReplacementInput schema. This file tells the simulator which items to swap into the simulation and how to handle them.

    Schema Keys:

    • combinations (boolean): If true, the simulator will test different combinations of the provided items.
    • fast_mode (boolean): Enables a faster simulation mode.
    • items (array of proto.ItemSpec): A list of item specifications to be used for replacement.
    {
      "combinations": true,
      "fast_mode": false,
      "items": [
        { "id": 12345 },
        { "id": 67890 }
      ]
    }