canary/docker/config.sh
Eduardo Dantas 82b4778a5f
feat(protocol): add runtime multiprotocol client profiles (#4009)
Add runtime multiprotocol support to Canary

This commit adds runtime multiprotocol support to Canary without changing the compiled CLIENT VERSION target and without requiring separate ports for each supported client version.

The server can now resolve and apply protocol behavior at runtime through explicit protocol profiles. This allows modern clients legacy old protocol clients and extended legacy client variants to be supported through the same server entry point while keeping each protocol family isolated behind its own transport login and asset compatibility rules.

The implementation separates the protocol stack into smaller contracts instead of relying on one shared hardcoded flow. Transport behavior connection startup behavior profile metadata login parsing and session hints are now handled by dedicated components. This makes the multiprotocol path easier to reason about and safer to extend when adding more client families later.

Transport handling is now described through TransportCodec and TransportProfile. These components define TCP framing checksum behavior XTEA payload layout and compression behavior for each protocol family. Legacy clients no longer inherit the modern post 14 05 framing rules by accident and can use their own packet layout where required.

The first game socket decision is now handled through InitialConnectionBehavior. This controls the expected transport the handshake flow the challenge layout and the profile expected for the connection. This is important because old protocol clients and modern clients do not share the same login handshake assumptions.

ProtocolProfile now describes the client version wire family RSA family feature flags item mapper policy and asset signatures for each supported profile. This gives the server an explicit model for the client family being served instead of relying only on the compiled CLIENT VERSION or manual server side assumptions.

The login flow was also split into separate account login and game login layouts. This avoids forcing old protocol and modern webservice flows to share fragile hardcoded parsing logic. Each login family can now use the layout expected by that protocol path.

ProtocolSessionHintStore was added so the account login flow can hint the later game connection automatically. This avoids requiring administrators to manually choose a profile or run separate ports for different supported client versions. When a safe hint exists the game connection can reuse it to select the correct protocol behavior.

Supported profiles covered by this commit

• Current modern Canary client profile

• Tibia 11 00 old protocol profile

• CipSoft 8 60 compatible profiles

• Canary extended 8 60 asset profile

The current modern Canary profile remains the default when no safe legacy hint exists. Policy can block a detected profile but policy does not choose legacy framing by itself. This keeps profile selection explicit and prevents configuration policy from silently forcing the wrong transport behavior.

For the extended 8 60 client path the server resolves the profile from protocol version and asset signatures instead of requiring a separate port or manual profile selection. This allows a single runtime server path to distinguish between compatible legacy variants when the client package and assets provide enough information.

The related client packages are available in the latest dudantas tibia client release 15 11 c9d1cf. Prepared clients support the matching extended dat and spr workflow as well as config ini based local profile configuration.

The intended outdated client asset workflow is also documented. Compatible dat and spr files can be exported from a modern asset source using the Assets Editor changes. Original CipSoft clients can be extended or edited using the Tibia Extended Client Library workflow. This allows the project to keep a single asset source of truth and export compatible packages for the extended 8 60 and 11 00 client paths.

Main changes included in this commit

• Adds runtime multiprotocol profile support

• Keeps the compiled CLIENT VERSION target unchanged

• Avoids separate ports per client version

• Adds TransportCodec and TransportProfile for framing checksum XTEA payload layout and compression behavior

• Adds InitialConnectionBehavior for game socket startup handshake challenge layout and expected profile selection

• Adds ProtocolProfile for client version wire family RSA family feature flags item mapper policy and asset signatures

• Splits account login and game login parsing into separate protocol aware layouts

• Adds ProtocolSessionHintStore so login can hint the game connection automatically

• Keeps the modern Canary profile as the default fallback

• Supports Tibia 11 00 through the old protocol path

• Supports CipSoft 8 60 compatible profiles

• Supports the Canary extended 8 60 asset profile

• Resolves the extended 8 60 profile from protocol version and asset signatures

• Keeps legacy clients on their own framing challenge and payload layouts

• Prevents policy configuration from silently choosing legacy framing by itself

• Enables legacy protocol support by default in the distributed config

• Improves protocol aware login logging with richer asset signature details when available

• Adds documentation for adding and maintaining runtime protocol profiles

• Links the multiprotocol documentation from the systems overview

• Expands build policy guidance so build entry points stay in sync

Validation covered by this commit

• Extended 8 60 client can log in and play with exported extended assets

• Tibia 11 00 old protocol client can log in through the old protocol path

• Modern 15 x client remains supported

• Local Windows release build completed with the Canary target

• Unit tests were added for protocol and profile resolution

• Unit tests were added for transport sizing and header behavior

• Unit tests were added for protocol session hint flows

Overall this commit introduces a runtime multiprotocol architecture for Canary while keeping the existing modern client path as the default. It adds explicit protocol profiles dedicated transport and login contracts automatic session hinting and documentation so multiple client families can be supported safely through one server runtime without changing the compiled client target or splitting traffic across separate ports.
2026-07-01 13:14:58 -03:00

143 lines
3.7 KiB
Bash

#!/bin/bash
# ./config.sh
# ./config.sh maxPlayers 88
# ./config.sh maxPlayers 88 serverName Teste maxItem 5 --file other_name.lua --env .env
# Replace values in .lua file
substitute_lua_variable() {
variable_name="$1"
new_value="$2"
if [[ "$new_value" == "true" || "$new_value" == "false" ]]; then
sed "s|$variable_name =.*|$variable_name = $new_value|" "$lua_file" > "$lua_file.tmp"
elif [[ $( echo "$new_value" | grep -E "^[0-9]+$") ]]; then
sed "s|$variable_name =.*|$variable_name = $new_value|" "$lua_file" > "$lua_file.tmp"
else
sed "s|$variable_name =.*|$variable_name = \"$new_value\"|" "$lua_file" > "$lua_file.tmp"
fi
mv "$lua_file.tmp" "$lua_file" 2>&1
}
# Get a named argument
get_named_arg() {
arg_name="$1"
shift
while [[ $# -gt 0 ]]; do
if [[ $1 == "$arg_name" && $# -gt 1 ]]; then
echo "$2"
return
fi
shift
done
}
lua_file=$( get_named_arg "--file" "$@")
env_file=$( get_named_arg "--env" "$@")
if [ -z "$lua_file" ]; then
lua_file="config.lua"
fi
if [ -z "$env_file" ]; then
env_file=".env"
fi
verify_file() {
if [ ! -f "$1" ]; then
echo "$2 not found"
echo "path: $1"
exit 1
fi
}
verify_file "$env_file" "env"
verify_file "$lua_file" "lua"
# Reads the env file
while IFS='=' read -r key value; do
if [[ "$key" != "#"* && "$key" != "" ]]; then
case $key in
CANARY_DB_HOST)
substitute_lua_variable "mysqlHost" "$value"
;;
CANARY_DB_NAME)
substitute_lua_variable "mysqlDatabase" "$value"
;;
CANARY_DB_USER)
substitute_lua_variable "mysqlUser" "$value"
;;
CANARY_DB_PASSWORD)
substitute_lua_variable "mysqlPass" "$value"
;;
CANARY_DB_PORT)
substitute_lua_variable "mysqlPort" "$value"
;;
CANARY_SERVER_NAME)
substitute_lua_variable "serverName" "$value"
;;
CANARY_SERVER_IP)
substitute_lua_variable "ip" "$value"
;;
CANARY_LOGIN_PORT)
substitute_lua_variable "loginProtocolPort" "$value"
;;
CANARY_GAME_PORT)
substitute_lua_variable "gameProtocolPort" "$value"
;;
CANARY_LEGACY_1100_GAME_PORT)
substitute_lua_variable "legacy1100GameProtocolPort" "$value"
;;
CANARY_LEGACY_860_GAME_PORT)
substitute_lua_variable "legacy860GameProtocolPort" "$value"
;;
CANARY_STATUS_PORT)
substitute_lua_variable "statusProtocolPort" "$value"
;;
CANARY_STATUS_TIMEOUT)
substitute_lua_variable "statusTimeout" "$value"
;;
CANARY_DATA_PACK)
substitute_lua_variable "dataPackDirectory" "$value"
;;
CANARY_MAP_URL)
substitute_lua_variable "mapDownloadUrl" "$value"
;;
MYSQL_HOST)
substitute_lua_variable "mysqlHost" "$value"
;;
MYSQL_DBNAME)
substitute_lua_variable "mysqlDatabase" "$value"
;;
MYSQL_USER)
substitute_lua_variable "mysqlUser" "$value"
;;
MYSQL_PASS)
substitute_lua_variable "mysqlPass" "$value"
;;
SERVER_NAME)
substitute_lua_variable "serverName" "$value"
;;
SERVER_IP)
substitute_lua_variable "ip" "$value"
;;
SERVER_PORT)
substitute_lua_variable "gameProtocolPort" "$value"
;;
*)
substitute_lua_variable "$key" "$value"
;;
esac
fi
done < "$env_file"
# # Substitutes other variables provided as command line arguments
args=("$@")
for ((i=0; i<${#args[@]}; i+=2)); do
if [[ "${args[i]}" == "--file" || "${args[i]}" == "--env" ]]; then
continue
fi
variable_name="${args[i]}"
new_value="${args[i+1]}"
substitute_lua_variable "$variable_name" "$new_value"
done