canary/docs/development.md
Luan Santos 4f01de4063
build: pin vcpkg registry and developer tools (#4052)
Pin vcpkg registry and native developer toolchain

This commit moves Canary patched protobuf port from the old overlay port model into a versioned local vcpkg registry and pins the native developer toolchain used by local builds and CI.

The goal is to make dependency resolution more reproducible without changing the CMake target structure or the existing CI build flow. The project still builds through the same CMake presets and vcpkg manifest model, but protobuf is now resolved from a controlled repository local registry instead of an unversioned overlay port path.

The vcpkg configuration now uses a pinned builtin registry baseline and a filesystem registry for the local protobuf package. The protobuf package is provided through the new vcpkg registry directory with its portfile metadata wrappers version database and Canary specific patches.

This keeps the patched protobuf dependency versioned inside the repository and makes future dependency updates easier to review because the registry baseline package version port version and patch set are all explicit.

The new local protobuf registry defines protobuf version 6.33.4 with port version 1 and keeps the required dependencies declared through the package metadata, including abseil host protobuf utf8 range vcpkg cmake and vcpkg cmake config. It also preserves optional zlib support through the protobuf zlib feature.

The developer toolchain is now pinned through mise. The repository adds a mise configuration that pins CMake Ninja sccache and Python, sets the default CMake generator to Ninja, and defines standard tasks for bootstrapping configuring building testing installing and checking cache stats.

Pinned tool versions

• mise minimum version 2026.5.15

• CMake 4.3.4

• Ninja 1.13.2

• sccache 0.14.0

• Python 3.14.6

A new bootstrap script installs the pinned vcpkg checkout into the configured VCPKG ROOT path, defaulting to the repository local tools directory. The script clones microsoft vcpkg when needed, fetches and checks out the builtin baseline from the vcpkg manifest, bootstraps vcpkg with metrics disabled, and prints the selected vcpkg root.

Main changes included in this commit

• Moves the patched protobuf port from overlay ports to a local vcpkg registry

• Adds a repository local vcpkg registry directory

• Adds protobuf package metadata under the local registry

• Adds protobuf version database entries for the local registry

• Pins the default builtin vcpkg registry baseline

• Configures protobuf to resolve from the filesystem registry

• Keeps overlay triplets unchanged

• Keeps CMake target structure unchanged

• Keeps the existing CI build flow conceptually unchanged

• Adds protobuf patches inside the versioned registry port

• Adds wrappers and package configuration files needed by the patched protobuf port

• Adds a mise based native developer toolchain definition

• Pins CMake Ninja Python and sccache for local development

• Sets VCPKG ROOT to the repository local tools vcpkg path by default

• Sets Ninja as the default CMake generator for the pinned workflow

• Adds mise tasks for bootstrap configure build test install and cache stats

• Adds a Python bootstrap script for the pinned vcpkg checkout

• Updates CI build workflows to install pinned build tools through mise

• Updates Linux macOS and Windows reusable build workflows to use the repository local vcpkg directory for CMake builds

• Updates CI path filters so changes to mise vcpkg configuration and the local registry trigger the correct jobs

• Updates cmake format checks to use pinned Python setup and hashed Python requirements

• Adds hashed requirements for cmakelang PyYAML and six

• Updates README test instructions to use the pinned mise workflow

• Updates development documentation to describe the unified local setup and build workflow

Workflow behavior after this change

Local developers can install the pinned tools and bootstrap vcpkg from the repository root before configuring or building Canary. The standard path is now based on mise install followed by the repository tasks for bootstrap configure build and test.

CI now sets up pinned build tools through mise before running native build steps. Linux and macOS workflows no longer rely on system installed Ninja from apt or brew for the build tool version. They install only the remaining platform dependencies and use the pinned toolchain for CMake Ninja and Python.

Windows CMake builds also use the pinned tool setup and place vcpkg under the repository local tools directory. Solution builds keep their existing repository vcpkg location behavior where needed.

CMake formatting now installs its Python dependencies through a hashed requirements file before running cmakelang format. This makes the formatting tool dependencies more deterministic and avoids installing unpinned formatter dependencies directly in the workflow.

Validation

• macOS release preset configures successfully with the local registry

• macOS release preset builds successfully with the local registry

• Manual testing was otherwise not reported

Overall this commit makes Canary native build dependency resolution more reproducible by versioning the patched protobuf port in a local vcpkg registry and pinning the developer toolchain through mise, while keeping the existing CMake presets target structure and CI build flow intact.
2026-08-05 09:07:02 -03:00

10 KiB

Development Guide

Introduction

This document describes the development workflow used by Canary and serves as a reference for contributors who want to:

  • Build the server locally
  • Develop new features
  • Fix bugs
  • Create Lua systems
  • Write tests
  • Submit pull requests

Canary is an MMORPG server emulator written primarily in:

  • C++20 (server core)
  • Lua (gameplay systems)
  • SQL (database schema)
  • CMake (build system)

Development Philosophy

Canary follows a few important principles:

  1. Keep the core engine stable.
  2. Prefer gameplay customization through Lua.
  3. Maintain compatibility with existing datapacks whenever possible.
  4. Favor readability over clever implementations.
  5. Keep systems modular and testable.
  6. Avoid introducing unnecessary dependencies.

Development Environment

IDEs

Supported:

  • Visual Studio 2026
  • CLion
  • VSCode

Useful Extensions

VSCode:

  • C/C++
  • CMake Tools

Repository Structure

canary/
│
├── src/
├── data/
├── data-canary/
├── data-otservbr-global/
├── docs/
├── tests/
├── docker/
├── metrics/
│
├── schema.sql
├── config.lua.dist
├── CMakeLists.txt
├── CMakePresets.json
├── vcpkg.json
└── package.json

Development Setup

The fastest way to start local testing is using the Docker quickstart.

Services provided:

  • Canary
  • MariaDB
  • MyAAC
  • Login Server

Start the stack:

cd docker
cp .env.dist .env
docker compose up -d --build

This pulls the published Canary runtime image and builds the MyAAC quickstart image. It does not compile Canary locally.

Default endpoints:

Website:                 http://localhost:8080
Client login API:        http://localhost:8088/login
Canary login protocol:   7171
Canary game protocol:    7172
Canary status protocol:  7173
Login-server gRPC:       9090

Docker is ideal when:

  • Testing scripts
  • Developing datapacks
  • Learning the project structure
  • Avoiding local dependency installation
  • Running local or LAN demos with trusted defaults

Do not expose the quickstart directly to the public Internet with default accounts, passwords or rolling image tags. See docker/DOCKER.md for the full Docker quickstart contract.


Option 2: Native Development

Recommended for engine contributors.

Required Software

Install Git, a supported C++ compiler, and mise. The repository's .mise.toml installs the pinned CMake, Ninja, Python, and sccache versions used by the native development workflow and relevant CI jobs.

Linux requires GCC or Clang. Windows requires Visual Studio with Desktop Development with C++.


Cloning the Repository

git clone https://github.com/opentibiabr/canary.git
cd canary

Canary does not require Git submodules. Install the pinned tools and vcpkg checkout from the repository root:

mise install
mise run bootstrap

Configuration

Create your local configuration:

cp config.lua.dist config.lua

Important settings:

serverName = "Development Server"
ip = "127.0.0.1"
mysqlHost = "localhost"
mysqlUser = "root"
mysqlPass = "password"

Never commit personal configuration changes.


Build System

Use the tasks in .mise.toml so local builds use the same tool versions as CI:

mise run configure linux-debug
mise run build linux-debug
mise run test linux-debug

Replace linux-debug with another preset from CMakePresets.json as needed. The underlying CMake commands remain available for IDE integration and advanced use.


Building Canary

mise run configure linux-release
mise run build linux-release

Windows

Open the repository in Visual Studio.

Visual Studio can automatically:

  • Detect CMake
  • Resolve dependencies through vcpkg
  • Generate the build cache

Make sure VCPKG_ROOT is configured before opening the folder or configuring the CMake preset.

Then:

Build → Build All

Dependency Management

Canary uses:

vcpkg.json

to declare dependencies.

Examples:

  • asio
  • curl
  • libmariadb
  • LuaJIT
  • mbedtls
  • protobuf
  • pugixml
  • spdlog

If dependencies fail:

cd "$VCPKG_ROOT"
git pull
./bootstrap-vcpkg.sh

or on Windows:

Set-Location $env:VCPKG_ROOT
git pull
.\bootstrap-vcpkg.bat

Running the Server

After compilation:

./canary

Expected startup sequence:

Loading config
Loading map
Loading monsters
Loading NPCs
Loading scripts
Starting game server

Database Development

Database schema:

schema.sql

Import:

mysql -u root -p database_name < schema.sql

Main tables:

accounts
players
guilds
houses
market
player_storage

Schema modifications should:

  • Be backward compatible when possible
  • Include migration documentation
  • Avoid destructive changes

Lua Development

Most gameplay features belong in Lua.

Examples:

  • Quests
  • NPCs
  • Actions
  • Talkactions
  • Spells
  • Events

Typical locations:

data/scripts/
data/actions/
data/spells/
data/npc/

Lua API

The server exposes C++ functionality through Lua bindings.

Examples:

player:addExperience(1000)

player:addItem(2160)

Game.getPlayers()

Generated API documentation is available in:

docs/lua-api/

Enable generation:

generateLuaApiDocs = true

Adding New Features

Prefer Lua First

Before modifying C++:

Ask:

Can this be implemented entirely in Lua?

If yes:

Use Lua.

If no:

Extend the C++ engine.


Adding a New Lua Event

Example:

local event = CreatureEvent("Example")

function event.onLogin(player)
    player:sendTextMessage(MESSAGE_STATUS, "Welcome!")
    return true
end

event:register()

C++ Development

Source Layout

src/
├── game/
├── creatures/
├── map/
├── items/
├── io/
├── lua/
├── server/
├── utils/
└── lib/

Before creating new modules:

  • Check existing systems.
  • Extend existing classes when appropriate.
  • Avoid duplicate functionality.

Coding Standards

Naming

Classes:

Player
Monster
ProtocolGame

Methods:

addExperience()
getHealth()
sendTextMessage()

Variables:

playerLevel
damageAmount
targetPosition

Constants:

MAX_PLAYERS
MAX_CONTAINER_ITEMS

General Guidelines

Prefer:

const auto&

instead of unnecessary copies.

Prefer:

std::vector
std::unordered_map
std::shared_ptr

when they match the ownership model of the surrounding code.

Avoid:

new
delete

when smart pointers are possible.

For Lua bindings that expose shared C++ objects, read docs/systems/lua-shared-userdata.md before changing ownership or userdata registration code.


Logging

Use existing logging systems.

Good:

g_logger().info("Player {} logged in", playerName);

Bad:

std::cout << "debug" << std::endl;

Never commit debugging output.


Debugging

Linux

Run with GDB:

gdb ./canary

Helper script:

./start_gdb.sh

Common Debug Targets

Investigate:

  • Crashes
  • Memory corruption
  • Infinite loops
  • Scheduler deadlocks

Useful commands:

bt
frame
print
continue

Testing

Canary includes automated tests.

Build tests:

cmake --preset linux-debug

cmake --build --preset linux-debug

Run tests:

ctest --preset linux-debug

Tests should be added for:

  • New systems
  • Bug fixes
  • Edge cases
  • Regression prevention

Pull Request Workflow

Create a Branch

git checkout -b feature/new-system

Examples:

feature/
fix/
refactor/
docs/

Commit Messages

Good:

fix(player): prevent logout race condition

feat(wheel): add progression API

refactor(combat): simplify condition processing

Avoid:

fix stuff

update

changes

Before Opening a Pull Request

Checklist:

  • Builds successfully
  • Tests pass
  • No debug code
  • No merge conflicts
  • Documentation updated
  • Lua scripts validated

Reviewing Changes

When reviewing code:

Focus on:

  • Correctness
  • Performance
  • Security
  • Maintainability
  • Backward compatibility

Do not approve changes solely because they work locally.


Performance Considerations

Critical systems:

  • Pathfinding
  • Combat
  • Scheduler
  • Dispatcher
  • Networking

Before introducing changes:

Consider:

How does this behave with 1000 players?

Small inefficiencies become large server costs.


Common Development Tasks

Add a Spell

data/spells/

Add a Monster

data/monster/

Add an NPC

data/npc/

Add a Quest

data/scripts/

Add Engine Functionality

src/

and expose it through:

src/lua/

if Lua access is required.


Troubleshooting

Dependency Errors

Rebuild vcpkg:

cd "$VCPKG_ROOT"
git pull
./bootstrap-vcpkg.sh

CMake Cache Issues

Remove only the affected preset directory, then reconfigure the same preset:

rm -rf build/<preset-name>
cmake --preset <preset-name>

For example, if linux-release is the broken cache, remove build/linux-release, not the entire build/ directory.


Lua Errors

Enable verbose logging.

Check:

data/logs/

and console output.


Development Workflow Summary

Create Branch
      ↓
Implement Feature
      ↓
Build
      ↓
Run Tests
      ↓
Manual Validation
      ↓
Update Documentation
      ↓
Open Pull Request
      ↓
Code Review
      ↓
Merge

Conclusion

Canary development is centered around:

  • C++20 for engine performance
  • Lua for gameplay flexibility
  • CMake for reproducible builds
  • vcpkg for dependency management
  • Automated testing and code review

Contributors are encouraged to keep changes modular, documented, tested, and aligned with the project's goal of providing a modern and extensible MMORPG server platform.