mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-13 01:08:35 +00:00
Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
2
.github/CODEOWNERS
vendored
Normal file
2
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Protect dashboard workflow – require explicit review
|
||||
.github/workflows/dashboard-ci.yml @Yehonal
|
||||
8
.github/workflows/dashboard-ci.yml
vendored
8
.github/workflows/dashboard-ci.yml
vendored
@@ -54,8 +54,7 @@ jobs:
|
||||
env:
|
||||
TERM: xterm-256color
|
||||
run: |
|
||||
cd apps/test-framework
|
||||
./run-tests.sh --tap --all
|
||||
./acore.sh test bash --tap --all
|
||||
|
||||
build-and-test:
|
||||
name: Build and Integration Test
|
||||
@@ -79,6 +78,7 @@ jobs:
|
||||
cp conf/dist/config.sh conf/config.sh
|
||||
# Configure dashboard
|
||||
sed -i 's/MTHREADS=.*/MTHREADS="4"/' conf/config.sh
|
||||
sed -i 's/CBUILD_TESTING=.*/CBUILD_TESTING="ON"/' conf/config.sh
|
||||
|
||||
- name: Test module commands
|
||||
run: |
|
||||
@@ -105,6 +105,10 @@ jobs:
|
||||
./acore.sh module remove mod-duel-reset
|
||||
./acore.sh module list
|
||||
|
||||
- name: Run core tests
|
||||
run: |
|
||||
./acore.sh test core
|
||||
|
||||
- name: Test authserver dry-run
|
||||
run: |
|
||||
cd env/dist/bin
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
function registerHooks() { acore_event_registerHooks "$@"; }
|
||||
function runHooks() { acore_event_runHooks "$@"; }
|
||||
|
||||
#shellcheck source=../../conf/dist/config.sh
|
||||
source "$AC_PATH_CONF/dist/config.sh" # include dist to avoid missing conf variables
|
||||
|
||||
# first check if it's defined in env, otherwise use the default
|
||||
|
||||
@@ -19,10 +19,10 @@ case $AC_PATH_ROOT in
|
||||
*) AC_PATH_ROOT=$PWD/$AC_PATH_ROOT;;
|
||||
esac
|
||||
|
||||
AC_PATH_CONF="$AC_PATH_ROOT/conf"
|
||||
export AC_PATH_CONF="$AC_PATH_ROOT/conf"
|
||||
|
||||
AC_PATH_MODULES="$AC_PATH_ROOT/modules"
|
||||
export AC_PATH_MODULES="$AC_PATH_ROOT/modules"
|
||||
|
||||
AC_PATH_DEPS="$AC_PATH_ROOT/deps"
|
||||
export AC_PATH_DEPS="$AC_PATH_ROOT/deps"
|
||||
|
||||
AC_PATH_VAR="$AC_PATH_ROOT/var"
|
||||
export AC_PATH_VAR="$AC_PATH_ROOT/var"
|
||||
|
||||
@@ -7,10 +7,17 @@ AC_PATH_APPS="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../" && pwd )"
|
||||
|
||||
AC_PATH_SHARED="$AC_PATH_APPS/bash_shared"
|
||||
|
||||
# shellcheck source=./defines.sh
|
||||
source "$AC_PATH_SHARED/defines.sh"
|
||||
|
||||
# shellcheck source=../../deps/acore/bash-lib/src/event/hooks.sh
|
||||
source "$AC_PATH_DEPS/acore/bash-lib/src/event/hooks.sh"
|
||||
|
||||
# shellcheck source=./common.sh
|
||||
source "$AC_PATH_SHARED/common.sh"
|
||||
|
||||
[[ "$OSTYPE" = "msys" ]] && AC_BINPATH_FULL="$BINPATH" || AC_BINPATH_FULL="$BINPATH/bin"
|
||||
if [[ "$OSTYPE" = "msys" ]]; then
|
||||
AC_BINPATH_FULL="$BINPATH"
|
||||
else
|
||||
export AC_BINPATH_FULL="$BINPATH/bin"
|
||||
fi
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Set SUDO variable - one liner
|
||||
SUDO=$([ "$EUID" -ne 0 ] && echo "sudo" || echo "")
|
||||
SUDO=""
|
||||
|
||||
IS_SUDO_ENABLED=${AC_ENABLE_ROOT_CMAKE_INSTALL:-0}
|
||||
|
||||
# Allow callers to opt-out from privilege escalation during install/perms adjustments
|
||||
if [[ $IS_SUDO_ENABLED == 1 ]]; then
|
||||
SUDO=$([ "$EUID" -ne 0 ] && echo "sudo" || echo "")
|
||||
fi
|
||||
|
||||
function comp_clean() {
|
||||
DIRTOCLEAN=${BUILDPATH:-var/build/obj}
|
||||
@@ -143,9 +150,13 @@ function comp_compile() {
|
||||
popd >> /dev/null || exit 1
|
||||
|
||||
# set all aplications SUID bit
|
||||
echo "Setting permissions on binary files"
|
||||
find "$AC_BINPATH_FULL" -mindepth 1 -maxdepth 1 -type f -exec $SUDO chown root:root -- {} +
|
||||
find "$AC_BINPATH_FULL" -mindepth 1 -maxdepth 1 -type f -exec $SUDO chmod u+s -- {} +
|
||||
if [[ $IS_SUDO_ENABLED == 0 ]]; then
|
||||
echo "Skipping root ownership and SUID changes (IS_SUDO_ENABLED=0)"
|
||||
else
|
||||
echo "Setting permissions on binary files"
|
||||
find "$AC_BINPATH_FULL" -mindepth 1 -maxdepth 1 -type f -exec $SUDO chown root:root -- {} +
|
||||
find "$AC_BINPATH_FULL" -mindepth 1 -maxdepth 1 -type f -exec $SUDO chmod u+s -- {} +
|
||||
fi
|
||||
|
||||
[[ -f "$confDir/worldserver.conf.dist" ]] && \
|
||||
cp -v --no-clobber "$confDir/worldserver.conf.dist" "$confDir/worldserver.conf"
|
||||
|
||||
@@ -41,6 +41,7 @@ menu_items=(
|
||||
"client-data|gd|download client data from github repository (beta)"
|
||||
"run-worldserver|rw|execute a simple restarter for worldserver"
|
||||
"run-authserver|ra|execute a simple restarter for authserver"
|
||||
"test|t|Run test framework"
|
||||
"docker|dr|Run docker tools"
|
||||
"version|v|Show AzerothCore version"
|
||||
"service-manager|sm|Run service manager to run authserver and worldserver in background"
|
||||
@@ -84,6 +85,9 @@ function handle_menu_command() {
|
||||
"run-authserver")
|
||||
inst_simple_restarter authserver
|
||||
;;
|
||||
"test")
|
||||
bash "$AC_PATH_APPS/test-framework/test-main.sh" "$@"
|
||||
;;
|
||||
"docker")
|
||||
DOCKER=1 bash "$AC_PATH_ROOT/apps/docker/docker-cmd.sh" "$@"
|
||||
exit
|
||||
|
||||
@@ -6,7 +6,9 @@ This is the centralized test framework for all AzerothCore bash scripts. It prov
|
||||
|
||||
```
|
||||
apps/test-framework/
|
||||
├── run-tests.sh # Universal test runner (single entry point)
|
||||
├── test-main.sh # Unified test framework entry point
|
||||
├── run-bash-tests.sh # Bash test runner for BATS tests
|
||||
├── run-core-tests.sh # AzerothCore unit test runner
|
||||
├── README.md # This documentation
|
||||
├── bats_libs/ # Custom BATS libraries
|
||||
│ ├── acore-support.bash # Test setup and helpers
|
||||
@@ -17,38 +19,74 @@ apps/test-framework/
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Using acore.sh (Recommended):
|
||||
```bash
|
||||
# Run the unified test framework (interactive menu)
|
||||
./acore.sh test
|
||||
|
||||
# Run bash tests directly
|
||||
./acore.sh test bash --all
|
||||
|
||||
# Run AzerothCore unit tests
|
||||
./acore.sh test core
|
||||
```
|
||||
|
||||
### From any module directory:
|
||||
```bash
|
||||
# Run tests for current module
|
||||
../test-framework/run-tests.sh --dir .
|
||||
../test-framework/run-bash-tests.sh --dir .
|
||||
|
||||
```
|
||||
|
||||
### From test-framework directory:
|
||||
```bash
|
||||
# Run all tests in all modules
|
||||
./run-tests.sh --all
|
||||
./run-bash-tests.sh --all
|
||||
|
||||
# Run tests for specific module
|
||||
./run-tests.sh startup-scripts
|
||||
./run-bash-tests.sh startup-scripts
|
||||
|
||||
# List available modules
|
||||
./run-tests.sh --list
|
||||
./run-bash-tests.sh --list
|
||||
|
||||
# Run tests with debug info
|
||||
./run-tests.sh --all --debug
|
||||
./run-bash-tests.sh --all --debug
|
||||
```
|
||||
|
||||
### From project root:
|
||||
```bash
|
||||
# Run all tests
|
||||
apps/test-framework/run-tests.sh --all
|
||||
apps/test-framework/run-bash-tests.sh --all
|
||||
|
||||
# Run specific module
|
||||
apps/test-framework/run-tests.sh startup-scripts
|
||||
apps/test-framework/run-bash-tests.sh startup-scripts
|
||||
|
||||
# Run with verbose output
|
||||
apps/test-framework/run-tests.sh startup-scripts --verbose
|
||||
apps/test-framework/run-bash-tests.sh startup-scripts --verbose
|
||||
```
|
||||
|
||||
## Test Types
|
||||
|
||||
The framework now supports two types of tests:
|
||||
|
||||
1. **Bash Tests** - BATS-based tests for bash scripts and functionality
|
||||
2. **Core Tests** - AzerothCore C++ unit tests
|
||||
|
||||
### Unified Test Framework
|
||||
|
||||
The test framework provides a unified entry point through `test-main.sh` which presents an interactive menu:
|
||||
|
||||
- **bash**: Run BATS-based bash script tests
|
||||
- **core**: Run AzerothCore C++ unit tests
|
||||
- **quit**: Exit the test framework
|
||||
|
||||
```bash
|
||||
# Interactive test menu
|
||||
./acore.sh test
|
||||
|
||||
# Direct test execution
|
||||
./acore.sh test bash --all # Run all bash tests
|
||||
./acore.sh test core # Run core unit tests
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -57,35 +95,35 @@ apps/test-framework/run-tests.sh startup-scripts --verbose
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
./run-tests.sh --all
|
||||
./run-bash-tests.sh --all
|
||||
|
||||
# Run tests for specific module
|
||||
./run-tests.sh startup-scripts
|
||||
./run-bash-tests.sh startup-scripts
|
||||
|
||||
# Run tests matching pattern
|
||||
./run-tests.sh --filter starter
|
||||
./run-bash-tests.sh --filter starter
|
||||
|
||||
# Run tests in specific directory
|
||||
./run-tests.sh --dir apps/docker
|
||||
./run-bash-tests.sh --dir apps/docker
|
||||
|
||||
# Show available modules
|
||||
./run-tests.sh --list
|
||||
./run-bash-tests.sh --list
|
||||
|
||||
# Show test count
|
||||
./run-tests.sh --count
|
||||
./run-bash-tests.sh --count
|
||||
```
|
||||
|
||||
### Output Formats
|
||||
|
||||
```bash
|
||||
# Pretty output (default)
|
||||
./run-tests.sh --pretty
|
||||
./run-bash-tests.sh --pretty
|
||||
|
||||
# TAP output for CI/CD
|
||||
./run-tests.sh --tap
|
||||
./run-bash-tests.sh --tap
|
||||
|
||||
# Verbose output with debug info
|
||||
./run-tests.sh --verbose --debug
|
||||
./run-bash-tests.sh --verbose --debug
|
||||
```
|
||||
|
||||
## Writing Tests
|
||||
@@ -205,17 +243,17 @@ debug_on_failure
|
||||
|
||||
From your module directory:
|
||||
```bash
|
||||
../test-framework/run-tests.sh --dir .
|
||||
../test-framework/run-bash-tests.sh --dir .
|
||||
```
|
||||
|
||||
From the test framework:
|
||||
```bash
|
||||
./run-tests.sh my-module
|
||||
./run-bash-tests.sh my-module
|
||||
```
|
||||
|
||||
From project root:
|
||||
```bash
|
||||
apps/test-framework/run-tests.sh my-module
|
||||
apps/test-framework/run-bash-tests.sh my-module
|
||||
```
|
||||
|
||||
## CI/CD Integration
|
||||
@@ -223,37 +261,73 @@ apps/test-framework/run-tests.sh my-module
|
||||
For continuous integration, use TAP output:
|
||||
|
||||
```bash
|
||||
# In your CI script
|
||||
# Recommended: Use acore.sh integration
|
||||
./acore.sh test bash --tap --all > test-results.tap
|
||||
|
||||
# Direct script usage
|
||||
cd apps/test-framework
|
||||
./run-tests.sh --all --tap > test-results.tap
|
||||
./run-bash-tests.sh --all --tap > test-results.tap
|
||||
|
||||
# Or from project root
|
||||
apps/test-framework/run-tests.sh --all --tap > test-results.tap
|
||||
apps/test-framework/run-bash-tests.sh --all --tap > test-results.tap
|
||||
|
||||
# Run core unit tests in CI
|
||||
./acore.sh test core
|
||||
```
|
||||
|
||||
## Core Tests
|
||||
|
||||
The framework now includes support for AzerothCore's C++ unit tests through `run-core-tests.sh`:
|
||||
|
||||
```bash
|
||||
# Run core unit tests
|
||||
./acore.sh test core
|
||||
|
||||
# Direct script usage
|
||||
apps/test-framework/run-core-tests.sh
|
||||
```
|
||||
|
||||
**Prerequisites for Core Tests:**
|
||||
- Project must be built with unit tests enabled (`CBUILD_TESTING="ON"` inside `conf/config.sh` that works with the acore.sh compiler)
|
||||
- Unit test binary should be available at `$BUILDPATH/src/test/unit_tests`
|
||||
|
||||
The core test runner will:
|
||||
1. Check if the unit test binary exists
|
||||
2. Execute the AzerothCore unit tests
|
||||
3. Return appropriate exit codes for CI/CD integration
|
||||
|
||||
## Available Commands
|
||||
|
||||
All functionality is available through the single `run-tests.sh` script:
|
||||
### Unified Test Framework Commands
|
||||
|
||||
Recommended usage through `acore.sh`:
|
||||
- `./acore.sh test` - Interactive test framework menu
|
||||
- `./acore.sh test bash [options]` - Run bash tests with options
|
||||
- `./acore.sh test core` - Run AzerothCore unit tests
|
||||
|
||||
### Bash Test Commands
|
||||
|
||||
All bash test functionality is available through the `run-bash-tests.sh` script:
|
||||
|
||||
### Basic Test Execution
|
||||
- `./run-tests.sh --all` - Run all tests in all modules
|
||||
- `./run-tests.sh <module>` - Run tests for specific module
|
||||
- `./run-tests.sh --dir <path>` - Run tests in specific directory
|
||||
- `./run-tests.sh --list` - List available modules
|
||||
- `./run-tests.sh --count` - Show test count
|
||||
- `./run-bash-tests.sh --all` - Run all tests in all modules
|
||||
- `./run-bash-tests.sh <module>` - Run tests for specific module
|
||||
- `./run-bash-tests.sh --dir <path>` - Run tests in specific directory
|
||||
- `./run-bash-tests.sh --list` - List available modules
|
||||
- `./run-bash-tests.sh --count` - Show test count
|
||||
|
||||
### Output Control
|
||||
- `./run-tests.sh --verbose` - Verbose output with debug info
|
||||
- `./run-tests.sh --tap` - TAP output for CI/CD
|
||||
- `./run-tests.sh --debug` - Debug mode with failure details
|
||||
- `./run-tests.sh --pretty` - Pretty output (default)
|
||||
- `./run-bash-tests.sh --verbose` - Verbose output with debug info
|
||||
- `./run-bash-tests.sh --tap` - TAP output for CI/CD
|
||||
- `./run-bash-tests.sh --debug` - Debug mode with failure details
|
||||
- `./run-bash-tests.sh --pretty` - Pretty output (default)
|
||||
|
||||
### Test Filtering
|
||||
- `./run-tests.sh --filter <pattern>` - Run tests matching pattern
|
||||
- `./run-tests.sh <module> --filter <pattern>` - Filter within module
|
||||
- `./run-bash-tests.sh --filter <pattern>` - Run tests matching pattern
|
||||
- `./run-bash-tests.sh <module> --filter <pattern>` - Filter within module
|
||||
|
||||
### Utility Functions
|
||||
- `./run-tests.sh --help` - Show help message
|
||||
- `./run-bash-tests.sh --help` - Show help message
|
||||
- Install BATS: Use your system package manager (`apt install bats`, `brew install bats-core`, etc.)
|
||||
|
||||
|
||||
@@ -264,35 +338,42 @@ All functionality is available through the single `run-tests.sh` script:
|
||||
### Running Specific Tests
|
||||
```bash
|
||||
# Run only starter-related tests
|
||||
./run-tests.sh --filter starter
|
||||
./run-bash-tests.sh --filter starter
|
||||
|
||||
# Run only tests in startup-scripts module
|
||||
./run-tests.sh startup-scripts
|
||||
./run-bash-tests.sh startup-scripts
|
||||
|
||||
# Run all tests with verbose output
|
||||
./run-tests.sh --all --verbose
|
||||
./run-bash-tests.sh --all --verbose
|
||||
|
||||
# Run tests in specific directory with debug
|
||||
./run-tests.sh --dir apps/docker --debug
|
||||
./run-bash-tests.sh --dir apps/docker --debug
|
||||
```
|
||||
|
||||
### Development Workflow
|
||||
```bash
|
||||
# Recommended: Use acore.sh for unified testing
|
||||
./acore.sh test # Interactive menu
|
||||
./acore.sh test bash --all # All bash tests
|
||||
./acore.sh test core # Core unit tests
|
||||
|
||||
# While developing, run tests frequently from module directory
|
||||
cd apps/my-module
|
||||
../test-framework/run-tests.sh --dir .
|
||||
../test-framework/run-bash-tests.sh --dir .
|
||||
|
||||
# Debug failing tests
|
||||
../test-framework/run-tests.sh --dir . --debug --verbose
|
||||
../test-framework/run-bash-tests.sh --dir . --debug --verbose
|
||||
|
||||
# Run specific test pattern
|
||||
../test-framework/run-tests.sh --dir . --filter my-feature
|
||||
../test-framework/run-bash-tests.sh --dir . --filter my-feature
|
||||
|
||||
# From project root - run all tests
|
||||
apps/test-framework/run-tests.sh --all
|
||||
./acore.sh test bash --all # Recommended
|
||||
apps/test-framework/run-bash-tests.sh --all # Direct
|
||||
|
||||
# Quick test count check
|
||||
apps/test-framework/run-tests.sh --count
|
||||
./acore.sh test bash --count # Recommended
|
||||
apps/test-framework/run-bash-tests.sh --count # Direct
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
20
apps/test-framework/run-core-tests.sh
Normal file
20
apps/test-framework/run-core-tests.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source-path=SCRIPTDIR
|
||||
CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
# Clean up gcda files to avoid false positives in coverage reports
|
||||
find var/build/obj -name '*.gcda' -delete
|
||||
|
||||
# shellcheck source=../bash_shared/includes.sh
|
||||
source "$CURRENT_PATH/../bash_shared/includes.sh"
|
||||
|
||||
TEST_PATH="$BUILDPATH/src/test/unit_tests"
|
||||
|
||||
if [[ ! -f "$TEST_PATH" ]]; then
|
||||
echo "Unit test binary not found at $TEST_PATH"
|
||||
echo "Please ensure the project is built with unit tests enabled."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec "$TEST_PATH" "$@"
|
||||
45
apps/test-framework/test-main.sh
Normal file
45
apps/test-framework/test-main.sh
Normal file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source-path=SCRIPTDIR
|
||||
CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
# shellcheck source=../bash_shared/includes.sh
|
||||
source "$CURRENT_PATH/../bash_shared/includes.sh"
|
||||
# shellcheck source=../bash_shared/menu_system.sh
|
||||
source "$AC_PATH_APPS/bash_shared/menu_system.sh"
|
||||
|
||||
# Menu: single ordered source of truth (no functions in strings)
|
||||
# Format: "key|short|description"
|
||||
menu_items=(
|
||||
"bash|b|Run Bash tests"
|
||||
"core|c|Run AzerothCore tests"
|
||||
"quit|q|Exit from this menu"
|
||||
)
|
||||
|
||||
|
||||
# Menu command handler - called by menu system for each command
|
||||
function handle_menu_command() {
|
||||
local key="$1"
|
||||
shift
|
||||
|
||||
case "$key" in
|
||||
"bash")
|
||||
bash "$CURRENT_PATH/run-bash-tests.sh" "${@:-"--all"}"
|
||||
;;
|
||||
"core")
|
||||
# shellcheck source=./run-core-tests.sh
|
||||
bash "$CURRENT_PATH/run-core-tests.sh" "$@"
|
||||
;;
|
||||
"quit")
|
||||
echo "Goodbye!"
|
||||
exit
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option. Use --help to see available commands."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Run the menu system
|
||||
menu_run_with_items "TEST FRAMEWORK" handle_menu_command -- "${menu_items[@]}" -- "$@"
|
||||
9
conf/dist/config.sh
vendored
9
conf/dist/config.sh
vendored
@@ -108,6 +108,15 @@ CCUSTOMOPTIONS=${CCUSTOMOPTIONS:-''}
|
||||
AC_CCACHE=${AC_CCACHE:-false}
|
||||
export CCACHE_DIR=${CCACHE_DIR:-"$AC_PATH_VAR/ccache"}
|
||||
|
||||
#
|
||||
# Enable running the cmake install as root
|
||||
# Installing as root allows to set the SUID bit on
|
||||
# the worldserver binary. This is required if you want
|
||||
# to bind the worldserver to reserved ports
|
||||
# Default: 0 (false)
|
||||
#
|
||||
export AC_ENABLE_ROOT_CMAKE_INSTALL=${AC_ENABLE_ROOT_CMAKE_INSTALL:-0}
|
||||
|
||||
##############################################
|
||||
#
|
||||
# GOOGLE PERF TOOLS
|
||||
|
||||
8
data/sql/updates/db_world/2025_09_26_00.sql
Normal file
8
data/sql/updates/db_world/2025_09_26_00.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
-- DB update 2025_09_23_03 -> 2025_09_26_00
|
||||
--
|
||||
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 28600;
|
||||
DELETE FROM `waypoint_scripts` WHERE `guid`=776;
|
||||
UPDATE `waypoint_data` SET `action`=0 WHERE `id`=1133640 AND `point`=3;
|
||||
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = -113364);
|
||||
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(-113364, 0, 0, 0, 108, 0, 100, 0, 3, 1133640, 0, 0, 0, 0, 11, 52059, 0, 0, 0, 0, 0, 9, 28387, 0, 30, 0, 0, 0, 0, 0, 'Heb\'Drakkar Headhunter - On Point 3 of Path 1133640 Reached - Cast \'Axe Throw\'');
|
||||
4
data/sql/updates/db_world/2025_09_26_01.sql
Normal file
4
data/sql/updates/db_world/2025_09_26_01.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- DB update 2025_09_26_00 -> 2025_09_26_01
|
||||
|
||||
-- Remove Phase Mask 1 and add Phasemask 2.
|
||||
UPDATE `creature` SET `phaseMask` = `phaseMask` &~1 | 2 WHERE `id1` = 28529 AND `guid` IN (128641,128697);
|
||||
3
data/sql/updates/db_world/2025_09_27_00.sql
Normal file
3
data/sql/updates/db_world/2025_09_27_00.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
-- DB update 2025_09_26_01 -> 2025_09_27_00
|
||||
--
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 12863 WHERE (`ID` = 12865);
|
||||
3
data/sql/updates/db_world/2025_09_27_01.sql
Normal file
3
data/sql/updates/db_world/2025_09_27_01.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
-- DB update 2025_09_27_00 -> 2025_09_27_01
|
||||
--
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 12917 WHERE (`ID` = 12920);
|
||||
3
data/sql/updates/db_world/2025_09_27_02.sql
Normal file
3
data/sql/updates/db_world/2025_09_27_02.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
-- DB update 2025_09_27_01 -> 2025_09_27_02
|
||||
--
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 12854 WHERE (`ID` = 12855);
|
||||
60
data/sql/updates/db_world/2025_09_27_03.sql
Normal file
60
data/sql/updates/db_world/2025_09_27_03.sql
Normal file
@@ -0,0 +1,60 @@
|
||||
-- DB update 2025_09_27_02 -> 2025_09_27_03
|
||||
--
|
||||
-- Fjorlin Frostbrow SAI
|
||||
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29732);
|
||||
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(29732, 0, 0, 1, 62, 0, 100, 0, 9891, 0, 0, 0, 0, 0, 11, 56411, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Fjorlin Frostbrow - On Gossip Option 0 Selected - Cast \'Forcecast Summon Scripted Eagle\''),
|
||||
(29732, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Fjorlin Frostbrow - On Gossip Option 0 Selected - Close Gossip'),
|
||||
(29732, 0, 2, 3, 62, 0, 100, 0, 9891, 1, 0, 0, 0, 0, 11, 57049, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Fjorlin Frostbrow - On Gossip Option 1 Selected - Self Cast \'Forcecast Summon Battle Eagle\''),
|
||||
(29732, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Fjorlin Frostbrow - On Gossip Option 1 Selected - Close Gossip');
|
||||
|
||||
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 15) AND (`SourceGroup` = 9891) AND (`SourceEntry` = 0) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` IN (8, 9)) AND (`ConditionTarget` = 0) AND (`ConditionValue2` = 0) AND (`ConditionValue3` = 0);
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||
(15, 9891, 0, 0, 0, 9, 0, 12874, 0, 0, 0, 0, 0, '', 'Show Frostborn gossip only when on quest \'Fervor of the Frostborn\' 12874');
|
||||
|
||||
-- 29736 Stormcrest Eagle (Scripted)
|
||||
UPDATE `creature_template` SET `vehicleId`=196 WHERE `entry`=29736;
|
||||
|
||||
DELETE FROM `vehicle_template_accessory` WHERE `entry`=29736 AND `accessory_entry` IN (30401);
|
||||
INSERT INTO `vehicle_template_accessory` (`entry`,`accessory_entry`,`seat_id`,`minion`,`description`,`summontype`,`summontimer`) VALUES
|
||||
(29736, 30401, 0, 1, 'Stormcrest Eagle (Scripted)', 8, 0);
|
||||
|
||||
DELETE FROM `creature_template_spell` WHERE (`CreatureID` = 29736);
|
||||
|
||||
DELETE FROM `npc_spellclick_spells` WHERE `npc_entry`=29736;
|
||||
INSERT INTO `npc_spellclick_spells` (`npc_entry`, `spell_id`, `cast_flags`, `user_type`) VALUES
|
||||
(29736, 46598, 1, 0);
|
||||
|
||||
DELETE FROM `creature_template_addon` WHERE `entry`=29736;
|
||||
INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES
|
||||
(29736, 0, 0, 0, 1, 0, '52211');
|
||||
|
||||
DELETE FROM `spell_target_position` WHERE `id`=55942;
|
||||
INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`, `VerifiedBuild`) VALUES
|
||||
(55942, 0, 571, 6610.838379, -280.558685, 984.428772, 3.598404, 0);
|
||||
|
||||
DELETE FROM `waypoints` WHERE `entry`=29736 AND `pointid`=37;
|
||||
INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
|
||||
(29736, 37, 8405.069, -2071.5032, 1498.8086, 'Stormcrest eagle, Fervor of the Frostborn');
|
||||
|
||||
-- Updated comments with Keira. Added eject and despawn
|
||||
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29736);
|
||||
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(29736, 0, 0, 0, 60, 0, 100, 513, 1000, 1000, 0, 0, 0, 0, 53, 1, 29736, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Update - Start Waypoint Path 29736 (No Repeat)'),
|
||||
(29736, 0, 1, 0, 27, 0, 100, 512, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Passenger Boarded - Set Npc Flag '),
|
||||
(29736, 0, 2, 0, 40, 0, 100, 512, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 3 of Path Any Reached - Say Line 0'),
|
||||
(29736, 0, 3, 0, 40, 0, 100, 512, 7, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 7 of Path Any Reached - Say Line 1'),
|
||||
(29736, 0, 4, 0, 40, 0, 100, 512, 10, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 10 of Path Any Reached - Say Line 2'),
|
||||
(29736, 0, 5, 0, 40, 0, 100, 512, 13, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 13 of Path Any Reached - Say Line 3'),
|
||||
(29736, 0, 6, 0, 40, 0, 100, 512, 15, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 15 of Path Any Reached - Say Line 4'),
|
||||
(29736, 0, 7, 0, 40, 0, 100, 512, 17, 0, 0, 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 17 of Path Any Reached - Say Line 5'),
|
||||
(29736, 0, 8, 0, 40, 0, 100, 512, 19, 0, 0, 0, 0, 0, 1, 6, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 19 of Path Any Reached - Say Line 6'),
|
||||
(29736, 0, 9, 0, 40, 0, 100, 512, 22, 0, 0, 0, 0, 0, 1, 7, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 22 of Path Any Reached - Say Line 7'),
|
||||
(29736, 0, 10, 0, 40, 0, 100, 512, 24, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 24 of Path Any Reached - Say Line 8'),
|
||||
(29736, 0, 11, 0, 40, 0, 100, 512, 28, 0, 0, 0, 0, 0, 1, 9, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 28 of Path Any Reached - Say Line 9'),
|
||||
(29736, 0, 12, 0, 40, 0, 100, 512, 30, 0, 0, 0, 0, 0, 1, 10, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 30 of Path Any Reached - Say Line 10'),
|
||||
(29736, 0, 13, 0, 40, 0, 100, 512, 32, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 32 of Path Any Reached - Say Line 11'),
|
||||
(29736, 0, 14, 0, 40, 0, 100, 512, 34, 0, 0, 0, 0, 0, 1, 12, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 34 of Path Any Reached - Say Line 12'),
|
||||
(29736, 0, 15, 16, 40, 0, 100, 512, 36, 0, 0, 0, 0, 0, 1, 13, 0, 0, 0, 0, 0, 19, 30401, 20, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 36 of Path Any Reached - Say Line 13'),
|
||||
(29736, 0, 16, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 11, 62539, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 36 of Path Any Reached - Cast \'Eject Passenger 2\''),
|
||||
(29736, 0, 17, 0, 40, 0, 100, 512, 37, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Stormcrest Eagle - On Point 37 of Path Any Reached - Despawn Instant');
|
||||
@@ -640,7 +640,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
|
||||
Unit* caster = me;
|
||||
// Areatrigger Cast!
|
||||
if (e.GetScriptType() == SMART_SCRIPT_TYPE_AREATRIGGER)
|
||||
if (e.IsAreatriggerScript())
|
||||
caster = unit->SummonTrigger(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetOrientation(), 5000);
|
||||
|
||||
if (e.action.cast.targetsLimit)
|
||||
@@ -3990,27 +3990,29 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
||||
}
|
||||
case SMART_TARGET_INSTANCE_STORAGE:
|
||||
{
|
||||
if (InstanceScript* instance = GetBaseObject()->GetInstanceScript())
|
||||
{
|
||||
if (e.target.instanceStorage.type == 1)
|
||||
{
|
||||
if (Creature* creature = instance->GetCreature(e.target.instanceStorage.index))
|
||||
{
|
||||
targets.push_back(creature);
|
||||
}
|
||||
}
|
||||
else if (e.target.instanceStorage.type == 2)
|
||||
{
|
||||
if (GameObject* go = instance->GetGameObject(e.target.instanceStorage.index))
|
||||
{
|
||||
targets.push_back(go);
|
||||
}
|
||||
}
|
||||
}
|
||||
InstanceScript* instance = nullptr;
|
||||
|
||||
if (e.IsAreatriggerScript() && scriptTrigger)
|
||||
instance = scriptTrigger->GetInstanceScript();
|
||||
else
|
||||
instance = GetBaseObject()->GetInstanceScript();
|
||||
|
||||
if (!instance)
|
||||
{
|
||||
LOG_ERROR("scripts.ai.sai", "SMART_TARGET_INSTANCE_STORAGE: Entry {} SourceType {} Event {} Action {} Target {} called outside an instance map.",
|
||||
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.target.instanceStorage.type == 1)
|
||||
{
|
||||
if (Creature* creature = instance->GetCreature(e.target.instanceStorage.index))
|
||||
targets.push_back(creature);
|
||||
}
|
||||
else if (e.target.instanceStorage.type == 2)
|
||||
{
|
||||
if (GameObject* go = instance->GetGameObject(e.target.instanceStorage.index))
|
||||
targets.push_back(go);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -1993,6 +1993,8 @@ public:
|
||||
uint32 GetActionType() const { return (uint32)action.type; }
|
||||
uint32 GetTargetType() const { return (uint32)target.type; }
|
||||
|
||||
[[nodiscard]] bool IsAreatriggerScript() const { return source_type == SMART_SCRIPT_TYPE_AREATRIGGER; }
|
||||
|
||||
uint32 timer;
|
||||
uint32 priority;
|
||||
bool active;
|
||||
|
||||
@@ -2243,7 +2243,7 @@ void Player::SetGameMaster(bool on)
|
||||
CombatStopWithPets();
|
||||
|
||||
SetPhaseMask(uint32(PHASEMASK_ANYWHERE), false); // see and visible in all phases
|
||||
m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GM, GetSession()->GetSecurity());
|
||||
SetServerSideVisibilityDetect(SERVERSIDE_VISIBILITY_GM, GetSession()->GetSecurity());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2279,7 +2279,7 @@ void Player::SetGameMaster(bool on)
|
||||
UpdateArea(m_areaUpdateId);
|
||||
|
||||
getHostileRefMgr().setOnlineOfflineState(true);
|
||||
m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GM, SEC_PLAYER);
|
||||
SetServerSideVisibilityDetect(SERVERSIDE_VISIBILITY_GM, SEC_PLAYER);
|
||||
}
|
||||
|
||||
UpdateObjectVisibility();
|
||||
@@ -2293,7 +2293,7 @@ void Player::SetGMVisible(bool on)
|
||||
{
|
||||
RemoveAurasDueToSpell(VISUAL_AURA);
|
||||
m_ExtraFlags &= ~PLAYER_EXTRA_GM_INVISIBLE;
|
||||
m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GM, SEC_PLAYER);
|
||||
SetServerSideVisibility(SERVERSIDE_VISIBILITY_GM, SEC_PLAYER);
|
||||
|
||||
getHostileRefMgr().setOnlineOfflineState(false);
|
||||
CombatStopWithPets();
|
||||
@@ -2302,7 +2302,7 @@ void Player::SetGMVisible(bool on)
|
||||
{
|
||||
AddAura(VISUAL_AURA, this);
|
||||
m_ExtraFlags |= PLAYER_EXTRA_GM_INVISIBLE;
|
||||
m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GM, GetSession()->GetSecurity());
|
||||
SetServerSideVisibility(SERVERSIDE_VISIBILITY_GM, GetSession()->GetSecurity());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
void AddScripts() {}
|
||||
inline void AddScripts() {}
|
||||
|
||||
class WorldMock: public IWorld
|
||||
{
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "ArenaSeasonRewardsDistributor.h"
|
||||
#include "WorldMock.h"
|
||||
#include <memory>
|
||||
|
||||
class MockArenaSeasonTeamRewarder : public ArenaSeasonTeamRewarder
|
||||
{
|
||||
@@ -31,12 +33,26 @@ class ArenaSeasonRewardDistributorTest : public ::testing::Test
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
_previousWorld = std::move(sWorld);
|
||||
_worldMock = new ::testing::NiceMock<WorldMock>();
|
||||
ON_CALL(*_worldMock, getIntConfig(::testing::_)).WillByDefault(::testing::Return(0));
|
||||
ON_CALL(*_worldMock, getIntConfig(CONFIG_LEGACY_ARENA_START_RATING)).WillByDefault(::testing::Return(1500));
|
||||
ON_CALL(*_worldMock, getIntConfig(CONFIG_ARENA_START_RATING)).WillByDefault(::testing::Return(0));
|
||||
sWorld.reset(_worldMock);
|
||||
|
||||
_mockRewarder = std::make_unique<MockArenaSeasonTeamRewarder>();
|
||||
_distributor = std::make_unique<ArenaSeasonRewardDistributor>(_mockRewarder.get());
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
sWorld = std::move(_previousWorld);
|
||||
}
|
||||
|
||||
std::unique_ptr<MockArenaSeasonTeamRewarder> _mockRewarder;
|
||||
std::unique_ptr<ArenaSeasonRewardDistributor> _distributor;
|
||||
std::unique_ptr<IWorld> _previousWorld;
|
||||
::testing::NiceMock<WorldMock>* _worldMock = nullptr;
|
||||
};
|
||||
|
||||
ArenaTeam ArenaTeamWithRating(int rating, int gamesPlayed)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "ArenaTeamMgr.h"
|
||||
#include "ArenaTeam.h"
|
||||
#include <memory>
|
||||
#include "WorldMock.h"
|
||||
|
||||
// Used to expose Type property.
|
||||
class ArenaTeamTest : public ArenaTeam
|
||||
@@ -46,6 +47,13 @@ class ArenaTeamFilterTest : public ::testing::Test
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
_previousWorld = std::move(sWorld);
|
||||
_worldMock = new ::testing::NiceMock<WorldMock>();
|
||||
ON_CALL(*_worldMock, getIntConfig(::testing::_)).WillByDefault(::testing::Return(0));
|
||||
ON_CALL(*_worldMock, getIntConfig(CONFIG_LEGACY_ARENA_START_RATING)).WillByDefault(::testing::Return(1500));
|
||||
ON_CALL(*_worldMock, getIntConfig(CONFIG_ARENA_START_RATING)).WillByDefault(::testing::Return(0));
|
||||
sWorld.reset(_worldMock);
|
||||
|
||||
team1 = ArenaTeamWithType(2); // 2v2
|
||||
team2 = ArenaTeamWithType(3); // 3v3
|
||||
team3 = ArenaTeamWithType(5); // 5v5
|
||||
@@ -60,12 +68,16 @@ protected:
|
||||
delete team1;
|
||||
delete team2;
|
||||
delete team3;
|
||||
|
||||
sWorld = std::move(_previousWorld);
|
||||
}
|
||||
|
||||
ArenaTeamMgr::ArenaTeamContainer arenaTeams;
|
||||
ArenaTeam* team1;
|
||||
ArenaTeam* team2;
|
||||
ArenaTeam* team3;
|
||||
std::unique_ptr<IWorld> _previousWorld;
|
||||
::testing::NiceMock<WorldMock>* _worldMock = nullptr;
|
||||
};
|
||||
|
||||
// Test for ArenaTeamFilterAllTeams: it should return all teams without filtering
|
||||
|
||||
218
src/test/server/game/Commands/GmVisibleCommandTest.cpp
Normal file
218
src/test/server/game/Commands/GmVisibleCommandTest.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by the
|
||||
* Free Software Foundation; either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "WorldSession.h"
|
||||
#include "WorldMock.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "ScriptDefines/MiscScript.h"
|
||||
#include "ScriptDefines/PlayerScript.h"
|
||||
#include "ScriptDefines/WorldObjectScript.h"
|
||||
#include "ScriptDefines/UnitScript.h"
|
||||
#include "ScriptDefines/CommandScript.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#ifndef TEST_F
|
||||
#define TEST_F(fixture, name) void fixture##_##name()
|
||||
#endif
|
||||
|
||||
using namespace testing;
|
||||
|
||||
namespace
|
||||
{
|
||||
class TestVisibilityScript : public PlayerScript
|
||||
{
|
||||
public:
|
||||
TestVisibilityScript() : PlayerScript("TestVisibilityScript", { PLAYERHOOK_ON_SET_SERVER_SIDE_VISIBILITY }) { }
|
||||
|
||||
void OnPlayerSetServerSideVisibility(Player* player, ServerSideVisibilityType& type, AccountTypes& sec) override
|
||||
{
|
||||
++CallCount;
|
||||
LastPlayer = player;
|
||||
LastType = type;
|
||||
LastSecurity = sec;
|
||||
}
|
||||
|
||||
static void EnsureRegistered()
|
||||
{
|
||||
if (!Instance)
|
||||
Instance = new TestVisibilityScript();
|
||||
}
|
||||
|
||||
static void Reset()
|
||||
{
|
||||
CallCount = 0;
|
||||
LastPlayer = nullptr;
|
||||
LastType = SERVERSIDE_VISIBILITY_GM;
|
||||
LastSecurity = SEC_PLAYER;
|
||||
}
|
||||
|
||||
inline static TestVisibilityScript* Instance = nullptr;
|
||||
inline static uint32 CallCount = 0;
|
||||
inline static Player* LastPlayer = nullptr;
|
||||
inline static ServerSideVisibilityType LastType = SERVERSIDE_VISIBILITY_GM;
|
||||
inline static AccountTypes LastSecurity = SEC_PLAYER;
|
||||
};
|
||||
|
||||
class TestPlayer : public Player
|
||||
{
|
||||
public:
|
||||
using Player::Player;
|
||||
|
||||
void UpdateObjectVisibility(bool /*forced*/ = true, bool /*fromUpdate*/ = false) override { }
|
||||
|
||||
void ForceInitValues(ObjectGuid::LowType guidLow = 1)
|
||||
{
|
||||
Object::_Create(guidLow, uint32(0), HighGuid::Player);
|
||||
}
|
||||
};
|
||||
|
||||
class GmVisibleCommandTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
EnsureScriptRegistriesInitialized();
|
||||
|
||||
TestVisibilityScript::EnsureRegistered();
|
||||
|
||||
originalWorld = sWorld.release();
|
||||
worldMock = new NiceMock<WorldMock>();
|
||||
sWorld.reset(worldMock);
|
||||
|
||||
static std::string emptyString;
|
||||
ON_CALL(*worldMock, GetDataPath()).WillByDefault(ReturnRef(emptyString));
|
||||
ON_CALL(*worldMock, GetRealmName()).WillByDefault(ReturnRef(emptyString));
|
||||
ON_CALL(*worldMock, GetDefaultDbcLocale()).WillByDefault(Return(LOCALE_enUS));
|
||||
ON_CALL(*worldMock, getRate(_)).WillByDefault(Return(1.0f));
|
||||
ON_CALL(*worldMock, getBoolConfig(_)).WillByDefault(Return(false));
|
||||
ON_CALL(*worldMock, getIntConfig(_)).WillByDefault(Return(0));
|
||||
ON_CALL(*worldMock, getFloatConfig(_)).WillByDefault(Return(0.0f));
|
||||
ON_CALL(*worldMock, GetPlayerSecurityLimit()).WillByDefault(Return(SEC_PLAYER));
|
||||
|
||||
session = new WorldSession(1, "gm", 0, nullptr, SEC_GAMEMASTER, EXPANSION_WRATH_OF_THE_LICH_KING,
|
||||
0, LOCALE_enUS, 0, false, false, 0);
|
||||
|
||||
player = new TestPlayer(session);
|
||||
player->ForceInitValues();
|
||||
session->SetPlayer(player);
|
||||
player->SetSession(session);
|
||||
|
||||
TestVisibilityScript::Reset();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
// Intentional leaks of session/player to avoid database access in destructors.
|
||||
IWorld* currentWorld = sWorld.release();
|
||||
delete currentWorld;
|
||||
worldMock = nullptr;
|
||||
|
||||
sWorld.reset(originalWorld);
|
||||
originalWorld = nullptr;
|
||||
session = nullptr;
|
||||
player = nullptr;
|
||||
}
|
||||
|
||||
void ExecuteCommand(std::string_view text)
|
||||
{
|
||||
if (text == ".gm visible off")
|
||||
{
|
||||
ApplyGmVisibleState(false);
|
||||
}
|
||||
else if (text == ".gm visible on")
|
||||
{
|
||||
ApplyGmVisibleState(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL() << "Unsupported test command: " << text;
|
||||
}
|
||||
}
|
||||
|
||||
static void EnsureScriptRegistriesInitialized()
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (!initialized)
|
||||
{
|
||||
ScriptRegistry<MiscScript>::InitEnabledHooksIfNeeded(MISCHOOK_END);
|
||||
ScriptRegistry<WorldObjectScript>::InitEnabledHooksIfNeeded(WORLDOBJECTHOOK_END);
|
||||
ScriptRegistry<UnitScript>::InitEnabledHooksIfNeeded(UNITHOOK_END);
|
||||
ScriptRegistry<PlayerScript>::InitEnabledHooksIfNeeded(PLAYERHOOK_END);
|
||||
ScriptRegistry<CommandSC>::InitEnabledHooksIfNeeded(ALLCOMMANDHOOK_END);
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
IWorld* originalWorld = nullptr;
|
||||
NiceMock<WorldMock>* worldMock = nullptr;
|
||||
WorldSession* session = nullptr;
|
||||
TestPlayer* player = nullptr;
|
||||
|
||||
private:
|
||||
void ApplyGmVisibleState(bool makeVisible)
|
||||
{
|
||||
constexpr uint32 VISUAL_AURA = 37800;
|
||||
|
||||
if (makeVisible)
|
||||
{
|
||||
player->RemoveAurasDueToSpell(VISUAL_AURA);
|
||||
player->SetGMVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
player->AddAura(VISUAL_AURA, player);
|
||||
player->SetGMVisible(false);
|
||||
}
|
||||
|
||||
player->UpdateObjectVisibility();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(GmVisibleCommandTest, SetsPlayerInvisibleAndInvokesHook)
|
||||
{
|
||||
ExecuteCommand(".gm visible off");
|
||||
|
||||
EXPECT_EQ(TestVisibilityScript::CallCount, 1u);
|
||||
EXPECT_EQ(TestVisibilityScript::LastPlayer, player);
|
||||
EXPECT_EQ(TestVisibilityScript::LastType, SERVERSIDE_VISIBILITY_GM);
|
||||
EXPECT_EQ(TestVisibilityScript::LastSecurity, session->GetSecurity());
|
||||
EXPECT_EQ(player->m_serverSideVisibility.GetValue(SERVERSIDE_VISIBILITY_GM), uint32(session->GetSecurity()));
|
||||
EXPECT_FALSE(player->isGMVisible());
|
||||
}
|
||||
|
||||
TEST_F(GmVisibleCommandTest, SetsPlayerVisibleAndInvokesHook)
|
||||
{
|
||||
// Ensure the player starts from invisible state to test the opposite transition as well.
|
||||
ExecuteCommand(".gm visible off");
|
||||
TestVisibilityScript::Reset();
|
||||
|
||||
ExecuteCommand(".gm visible on");
|
||||
|
||||
EXPECT_EQ(TestVisibilityScript::CallCount, 1u);
|
||||
EXPECT_EQ(TestVisibilityScript::LastPlayer, player);
|
||||
EXPECT_EQ(TestVisibilityScript::LastType, SERVERSIDE_VISIBILITY_GM);
|
||||
EXPECT_EQ(TestVisibilityScript::LastSecurity, SEC_PLAYER);
|
||||
EXPECT_EQ(player->m_serverSideVisibility.GetValue(SERVERSIDE_VISIBILITY_GM), uint32(SEC_PLAYER));
|
||||
EXPECT_TRUE(player->isGMVisible());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user