From dbc9b338386d659c5059f75794f8114e07b25a60 Mon Sep 17 00:00:00 2001 From: Andy Kernel <171799466+starswaitforus@users.noreply.github.com> Date: Mon, 16 Sep 2024 20:00:41 +0200 Subject: [PATCH] Stability++ --- .github/workflows/test.yml | 17 +- composer.json | 10 +- composer.lock | 3490 ++++++++++++++---- infection.json5 | 56 + server/src/Core/Bullet.php | 4 +- server/src/Core/ConsoleLogger.php | 9 +- server/src/Core/Game.php | 27 +- server/src/Core/GameException.php | 7 +- server/src/Core/HitBox.php | 15 +- server/src/Core/Inventory.php | 2 +- server/src/Core/Item.php | 7 + server/src/Core/PathFinder.php | 2 +- server/src/Core/Plane.php | 12 +- server/src/Core/Player.php | 1 + server/src/Core/World.php | 51 +- server/src/Equipment/Flashbang.php | 2 + server/src/Event/CrouchEvent.php | 5 + server/src/Event/DropEvent.php | 12 +- server/src/Event/GrillEvent.php | 19 +- server/src/Event/SmokeEvent.php | 14 +- server/src/Event/SoundEvent.php | 5 + server/src/Event/ThrowEvent.php | 2 +- server/src/Event/VolumetricEvent.php | 14 +- server/src/HitGeometry/SphereGroupHitBox.php | 1 + server/src/Net/Protocol.php | 1 + server/src/Net/Protocol/TextProtocol.php | 1 + server/src/Net/Server.php | 7 +- server/src/Traits/Player/AttackTrait.php | 16 +- server/src/Traits/Player/CrouchTrait.php | 10 +- server/src/Traits/Player/GravityTrait.php | 4 +- server/src/Traits/Player/InventoryTrait.php | 4 +- server/src/Traits/Player/JumpTrait.php | 2 +- server/src/Traits/Player/MovementTrait.php | 4 +- server/src/Weapon/PistolGlock.php | 2 +- server/src/Weapon/PistolP250.php | 2 +- server/src/Weapon/RifleAWP.php | 2 +- server/src/Weapon/RifleAk.php | 2 +- server/src/Weapon/RifleM4A4.php | 2 +- test/og/BaseTestCase.php | 2 + test/og/Game/RoundTest.php | 5 + test/og/Inventory/SimpleInventoryTest.php | 78 +- test/og/Movement/MovementTest.php | 24 + test/og/Movement/WorldCollisionTest.php | 2 + test/og/Shooting/BacktrackTest.php | 40 +- test/og/Shooting/GrenadeTest.php | 24 + test/og/Shooting/MolotovGrenadeTest.php | 67 + test/og/Shooting/PlayerKillTest.php | 112 +- test/og/Shooting/RecoilTest.php | 67 +- test/og/Shooting/SimpleShootTest.php | 45 + test/og/Unit/BoxTest.php | 49 + test/og/Unit/PerformanceTest.php | 4 +- test/og/World/CrouchTest.php | 2 + test/og/World/NavigationMeshTest.php | 12 + test/og/World/WorldTest.php | 5 +- 54 files changed, 3484 insertions(+), 897 deletions(-) create mode 100644 infection.json5 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 53db6aa..7f312f4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,13 +37,24 @@ jobs: - name: "Run Composer check" timeout-minutes: 1 run: | + export XDEBUG_MODE=off composer check - name: "Check code coverage min percentage" timeout-minutes: 5 run: | - echo ' cc.php - XDEBUG_MODE=coverage php vendor/bin/phpunit -d memory_limit=70M \ - --coverage-text --only-summary-for-coverage-text --stderr --no-progress --colors=never 2> cc.txt + echo ' cc.php + export XDEBUG_MODE=coverage + composer unit -- --stderr --no-progress --colors=never \ + --coverage-xml=www/coverage/coverage-xml --log-junit=www/coverage/junit.xml \ + --coverage-text --only-summary-for-coverage-text 2> cc.txt cat cc.txt grep 'Lines: ' cc.txt | php -d error_reporting=E_ALL cc.php + + - name: "Check infection mutation framework min percentage" + timeout-minutes: 10 + run: | + export XDEBUG_MODE=off + grep '"timeout": 20,' infection.json5 + sed -i 's/"timeout": 20,/"timeout": 40,/' infection.json5 + composer infection-cache -- --threads=$(($(nproc) + 1)) --only-covering-test-cases --skip-initial-tests diff --git a/composer.json b/composer.json index c914201..857998d 100644 --- a/composer.json +++ b/composer.json @@ -2,13 +2,15 @@ "scripts": { "stan": "php vendor/bin/phpstan --memory-limit=300M analyze", "unit": "php vendor/bin/phpunit -d memory_limit=70M", + "infection": "php -d memory_limit=180M vendor/bin/infection --only-covered --threads=6 --min-covered-msi=87", + "infection-cache": "@infection --coverage=www/coverage/", "dev": "php cli/server.php 1 8080 --debug & php cli/udp-ws-bridge.php", "dev2": "php cli/server.php 2 8080 --debug & php cli/udp-ws-bridge.php & php cli/udp-ws-bridge.php 8082", "dev2c": "php cli/server.php 2 8080 --debug & php cli/udp-ws-bridge.php & sleep 2 && php cli/client.php acode 8080", "dev3c": "php cli/server.php 3 8080 --debug & php cli/udp-ws-bridge.php & sleep 1 ; php cli/client.php acode 8080 & php cli/client.php acode 8080", "coverage": [ "@putenv XDEBUG_MODE=coverage", - "@unit --coverage-html www/coverage" + "@unit --coverage-html www/coverage --coverage-xml=www/coverage/coverage-xml --log-junit=www/coverage/junit.xml" ], "check": [ "@putenv PROJECT_CHECK=true", @@ -32,6 +34,7 @@ } }, "require-dev": { + "infection/infection": "*", "phpstan/phpstan-phpunit": "^1.3", "phpunit/phpunit": "^10.5" }, @@ -40,5 +43,10 @@ "Test\\Simulation\\": "test/simulation/", "Test\\": "test/og/" } + }, + "config": { + "allow-plugins": { + "infection/extension-installer": false + } } } diff --git a/composer.lock b/composer.lock index 1b51bf4..19a4aeb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2dfa01ebaee9c1768372481e16abcd04", + "content-hash": "dc88427d2188c4aa58b2e08c4ea162cf", "packages": [ { "name": "actived/graphphp", @@ -223,103 +223,1841 @@ } ], "packages-dev": [ + { + "name": "colinodell/json5", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/colinodell/json5.git", + "reference": "5724d21bc5c910c2560af1b8915f0cc0163579c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/colinodell/json5/zipball/5724d21bc5c910c2560af1b8915f0cc0163579c8", + "reference": "5724d21bc5c910c2560af1b8915f0cc0163579c8", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "php": "^8.0" + }, + "require-dev": { + "mikehaertl/php-shellcommand": "^1.7.0", + "phpstan/phpstan": "^1.10.57", + "scrutinizer/ocular": "^1.9", + "squizlabs/php_codesniffer": "^3.8.1", + "symfony/finder": "^6.0|^7.0", + "symfony/phpunit-bridge": "^7.0.3" + }, + "bin": [ + "bin/json5" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "files": [ + "src/global.php" + ], + "psr-4": { + "ColinODell\\Json5\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Developer" + } + ], + "description": "UTF-8 compatible JSON5 parser for PHP", + "homepage": "https://github.com/colinodell/json5", + "keywords": [ + "JSON5", + "json", + "json5_decode", + "json_decode" + ], + "support": { + "issues": "https://github.com/colinodell/json5/issues", + "source": "https://github.com/colinodell/json5/tree/v3.0.0" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://www.patreon.com/colinodell", + "type": "patreon" + } + ], + "time": "2024-02-09T13:06:12+00:00" + }, + { + "name": "composer/pcre", + "version": "3.3.1", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/63aaeac21d7e775ff9bc9d45021e1745c97521c4", + "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.11.10", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8 || ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.1" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-08-27T18:44:43+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-05-06T16:37:16+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "8520451a140d3f46ac33042715115e290cf5785f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", + "reference": "8520451a140d3f46ac33042715115e290cf5785f", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.2.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2024-08-06T10:04:20+00:00" + }, + { + "name": "infection/abstract-testframework-adapter", + "version": "0.5.0", + "source": { + "type": "git", + "url": "https://github.com/infection/abstract-testframework-adapter.git", + "reference": "18925e20d15d1a5995bb85c9dc09e8751e1e069b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/infection/abstract-testframework-adapter/zipball/18925e20d15d1a5995bb85c9dc09e8751e1e069b", + "reference": "18925e20d15d1a5995bb85c9dc09e8751e1e069b", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.8", + "friendsofphp/php-cs-fixer": "^2.17", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Infection\\AbstractTestFramework\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Maks Rafalko", + "email": "maks.rafalko@gmail.com" + } + ], + "description": "Abstract Test Framework Adapter for Infection", + "support": { + "issues": "https://github.com/infection/abstract-testframework-adapter/issues", + "source": "https://github.com/infection/abstract-testframework-adapter/tree/0.5.0" + }, + "funding": [ + { + "url": "https://github.com/infection", + "type": "github" + }, + { + "url": "https://opencollective.com/infection", + "type": "open_collective" + } + ], + "time": "2021-08-17T18:49:12+00:00" + }, + { + "name": "infection/extension-installer", + "version": "0.1.2", + "source": { + "type": "git", + "url": "https://github.com/infection/extension-installer.git", + "reference": "9b351d2910b9a23ab4815542e93d541e0ca0cdcf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/infection/extension-installer/zipball/9b351d2910b9a23ab4815542e93d541e0ca0cdcf", + "reference": "9b351d2910b9a23ab4815542e93d541e0ca0cdcf", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1 || ^2.0" + }, + "require-dev": { + "composer/composer": "^1.9 || ^2.0", + "friendsofphp/php-cs-fixer": "^2.18, <2.19", + "infection/infection": "^0.15.2", + "php-coveralls/php-coveralls": "^2.4", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12.10", + "phpstan/phpstan-phpunit": "^0.12.6", + "phpstan/phpstan-strict-rules": "^0.12.2", + "phpstan/phpstan-webmozart-assert": "^0.12.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.8" + }, + "type": "composer-plugin", + "extra": { + "class": "Infection\\ExtensionInstaller\\Plugin" + }, + "autoload": { + "psr-4": { + "Infection\\ExtensionInstaller\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Maks Rafalko", + "email": "maks.rafalko@gmail.com" + } + ], + "description": "Infection Extension Installer", + "support": { + "issues": "https://github.com/infection/extension-installer/issues", + "source": "https://github.com/infection/extension-installer/tree/0.1.2" + }, + "funding": [ + { + "url": "https://github.com/infection", + "type": "github" + }, + { + "url": "https://opencollective.com/infection", + "type": "open_collective" + } + ], + "time": "2021-10-20T22:08:34+00:00" + }, + { + "name": "infection/include-interceptor", + "version": "0.2.5", + "source": { + "type": "git", + "url": "https://github.com/infection/include-interceptor.git", + "reference": "0cc76d95a79d9832d74e74492b0a30139904bdf7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/infection/include-interceptor/zipball/0cc76d95a79d9832d74e74492b0a30139904bdf7", + "reference": "0cc76d95a79d9832d74e74492b0a30139904bdf7", + "shasum": "" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.16", + "infection/infection": "^0.15.0", + "phan/phan": "^2.4 || ^3", + "php-coveralls/php-coveralls": "^2.2", + "phpstan/phpstan": "^0.12.8", + "phpunit/phpunit": "^8.5", + "vimeo/psalm": "^3.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Infection\\StreamWrapper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Maks Rafalko", + "email": "maks.rafalko@gmail.com" + } + ], + "description": "Stream Wrapper: Include Interceptor. Allows to replace included (autoloaded) file with another one.", + "support": { + "issues": "https://github.com/infection/include-interceptor/issues", + "source": "https://github.com/infection/include-interceptor/tree/0.2.5" + }, + "funding": [ + { + "url": "https://github.com/infection", + "type": "github" + }, + { + "url": "https://opencollective.com/infection", + "type": "open_collective" + } + ], + "time": "2021-08-09T10:03:57+00:00" + }, + { + "name": "infection/infection", + "version": "0.29.6", + "source": { + "type": "git", + "url": "https://github.com/infection/infection.git", + "reference": "a8510c1d472892dda2ae32e2c4b2e795533db810" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/infection/infection/zipball/a8510c1d472892dda2ae32e2c4b2e795533db810", + "reference": "a8510c1d472892dda2ae32e2c4b2e795533db810", + "shasum": "" + }, + "require": { + "colinodell/json5": "^2.2 || ^3.0", + "composer-runtime-api": "^2.0", + "composer/xdebug-handler": "^2.0 || ^3.0", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "fidry/cpu-core-counter": "^0.4.0 || ^0.5.0 || ^1.0", + "infection/abstract-testframework-adapter": "^0.5.0", + "infection/extension-installer": "^0.1.0", + "infection/include-interceptor": "^0.2.5", + "infection/mutator": "^0.4", + "justinrainbow/json-schema": "^5.2.10", + "nikic/php-parser": "^5.0", + "ondram/ci-detector": "^4.1.0", + "php": "^8.1", + "sanmai/later": "^0.1.1", + "sanmai/pipeline": "^5.1 || ^6", + "sebastian/diff": "^3.0.2 || ^4.0 || ^5.0 || ^6.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", + "symfony/finder": "^5.4 || ^6.0 || ^7.0", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "thecodingmachine/safe": "^2.1.2", + "webmozart/assert": "^1.11" + }, + "conflict": { + "antecedent/patchwork": "<2.1.25", + "dg/bypass-finals": "<1.4.1", + "phpunit/php-code-coverage": ">9,<9.1.4 || >9.2.17,<9.2.21" + }, + "require-dev": { + "ext-simplexml": "*", + "fidry/makefile": "^1.0", + "helmich/phpunit-json-assert": "^3.0", + "phpspec/prophecy": "^1.15", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.1.0", + "phpstan/phpstan": "^1.10.15", + "phpstan/phpstan-phpunit": "^1.0.0", + "phpstan/phpstan-strict-rules": "^1.1.0", + "phpstan/phpstan-webmozart-assert": "^1.0.2", + "phpunit/phpunit": "^10.5", + "rector/rector": "^1.0", + "sidz/phpstan-rules": "^0.4", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0", + "thecodingmachine/phpstan-safe-rule": "^1.2.0" + }, + "bin": [ + "bin/infection" + ], + "type": "library", + "autoload": { + "psr-4": { + "Infection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Maks Rafalko", + "email": "maks.rafalko@gmail.com", + "homepage": "https://twitter.com/maks_rafalko" + }, + { + "name": "Oleg Zhulnev", + "homepage": "https://github.com/sidz" + }, + { + "name": "Gert de Pagter", + "homepage": "https://github.com/BackEndTea" + }, + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com", + "homepage": "https://twitter.com/tfidry" + }, + { + "name": "Alexey Kopytko", + "email": "alexey@kopytko.com", + "homepage": "https://www.alexeykopytko.com" + }, + { + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" + } + ], + "description": "Infection is a Mutation Testing framework for PHP. The mutation adequacy score can be used to measure the effectiveness of a test set in terms of its ability to detect faults.", + "keywords": [ + "coverage", + "mutant", + "mutation framework", + "mutation testing", + "testing", + "unit testing" + ], + "support": { + "issues": "https://github.com/infection/infection/issues", + "source": "https://github.com/infection/infection/tree/0.29.6" + }, + "funding": [ + { + "url": "https://github.com/infection", + "type": "github" + }, + { + "url": "https://opencollective.com/infection", + "type": "open_collective" + } + ], + "time": "2024-06-21T10:21:05+00:00" + }, + { + "name": "infection/mutator", + "version": "0.4.0", + "source": { + "type": "git", + "url": "https://github.com/infection/mutator.git", + "reference": "51d6d01a2357102030aee9d603063c4bad86b144" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/infection/mutator/zipball/51d6d01a2357102030aee9d603063c4bad86b144", + "reference": "51d6d01a2357102030aee9d603063c4bad86b144", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^10" + }, + "type": "library", + "autoload": { + "psr-4": { + "Infection\\Mutator\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Maks Rafalko", + "email": "maks.rafalko@gmail.com" + } + ], + "description": "Mutator interface to implement custom mutators (mutation operators) for Infection", + "support": { + "issues": "https://github.com/infection/mutator/issues", + "source": "https://github.com/infection/mutator/tree/0.4.0" + }, + "funding": [ + { + "url": "https://github.com/infection", + "type": "github" + }, + { + "url": "https://opencollective.com/infection", + "type": "open_collective" + } + ], + "time": "2024-05-14T22:39:59+00:00" + }, + { + "name": "justinrainbow/json-schema", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/jsonrainbow/json-schema.git", + "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", + "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", + "json-schema/json-schema-test-suite": "1.2.0", + "phpunit/phpunit": "^4.8.35" + }, + "bin": [ + "bin/validate-json" + ], + "type": "library", + "autoload": { + "psr-4": { + "JsonSchema\\": "src/JsonSchema/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" + }, + { + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" + } + ], + "description": "A library to validate a json schema.", + "homepage": "https://github.com/justinrainbow/json-schema", + "keywords": [ + "json", + "schema" + ], + "support": { + "issues": "https://github.com/jsonrainbow/json-schema/issues", + "source": "https://github.com/jsonrainbow/json-schema/tree/5.3.0" + }, + "time": "2024-07-06T21:00:26+00:00" + }, { "name": "myclabs/deep-copy", "version": "1.12.0", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2024-06-12T14:39:25+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.2.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb", + "reference": "23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.2.0" + }, + "time": "2024-09-15T16:40:33+00:00" + }, + { + "name": "ondram/ci-detector", + "version": "4.2.0", + "source": { + "type": "git", + "url": "https://github.com/OndraM/ci-detector.git", + "reference": "8b0223b5ed235fd377c75fdd1bfcad05c0f168b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/OndraM/ci-detector/zipball/8b0223b5ed235fd377c75fdd1bfcad05c0f168b8", + "reference": "8b0223b5ed235fd377c75fdd1bfcad05c0f168b8", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.13.2", + "lmc/coding-standard": "^3.0.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.1.0", + "phpstan/phpstan": "^1.2.0", + "phpstan/phpstan-phpunit": "^1.0.0", + "phpunit/phpunit": "^9.6.13" + }, + "type": "library", + "autoload": { + "psr-4": { + "OndraM\\CiDetector\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ondřej Machulda", + "email": "ondrej.machulda@gmail.com" + } + ], + "description": "Detect continuous integration environment and provide unified access to properties of current build", + "keywords": [ + "CircleCI", + "Codeship", + "Wercker", + "adapter", + "appveyor", + "aws", + "aws codebuild", + "azure", + "azure devops", + "azure pipelines", + "bamboo", + "bitbucket", + "buddy", + "ci-info", + "codebuild", + "continuous integration", + "continuousphp", + "devops", + "drone", + "github", + "gitlab", + "interface", + "jenkins", + "pipelines", + "sourcehut", + "teamcity", + "travis" + ], + "support": { + "issues": "https://github.com/OndraM/ci-detector/issues", + "source": "https://github.com/OndraM/ci-detector/tree/4.2.0" + }, + "time": "2024-03-12T13:22:30+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "1.12.3", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0fcbf194ab63d8159bb70d9aa3e1350051632009", + "reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2024-09-09T08:10:35+00:00" + }, + { + "name": "phpstan/phpstan-phpunit", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-phpunit.git", + "reference": "f3ea021866f4263f07ca3636bf22c64be9610c11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/f3ea021866f4263f07ca3636bf22c64be9610c11", + "reference": "f3ea021866f4263f07ca3636bf22c64be9610c11", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.11" + }, + "conflict": { + "phpunit/phpunit": "<7.0" + }, + "require-dev": { + "nikic/php-parser": "^4.13.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-strict-rules": "^1.5.1", + "phpunit/phpunit": "^9.5" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon", + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPUnit extensions and rules for PHPStan", + "support": { + "issues": "https://github.com/phpstan/phpstan-phpunit/issues", + "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.4.0" + }, + "time": "2024-04-20T06:39:00+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "10.1.16", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-text-template": "^3.0.1", + "sebastian/code-unit-reverse-lookup": "^3.0.0", + "sebastian/complexity": "^3.2.0", + "sebastian/environment": "^6.1.0", + "sebastian/lines-of-code": "^2.0.2", + "sebastian/version": "^4.0.1", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-22T04:31:57+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "4.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T06:24:48+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:09+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T14:07:24+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:57:52+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "10.5.34", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "3c69d315bdf79080c8e115b69d1961c6905b0e18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3c69d315bdf79080c8e115b69d1961c6905b0e18", + "reference": "3c69d315bdf79080c8e115b69d1961c6905b0e18", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.16", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-invoker": "^4.0.0", + "phpunit/php-text-template": "^3.0.1", + "phpunit/php-timer": "^6.0.0", + "sebastian/cli-parser": "^2.0.1", + "sebastian/code-unit": "^2.0.0", + "sebastian/comparator": "^5.0.2", + "sebastian/diff": "^5.1.1", + "sebastian/environment": "^6.1.0", + "sebastian/exporter": "^5.1.2", + "sebastian/global-state": "^6.0.2", + "sebastian/object-enumerator": "^5.0.0", + "sebastian/recursion-context": "^5.0.0", + "sebastian/type": "^4.0.0", + "sebastian/version": "^4.0.1" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.34" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-09-13T05:19:38+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "sanmai/later", + "version": "0.1.4", + "source": { + "type": "git", + "url": "https://github.com/sanmai/later.git", + "reference": "e24c4304a4b1349c2a83151a692cec0c10579f60" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sanmai/later/zipball/e24c4304a4b1349c2a83151a692cec0c10579f60", + "reference": "e24c4304a4b1349c2a83151a692cec0c10579f60", + "shasum": "" + }, + "require": { + "php": ">=7.4" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.8", + "friendsofphp/php-cs-fixer": "^3.35.1", + "infection/infection": ">=0.27.6", + "phan/phan": ">=2", + "php-coveralls/php-coveralls": "^2.0", + "phpstan/phpstan": ">=1.4.5", + "phpunit/phpunit": ">=9.5 <10", + "vimeo/psalm": ">=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.1.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Later\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Alexey Kopytko", + "email": "alexey@kopytko.com" + } + ], + "description": "Later: deferred wrapper object", + "support": { + "issues": "https://github.com/sanmai/later/issues", + "source": "https://github.com/sanmai/later/tree/0.1.4" + }, + "funding": [ + { + "url": "https://github.com/sanmai", + "type": "github" + } + ], + "time": "2023-10-24T00:25:28+00:00" + }, + { + "name": "sanmai/pipeline", + "version": "v6.11", + "source": { + "type": "git", + "url": "https://github.com/sanmai/pipeline.git", + "reference": "a5fa2a6c6ca93efa37e7c24aab72f47448a6b110" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sanmai/pipeline/zipball/a5fa2a6c6ca93efa37e7c24aab72f47448a6b110", + "reference": "a5fa2a6c6ca93efa37e7c24aab72f47448a6b110", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.8", + "friendsofphp/php-cs-fixer": "^3.17", + "infection/infection": ">=0.10.5", + "league/pipeline": "^0.3 || ^1.0", + "phan/phan": ">=1.1", + "php-coveralls/php-coveralls": "^2.4.1", + "phpstan/phpstan": ">=0.10", + "phpunit/phpunit": ">=9.4", + "vimeo/psalm": ">=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "v6.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Pipeline\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Alexey Kopytko", + "email": "alexey@kopytko.com" + } + ], + "description": "General-purpose collections pipeline", + "support": { + "issues": "https://github.com/sanmai/pipeline/issues", + "source": "https://github.com/sanmai/pipeline/tree/v6.11" + }, + "funding": [ + { + "url": "https://github.com/sanmai", + "type": "github" + } + ], + "time": "2024-06-15T03:11:19+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" + "php": ">=8.1" }, "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + "phpunit/phpunit": "^10.0" }, "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" }, "funding": [ { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "time": "2024-06-12T14:39:25+00:00" + "time": "2024-03-02T07:12:49+00:00" }, { - "name": "nikic/php-parser", - "version": "v5.1.0", + "name": "sebastian/code-unit", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", "shasum": "" }, "require": { - "ext-ctype": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=7.4" + "php": ">=8.1" }, "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^10.0" }, - "bin": [ - "bin/php-parse" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -327,46 +2065,49 @@ ], "authors": [ { - "name": "Nikita Popov" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" }, - "time": "2024-07-01T20:03:41+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:43+00:00" }, { - "name": "phar-io/manifest", - "version": "2.0.4", + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -379,53 +2120,55 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "email": "sebastian@phpunit.de" } ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" }, "funding": [ { - "url": "https://github.com/theseer", + "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2024-03-03T12:33:53+00:00" + "time": "2023-02-03T06:59:15+00:00" }, { - "name": "phar-io/version", - "version": "3.2.1", + "name": "sebastian/comparator", + "version": "5.0.2", "source": { "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", + "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.4" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -437,178 +2180,194 @@ ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" } ], - "description": "Library for handling version information and constraints", + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.2" }, - "time": "2022-02-21T01:04:05+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-12T06:03:08+00:00" }, { - "name": "phpstan/phpstan", - "version": "1.11.11", + "name": "sebastian/complexity", + "version": "3.2.0", "source": { "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3" + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "68ff824baeae169ec9f2137158ee529584553799" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/707c2aed5d8d0075666e673a5e71440c1d01a5a3", - "reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", "shasum": "" }, "require": { - "php": "^7.2|^8.0" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" }, - "conflict": { - "phpstan/phpstan-shim": "*" + "require-dev": { + "phpunit/phpunit": "^10.0" }, - "bin": [ - "phpstan", - "phpstan.phar" - ], "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.2-dev" + } + }, "autoload": { - "files": [ - "bootstrap.php" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], - "description": "PHPStan - PHP Static Analysis Tool", - "keywords": [ - "dev", - "static analysis" + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", "support": { - "docs": "https://phpstan.org/user-guide/getting-started", - "forum": "https://github.com/phpstan/phpstan/discussions", - "issues": "https://github.com/phpstan/phpstan/issues", - "security": "https://github.com/phpstan/phpstan/security/policy", - "source": "https://github.com/phpstan/phpstan-src" + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" }, "funding": [ { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", + "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2024-08-19T14:37:29+00:00" + "time": "2023-12-21T08:37:17+00:00" }, { - "name": "phpstan/phpstan-phpunit", - "version": "1.4.0", + "name": "sebastian/diff", + "version": "5.1.1", "source": { "type": "git", - "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "f3ea021866f4263f07ca3636bf22c64be9610c11" + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/f3ea021866f4263f07ca3636bf22c64be9610c11", - "reference": "f3ea021866f4263f07ca3636bf22c64be9610c11", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.11" - }, - "conflict": { - "phpunit/phpunit": "<7.0" + "php": ">=8.1" }, "require-dev": { - "nikic/php-parser": "^4.13.0", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-strict-rules": "^1.5.1", - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" }, - "type": "phpstan-extension", + "type": "library", "extra": { - "phpstan": { - "includes": [ - "extension.neon", - "rules.neon" - ] + "branch-alias": { + "dev-main": "5.1-dev" } }, "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" ], - "description": "PHPUnit extensions and rules for PHPStan", "support": { - "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.4.0" + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" }, - "time": "2024-04-20T06:39:00+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:15:17+00:00" }, { - "name": "phpunit/php-code-coverage", - "version": "10.1.16", + "name": "sebastian/environment", + "version": "6.1.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77" + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=8.1", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-text-template": "^3.0.1", - "sebastian/code-unit-reverse-lookup": "^3.0.0", - "sebastian/complexity": "^3.2.0", - "sebastian/environment": "^6.1.0", - "sebastian/lines-of-code": "^2.0.2", - "sebastian/version": "^4.0.1", - "theseer/tokenizer": "^1.2.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^10.1" + "phpunit/phpunit": "^10.0" }, "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "10.1.x-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -623,21 +2382,20 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ - "coverage", - "testing", - "xunit" + "Xdebug", + "environment", + "hhvm" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" }, "funding": [ { @@ -645,24 +2403,26 @@ "type": "github" } ], - "time": "2024-08-22T04:31:57+00:00" + "time": "2024-03-23T08:47:14+00:00" }, { - "name": "phpunit/php-file-iterator", - "version": "4.1.0", + "name": "sebastian/exporter", + "version": "5.1.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf", "shasum": "" }, "require": { - "php": ">=8.1" + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" }, "require-dev": { "phpunit/phpunit": "^10.0" @@ -670,7 +2430,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -685,20 +2445,35 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ - "filesystem", - "iterator" + "export", + "exporter" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" }, "funding": [ { @@ -706,36 +2481,35 @@ "type": "github" } ], - "time": "2023-08-31T06:24:48+00:00" + "time": "2024-03-02T07:17:12+00:00" }, { - "name": "phpunit/php-invoker", - "version": "4.0.0", + "name": "sebastian/global-state", + "version": "6.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "ext-pcntl": "*", + "ext-dom": "*", "phpunit/phpunit": "^10.0" }, - "suggest": { - "ext-pcntl": "*" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -750,18 +2524,18 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ - "process" + "global state" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" }, "funding": [ { @@ -769,23 +2543,24 @@ "type": "github" } ], - "time": "2023-02-03T06:56:09+00:00" + "time": "2024-03-02T07:19:19+00:00" }, { - "name": "phpunit/php-text-template", - "version": "3.0.1", + "name": "sebastian/lines-of-code", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", "shasum": "" }, "require": { + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=8.1" }, "require-dev": { @@ -794,7 +2569,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -813,15 +2588,12 @@ "role": "lead" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" }, "funding": [ { @@ -829,24 +2601,26 @@ "type": "github" } ], - "time": "2023-08-31T14:07:24+00:00" + "time": "2023-12-21T08:38:20+00:00" }, { - "name": "phpunit/php-timer", - "version": "6.0.0", + "name": "sebastian/object-enumerator", + "version": "5.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { "phpunit/phpunit": "^10.0" @@ -854,7 +2628,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -869,18 +2643,14 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" }, "funding": [ { @@ -888,66 +2658,35 @@ "type": "github" } ], - "time": "2023-02-03T06:57:52+00:00" + "time": "2023-02-03T07:08:32+00:00" }, { - "name": "phpunit/phpunit", - "version": "10.5.30", + "name": "sebastian/object-reflector", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "b15524febac0153876b4ba9aab3326c2ee94c897" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b15524febac0153876b4ba9aab3326c2ee94c897", - "reference": "b15524febac0153876b4ba9aab3326c2ee94c897", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.0", - "phar-io/manifest": "^2.0.4", - "phar-io/version": "^3.2.1", - "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.15", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-invoker": "^4.0.0", - "phpunit/php-text-template": "^3.0.1", - "phpunit/php-timer": "^6.0.0", - "sebastian/cli-parser": "^2.0.1", - "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.2", - "sebastian/diff": "^5.1.1", - "sebastian/environment": "^6.1.0", - "sebastian/exporter": "^5.1.2", - "sebastian/global-state": "^6.0.2", - "sebastian/object-enumerator": "^5.0.0", - "sebastian/recursion-context": "^5.0.0", - "sebastian/type": "^4.0.0", - "sebastian/version": "^4.0.1" + "php": ">=8.1" }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files" + "require-dev": { + "phpunit/phpunit": "^10.0" }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-main": "10.5-dev" + "dev-main": "3.0-dev" } }, "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], "classmap": [ "src/" ] @@ -959,50 +2698,35 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.30" + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" }, "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" } ], - "time": "2024-08-13T06:09:37+00:00" + "time": "2023-02-03T07:06:18+00:00" }, { - "name": "sebastian/cli-parser", - "version": "2.0.1", + "name": "sebastian/recursion-context", + "version": "5.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", "shasum": "" }, "require": { @@ -1014,7 +2738,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -1029,16 +2753,22 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" }, "funding": [ { @@ -1046,20 +2776,20 @@ "type": "github" } ], - "time": "2024-03-02T07:12:49+00:00" + "time": "2023-02-03T07:05:40+00:00" }, { - "name": "sebastian/code-unit", - "version": "2.0.0", + "name": "sebastian/type", + "version": "4.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", "shasum": "" }, "require": { @@ -1071,7 +2801,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1090,11 +2820,11 @@ "role": "lead" } ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" }, "funding": [ { @@ -1102,32 +2832,29 @@ "type": "github" } ], - "time": "2023-02-03T06:58:43+00:00" + "time": "2023-02-03T07:10:45+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "3.0.0", + "name": "sebastian/version", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", "shasum": "" }, "require": { "php": ">=8.1" }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1142,14 +2869,15 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" }, "funding": [ { @@ -1157,755 +2885,985 @@ "type": "github" } ], - "time": "2023-02-03T06:59:15+00:00" + "time": "2023-02-07T11:34:05+00:00" }, { - "name": "sebastian/comparator", - "version": "5.0.2", + "name": "symfony/console", + "version": "v6.4.11", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53" + "url": "https://github.com/symfony/console.git", + "reference": "42686880adaacdad1835ee8fc2a9ec5b7bd63998" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", - "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", + "url": "https://api.github.com/repos/symfony/console/zipball/42686880adaacdad1835ee8fc2a9ec5b7bd63998", + "reference": "42686880adaacdad1835ee8fc2a9ec5b7bd63998", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-mbstring": "*", "php": ">=8.1", - "sebastian/diff": "^5.0", - "sebastian/exporter": "^5.0" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { - "phpunit/phpunit": "^10.4" + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", "keywords": [ - "comparator", - "compare", - "equality" + "cli", + "command-line", + "console", + "terminal" ], "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.2" + "source": "https://github.com/symfony/console/tree/v6.4.11" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-08-12T06:03:08+00:00" + "time": "2024-08-15T22:48:29+00:00" }, { - "name": "sebastian/complexity", - "version": "3.2.0", + "name": "symfony/deprecation-contracts", + "version": "v3.5.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "68ff824baeae169ec9f2137158ee529584553799" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", - "reference": "68ff824baeae169ec9f2137158ee529584553799", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", "php": ">=8.1" }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.2-dev" + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { - "classmap": [ - "src/" + "files": [ + "function.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2023-12-21T08:37:17+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { - "name": "sebastian/diff", - "version": "5.1.1", + "name": "symfony/filesystem", + "version": "v6.4.9", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" + "url": "https://github.com/symfony/filesystem.git", + "reference": "b51ef8059159330b74a4d52f68e671033c0fe463" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b51ef8059159330b74a4d52f68e671033c0fe463", + "reference": "b51ef8059159330b74a4d52f68e671033c0fe463", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^6.4" + "symfony/process": "^5.4|^6.4|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.1-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" + "source": "https://github.com/symfony/filesystem/tree/v6.4.9" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-03-02T07:15:17+00:00" + "time": "2024-06-28T09:49:33+00:00" }, { - "name": "sebastian/environment", - "version": "6.1.0", + "name": "symfony/finder", + "version": "v6.4.11", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" + "url": "https://github.com/symfony/finder.git", + "reference": "d7eb6daf8cd7e9ac4976e9576b32042ef7253453" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", + "url": "https://api.github.com/repos/symfony/finder/zipball/d7eb6daf8cd7e9ac4976e9576b32042ef7253453", + "reference": "d7eb6daf8cd7e9ac4976e9576b32042ef7253453", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "suggest": { - "ext-posix": "*" + "symfony/filesystem": "^6.0|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.1-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "https://github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" + "source": "https://github.com/symfony/finder/tree/v6.4.11" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-03-23T08:47:14+00:00" + "time": "2024-08-13T14:27:37+00:00" }, { - "name": "sebastian/exporter", - "version": "5.1.2", + "name": "symfony/polyfill-ctype", + "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/recursion-context": "^5.0" + "php": ">=7.2" }, - "require-dev": { - "phpunit/phpunit": "^10.0" + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "5.1-dev" + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "classmap": [ - "src/" - ] + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", "keywords": [ - "export", - "exporter" + "compatibility", + "ctype", + "polyfill", + "portable" ], "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-03-02T07:17:12+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "sebastian/global-state", - "version": "6.0.2", + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=7.2" }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^10.0" + "suggest": { + "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "6.0-dev" + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "classmap": [ - "src/" - ] + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Snapshotting of global state", - "homepage": "https://www.github.com/sebastianbergmann/global-state", + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", "keywords": [ - "global state" + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" ], "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-03-02T07:19:19+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "sebastian/lines-of-code", - "version": "2.0.2", + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "php": ">=7.2" }, - "require-dev": { - "phpunit/phpunit": "^10.0" + "suggest": { + "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "2.0-dev" + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, "classmap": [ - "src/" + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2023-12-21T08:38:20+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "5.0.0", + "name": "symfony/polyfill-mbstring", + "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=7.2" }, - "require-dev": { - "phpunit/phpunit": "^10.0" + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "5.0-dev" + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "classmap": [ - "src/" - ] + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2023-02-03T07:08:32+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "sebastian/object-reflector", - "version": "3.0.0", + "name": "symfony/process", + "version": "v6.4.8", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + "url": "https://github.com/symfony/process.git", + "reference": "8d92dd79149f29e89ee0f480254db595f6a6a2c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "url": "https://api.github.com/repos/symfony/process/zipball/8d92dd79149f29e89ee0f480254db595f6a6a2c5", + "reference": "8d92dd79149f29e89ee0f480254db595f6a6a2c5", "shasum": "" }, "require": { "php": ">=8.1" }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + "source": "https://github.com/symfony/process/tree/v6.4.8" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2023-02-03T07:06:18+00:00" + "time": "2024-05-31T14:49:08+00:00" }, { - "name": "sebastian/recursion-context", - "version": "5.0.0", + "name": "symfony/service-contracts", + "version": "v3.5.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + "url": "https://github.com/symfony/service-contracts.git", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, - "require-dev": { - "phpunit/phpunit": "^10.0" + "conflict": { + "ext-psr": "<1.1|>=2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2023-02-03T07:05:40+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { - "name": "sebastian/type", - "version": "4.0.0", + "name": "symfony/string", + "version": "v6.4.11", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + "url": "https://github.com/symfony/string.git", + "reference": "5bc3eb632cf9c8dbfd6529d89be9950d1518883b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "url": "https://api.github.com/repos/symfony/string/zipball/5bc3eb632cf9c8dbfd6529d89be9950d1518883b", + "reference": "5bc3eb632cf9c8dbfd6529d89be9950d1518883b", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + "source": "https://github.com/symfony/string/tree/v6.4.11" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2023-02-03T07:10:45+00:00" + "time": "2024-08-12T09:55:28+00:00" }, { - "name": "sebastian/version", - "version": "4.0.1", + "name": "thecodingmachine/safe", + "version": "v2.5.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + "url": "https://github.com/thecodingmachine/safe.git", + "reference": "3115ecd6b4391662b4931daac4eba6b07a2ac1f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/3115ecd6b4391662b4931daac4eba6b07a2ac1f0", + "reference": "3115ecd6b4391662b4931daac4eba6b07a2ac1f0", "shasum": "" }, "require": { - "php": ">=8.1" + "php": "^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.5", + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.2", + "thecodingmachine/phpstan-strict-rules": "^1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-master": "2.2.x-dev" } }, "autoload": { + "files": [ + "deprecated/apc.php", + "deprecated/array.php", + "deprecated/datetime.php", + "deprecated/libevent.php", + "deprecated/misc.php", + "deprecated/password.php", + "deprecated/mssql.php", + "deprecated/stats.php", + "deprecated/strings.php", + "lib/special_cases.php", + "deprecated/mysqli.php", + "generated/apache.php", + "generated/apcu.php", + "generated/array.php", + "generated/bzip2.php", + "generated/calendar.php", + "generated/classobj.php", + "generated/com.php", + "generated/cubrid.php", + "generated/curl.php", + "generated/datetime.php", + "generated/dir.php", + "generated/eio.php", + "generated/errorfunc.php", + "generated/exec.php", + "generated/fileinfo.php", + "generated/filesystem.php", + "generated/filter.php", + "generated/fpm.php", + "generated/ftp.php", + "generated/funchand.php", + "generated/gettext.php", + "generated/gmp.php", + "generated/gnupg.php", + "generated/hash.php", + "generated/ibase.php", + "generated/ibmDb2.php", + "generated/iconv.php", + "generated/image.php", + "generated/imap.php", + "generated/info.php", + "generated/inotify.php", + "generated/json.php", + "generated/ldap.php", + "generated/libxml.php", + "generated/lzf.php", + "generated/mailparse.php", + "generated/mbstring.php", + "generated/misc.php", + "generated/mysql.php", + "generated/network.php", + "generated/oci8.php", + "generated/opcache.php", + "generated/openssl.php", + "generated/outcontrol.php", + "generated/pcntl.php", + "generated/pcre.php", + "generated/pgsql.php", + "generated/posix.php", + "generated/ps.php", + "generated/pspell.php", + "generated/readline.php", + "generated/rpminfo.php", + "generated/rrd.php", + "generated/sem.php", + "generated/session.php", + "generated/shmop.php", + "generated/sockets.php", + "generated/sodium.php", + "generated/solr.php", + "generated/spl.php", + "generated/sqlsrv.php", + "generated/ssdeep.php", + "generated/ssh2.php", + "generated/stream.php", + "generated/strings.php", + "generated/swoole.php", + "generated/uodbc.php", + "generated/uopz.php", + "generated/url.php", + "generated/var.php", + "generated/xdiff.php", + "generated/xml.php", + "generated/xmlrpc.php", + "generated/yaml.php", + "generated/yaz.php", + "generated/zip.php", + "generated/zlib.php" + ], "classmap": [ - "src/" + "lib/DateTime.php", + "lib/DateTimeImmutable.php", + "lib/Exceptions/", + "deprecated/Exceptions/", + "generated/Exceptions/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } + "MIT" ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", + "description": "PHP core functions that throw exceptions instead of returning FALSE on error", "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + "issues": "https://github.com/thecodingmachine/safe/issues", + "source": "https://github.com/thecodingmachine/safe/tree/v2.5.0" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-07T11:34:05+00:00" + "time": "2023-04-05T11:54:14+00:00" }, { "name": "theseer/tokenizer", @@ -1956,6 +3914,64 @@ } ], "time": "2024-03-03T12:36:25+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" } ], "aliases": [], diff --git a/infection.json5 b/infection.json5 new file mode 100644 index 0000000..a2ed0d6 --- /dev/null +++ b/infection.json5 @@ -0,0 +1,56 @@ +{ + "$schema": "vendor/infection/infection/resources/schema.json", + "source": { + "directories": [ + "server/src/", + ], + }, + "logs": { + "text": "/tmp/infection.log", + }, + "timeout": 20, + "testFramework": "phpunit", + "mutators": { + "global-ignoreSourceCodeByRegex": [ + "\\$this->log\\(.*\\);", + "throw new GameException\\(.+\\);", + "GameException::notImplementedYet\\(.*\\);", + ], + "@default": true, + "@arithmetic": false, + "@boolean": false, + "@cast": false, + "@conditional_boundary": false, + "@conditional_negotiation": false, + "@equal": false, + "@function_signature": true, + "PublicVisibility": { + ignoreSourceCodeByRegex: [ + "public function processFlammableExplosion\\(.+", + ], + }, + "@identical": true, + "@number": false, + "@operator": false, + "@regex": true, + "@removal": true, + "MethodCallRemoval": { + "ignoreSourceCodeByRegex": [ + "\\$prevPos->setFrom\\(\\$candidate\\);", + "\\$prevPos->setFrom\\(\\$newPos\\);", + "\\$this->makeSound\\(.+\\);", + "\\$soundEvent->setItem\\(.+\\);", + "\\$soundEvent->setPlayer\\(.+\\);", + "\\$soundEvent->setSurface\\(.+\\);", + "\\$soundEvent->addExtra\\(.+\\);", + "\\$this->addSoundEvent\\(.+\\);", + ] + }, + "@return_value": true, + "IntegerNegation": false, + "@sort": true, + "@unwrap": true, + "For_": true, + "Foreach_": true, + }, +} diff --git a/server/src/Core/Bullet.php b/server/src/Core/Bullet.php index 279ac08..a7d1497 100644 --- a/server/src/Core/Bullet.php +++ b/server/src/Core/Bullet.php @@ -13,7 +13,7 @@ class Bullet private bool $originPlayerIsAttacker; private int $distanceTraveled; private int $damage = 1; - /** @var array [playerId => true] */ + /** @var array [playerId => true] */ private array $playerSkipIds = []; public function __construct(private AttackEnable $item, private int $distanceMax = 1) @@ -91,7 +91,7 @@ public function getShootItem(): AttackEnable } /** - * @return array [playerId => true] + * @return array [playerId => true] */ public function getPlayerSkipIds(): array { diff --git a/server/src/Core/ConsoleLogger.php b/server/src/Core/ConsoleLogger.php index a7543a4..5ad0772 100644 --- a/server/src/Core/ConsoleLogger.php +++ b/server/src/Core/ConsoleLogger.php @@ -5,12 +5,13 @@ use Psr\Log\AbstractLogger; use Stringable; -class ConsoleLogger extends AbstractLogger +/** + * @codeCoverageIgnore + * @infection-ignore-all + */ +final class ConsoleLogger extends AbstractLogger { - /** - * @codeCoverageIgnore - */ public function log(mixed $level, Stringable|string $message, array $context = []): void // @phpstan-ignore-line { if (!is_string($level)) { diff --git a/server/src/Core/Game.php b/server/src/Core/Game.php index ec682e7..bd5250b 100644 --- a/server/src/Core/Game.php +++ b/server/src/Core/Game.php @@ -244,7 +244,6 @@ public function getRoundNumber(): int return $this->roundNumber; } - /** @infection-ignore-all */ public function addSoundEvent(SoundEvent $event): void { $this->addEvent($event); @@ -295,8 +294,8 @@ private function playerKilledEvent(Player $playerCulprit, Player $playerDead, in $this->score->getPlayerStat($playerDead->getId())->addDeath(); $this->addEvent(new KillEvent($playerDead, $playerCulprit, $itemId, $headShot)); - $sound = new SoundEvent($playerDead->getPositionClone(), SoundType::PLAYER_DEAD); - $this->addSoundEvent($sound->setPlayer($playerDead)); + $soundEvent = new SoundEvent($playerDead->getPositionClone(), SoundType::PLAYER_DEAD); + $this->addSoundEvent($soundEvent->setPlayer($playerDead)); } public function playerFallDamageKilledEvent(Player $playerDead): void @@ -305,15 +304,15 @@ public function playerFallDamageKilledEvent(Player $playerDead): void $this->score->getPlayerStat($playerDead->getId())->addDeath(); $this->addEvent(new KillEvent($playerDead, $playerDead, ItemId::SOLID_SURFACE, false)); - $sound = new SoundEvent($playerDead->getPositionClone(), SoundType::PLAYER_DEAD); - $this->addSoundEvent($sound->setPlayer($playerDead)); + $soundEvent = new SoundEvent($playerDead->getPositionClone(), SoundType::PLAYER_DEAD); + $this->addSoundEvent($soundEvent->setPlayer($playerDead)); } - protected function playerBombKilledEvent(Player $playerDead): void + private function playerBombKilledEvent(Player $playerDead): void { $this->addEvent(new KillEvent($playerDead, $playerDead, ItemId::BOMB, false)); - $sound = new SoundEvent($playerDead->getPositionClone(), SoundType::PLAYER_DEAD); - $this->addSoundEvent($sound->setPlayer($playerDead)->setItem($this->bomb)); + $soundEvent = new SoundEvent($playerDead->getPositionClone(), SoundType::PLAYER_DEAD); + $this->addSoundEvent($soundEvent->setPlayer($playerDead)->setItem($this->bomb)); } private function spawnBomb(): void @@ -342,8 +341,8 @@ private function bombReset(): void public function bombDefused(Player $defuser): void { $defuser->getInventory()->earnMoney(300); - $sound = new SoundEvent($this->bomb->getPosition(), SoundType::BOMB_DEFUSED); - $this->addSoundEvent($sound->setItem($this->bomb)); + $soundEvent = new SoundEvent($this->bomb->getPosition(), SoundType::BOMB_DEFUSED); + $this->addSoundEvent($soundEvent->setItem($this->bomb)); $this->roundEnd(false, RoundEndReason::BOMB_DEFUSED); $this->bombReset(); } @@ -352,12 +351,12 @@ public function bombPlanted(Player $planter): void { $this->bombPlanted = true; $planter->getInventory()->earnMoney(300); - $sound = new SoundEvent($this->bomb->getPosition(), SoundType::BOMB_PLANTED); - $this->addSoundEvent($sound->setItem($this->bomb)); + $soundEvent = new SoundEvent($this->bomb->getPosition(), SoundType::BOMB_PLANTED); + $this->addSoundEvent($soundEvent->setItem($this->bomb)); $event = new PlantEvent(function (): void { - $sound = new SoundEvent($this->bomb->getPosition(), SoundType::BOMB_EXPLODED); - $this->addSoundEvent($sound->setItem($this->bomb)); + $soundEvent = new SoundEvent($this->bomb->getPosition(), SoundType::BOMB_EXPLODED); + $this->addSoundEvent($soundEvent->setItem($this->bomb)); $this->roundEnd(true, RoundEndReason::BOMB_EXPLODED); foreach ($this->getAlivePlayers() as $player) { diff --git a/server/src/Core/GameException.php b/server/src/Core/GameException.php index 34d5fc0..735b967 100644 --- a/server/src/Core/GameException.php +++ b/server/src/Core/GameException.php @@ -4,11 +4,12 @@ use Exception; +/** + * @codeCoverageIgnore + * @infection-ignore-all + */ class GameException extends Exception { - /** - * @codeCoverageIgnore - */ public static function notImplementedYet(string $msg = ''): never { throw new self("Not implemented yet! " . $msg); diff --git a/server/src/Core/HitBox.php b/server/src/Core/HitBox.php index dcc34a7..3a7a1b1 100644 --- a/server/src/Core/HitBox.php +++ b/server/src/Core/HitBox.php @@ -10,7 +10,7 @@ use cs\Interface\Hittable; use cs\Weapon\BaseWeapon; -class HitBox implements Hittable +final class HitBox implements Hittable { private int $moneyAward; private bool $playerWasKilled; @@ -40,14 +40,14 @@ public function getHitAntiForce(Point $point): int if ($this->player->getArmorType()->hasArmorHead()) { return 95; } - return 10; + return 50; } if ($this->player->getArmorType()->hasArmor()) { return 60; } - return 20; + return 30; } public function registerHit(Bullet $bullet): void @@ -66,9 +66,16 @@ public function registerHit(Bullet $bullet): void if ($isTeamDamage) { $healthDamage = (int)ceil($healthDamage / 2); } + $bulletDamage = $bullet->getDamage(); + $armorDamage = $this->calculateArmorDamage($shootItem, $playerArmorType, $hitBoxType); + if ($bulletDamage < $shootItem::damage) { + $portion = ($bulletDamage / $shootItem::damage) * 0.9; + $healthDamage = (int)ceil($healthDamage * $portion); + $armorDamage = (int)ceil($armorDamage * $portion); + } $this->player->lowerHealth($healthDamage); - $this->player->lowerArmor($this->calculateArmorDamage($shootItem, $playerArmorType, $hitBoxType)); + $this->player->lowerArmor($armorDamage); $this->wasHeadShot = ($hitBoxType === HitBoxType::HEAD); $this->damage = $isTeamDamage ? 0 : $healthDamage; if (!$this->player->isAlive()) { diff --git a/server/src/Core/Inventory.php b/server/src/Core/Inventory.php index 93d06e5..78cd254 100644 --- a/server/src/Core/Inventory.php +++ b/server/src/Core/Inventory.php @@ -107,7 +107,7 @@ public function removeSlot(int $slot): void { $item = $this->items[$slot] ?? false; if (!$item) { - return; + return; // @codeCoverageIgnore } if ($this->equippedSlot === $slot) { diff --git a/server/src/Core/Item.php b/server/src/Core/Item.php index 6697dad..d3fb3e1 100644 --- a/server/src/Core/Item.php +++ b/server/src/Core/Item.php @@ -14,7 +14,9 @@ abstract class Item private int $id; private int $skinId; protected bool $equipped = false; + /** @var non-negative-int */ protected int $price = 9999; + /** @var non-negative-int */ protected int $scopeLevel = 0; private ?EquipEvent $eventEquip = null; /** @var array */ @@ -50,21 +52,25 @@ public function isUserDroppable(): bool return true; } + /** @return non-negative-int */ public function getMaxBuyCount(): int { return 5; } + /** @return positive-int */ public function getMaxQuantity(): int { return 1; } + /** @return positive-int */ public function getQuantity(): int { return 1; } + /** @return non-negative-int */ public function getScopeLevel(): int { return $this->scopeLevel; @@ -107,6 +113,7 @@ public function getSkinId(): int return $this->skinId; } + /** @return non-negative-int */ public function getPrice(?self $alreadyHaveSlotItem = null): int { return $this->price; diff --git a/server/src/Core/PathFinder.php b/server/src/Core/PathFinder.php index 8f5ab5e..44c1993 100644 --- a/server/src/Core/PathFinder.php +++ b/server/src/Core/PathFinder.php @@ -34,7 +34,7 @@ public function __construct(private readonly World $world, public readonly int $ $this->obstacleOvercomeHeight = Setting::playerObstacleOvercomeHeight(); } - protected function canFullyMoveTo(Point $candidate, int $angle, int $targetDistance, int $radius, int $height): bool + private function canFullyMoveTo(Point $candidate, int $angle, int $targetDistance, int $radius, int $height): bool { if ($angle % 90 !== 0) { GameException::notImplementedYet(); // @codeCoverageIgnore diff --git a/server/src/Core/Plane.php b/server/src/Core/Plane.php index b928b3c..2375707 100644 --- a/server/src/Core/Plane.php +++ b/server/src/Core/Plane.php @@ -5,6 +5,8 @@ abstract class Plane extends SolidSurface { + public const MAX_HIT_ANTI_FORCE = 99999; + protected bool $penetrable = true; protected int $hitAntiForce = 25123; protected int $hitAntiForceMargin = 10; @@ -26,7 +28,6 @@ public function setPenetrable(bool $penetrable): static public function setHitAntiForce(int $hitAntiForceBody, int $hitAntiForceMargin, int $wallBangEdgeMarginDistance): void { - $this->setPenetrable(true); $this->hitAntiForce = max(0, $hitAntiForceBody); $this->hitAntiForceMargin = max(0, $hitAntiForceMargin); $this->wallBangEdgeMarginDistance = max(0, $wallBangEdgeMarginDistance); @@ -35,11 +36,16 @@ public function setHitAntiForce(int $hitAntiForceBody, int $hitAntiForceMargin, public function getHitAntiForce(Point $point): int { if (!$this->penetrable) { - return 99999; + return self::MAX_HIT_ANTI_FORCE; } - $margin = $this->wallBangEdgeMarginDistance; $hit = $point->to2D($this->axis2d); + if ($hit->x < $this->point2DStart->x || $hit->x > $this->point2DEnd->x + || $hit->y < $this->point2DStart->y || $hit->y > $this->point2DEnd->y) { + throw new GameException("Hit '{$hit}' out of plane boundary '{$this}'"); + } + + $margin = $this->wallBangEdgeMarginDistance; if ($hit->x - $this->point2DStart->x <= $margin || $this->point2DEnd->x - $hit->x <= $margin) { return $this->hitAntiForceMargin; } diff --git a/server/src/Core/Player.php b/server/src/Core/Player.php index e8e1e76..57c3533 100644 --- a/server/src/Core/Player.php +++ b/server/src/Core/Player.php @@ -302,6 +302,7 @@ public static function fromArray(array $data): self /** * @codeCoverageIgnore + * @infection-ignore-all * @return array{id: int, color: int, isAttacker: bool} */ public function toArray(): array diff --git a/server/src/Core/World.php b/server/src/Core/World.php index f7c4b1e..b201605 100644 --- a/server/src/Core/World.php +++ b/server/src/Core/World.php @@ -18,7 +18,7 @@ use cs\Interface\Hittable; use cs\Map\Map; -class World +final class World { private const WALL_X = 'zy'; private const WALL_Z = 'xy'; @@ -291,8 +291,8 @@ public function tryPickDropItems(Player $player): void } if ($player->getInventory()->pickup($dropItem->getItem())) { - $sound = new SoundEvent($dropItem->getPosition(), SoundType::ITEM_PICKUP); - $this->makeSound($sound->setPlayer($player)->setItem($dropItem->getItem())->addExtra('id', $dropItem->getId())); + $soundEvent = new SoundEvent($dropItem->getPosition(), SoundType::ITEM_PICKUP); + $this->makeSound($soundEvent->setPlayer($player)->setItem($dropItem->getItem())->addExtra('id', $dropItem->getId())); unset($this->dropItems[$key]); } } @@ -317,8 +317,8 @@ public function playerUse(Player $player): void if ($this->lastBombActionTick + Util::millisecondsToFrames(50) < $this->getTickId()) { $bomb->reset(); $player->stop(); - $sound = new SoundEvent($player->getPositionClone()->addY(10), SoundType::BOMB_DEFUSING); - $this->makeSound($sound->setPlayer($player)->setItem($bomb)); + $soundEvent = new SoundEvent($player->getPositionClone()->addY(10), SoundType::BOMB_DEFUSING); + $this->makeSound($soundEvent->setPlayer($player)->setItem($bomb)); } $this->lastBombActionTick = $this->getTickId(); $this->lastBombPlayerId = $player->getId(); @@ -347,8 +347,8 @@ public function playerUse(Player $player): void $player->dropItemFromSlot($slotId); } if ($player->getInventory()->pickup($item)) { - $sound = new SoundEvent($dropItem->getPosition(), SoundType::ITEM_PICKUP); - $this->makeSound($sound->setPlayer($player)->setItem($item)->addExtra('id', $dropItem->getId())); + $soundEvent = new SoundEvent($dropItem->getPosition(), SoundType::ITEM_PICKUP); + $this->makeSound($soundEvent->setPlayer($player)->setItem($item)->addExtra('id', $dropItem->getId())); unset($this->dropItems[$key]); if ($shouldEquipOnPickup) { $player->equip($slot); @@ -415,7 +415,7 @@ public function optimizeBulletHitCheck(Bullet $bullet): void $bp = $bullet->getPosition(); $headCrouch = Setting::playerHeadHeightCrouch(); foreach ($this->game->getPlayers() as $playerId => $player) { - if (isset($skipPlayerIds[$playerId])) { + if ($skipPlayerIds[$playerId] ?? false) { continue; } if (!$player->isAlive()) { @@ -443,7 +443,7 @@ public function calculateHits(Bullet $bullet, Point $bulletPosition): array $hits = []; $skipPlayerIds = $bullet->getPlayerSkipIds(); foreach ($this->playersColliders as $playerId => $playerCollider) { - if (isset($skipPlayerIds[$playerId])) { + if ($skipPlayerIds[$playerId] ?? false) { continue; } @@ -599,7 +599,9 @@ public function checkFlameDamage(GrillEvent $fire, int $tickId): void } $fire->playerHit($playerId, $tickId); - $damage = $fire->getItem()->calculateDamage($player->getArmorType() !== ArmorType::NONE); + $flammableItem = $fire->getItem(); + assert($flammableItem instanceof Flammable); + $damage = $flammableItem->calculateDamage($player->getArmorType() !== ArmorType::NONE); assert($fire->item instanceof Item); $this->playerHit( $player->getCentrePoint(), $player, $fire->initiator, SoundType::FLAME_PLAYER_HIT, @@ -607,7 +609,7 @@ public function checkFlameDamage(GrillEvent $fire, int $tickId): void ); $player->lowerHealth($damage); if (!$player->isAlive()) { - $this->playerDiedToFlame($fire->initiator, $player, $fire->getItem()); + $this->playerDiedToFlame($fire->initiator, $player, $flammableItem); } break; @@ -639,7 +641,7 @@ private function processHighExplosiveBlast(Player $thrower, Point $epicentre, Hi foreach ($this->playersColliders as $playerId => $playerCollider) { $player = $this->game->getPlayer($playerId); if (!$player->isAlive()) { - continue; + continue; // @codeCoverageIgnore } if (Util::distanceSquared($epicentre, $player->getCentrePoint()) > $maxBlastDistanceSquared) { continue; @@ -649,7 +651,7 @@ private function processHighExplosiveBlast(Player $thrower, Point $epicentre, Hi foreach ($player->getPlayerGrenadeHitPoints() as $point) { $distanceSquared = Util::distanceSquared($epicentre, $point); if ($distanceSquared > $maxBlastDistanceSquared) { - continue; + continue; // @codeCoverageIgnore } [$angleHorizontal, $angleVertical] = Util::worldAngle($point, $epicentre); if (!$this->pointCanSeePoint($epicentre, $point, $angleHorizontal ?? 0, $angleVertical, $maxBlastDistance, null)) { @@ -715,7 +717,7 @@ public function playerDiedToFallDamage(Player $playerDead): void $this->game->playerFallDamageKilledEvent($playerDead); } - protected function playerDiedToFlame(Player $playerCulprit, Player $playerDead, Flammable $item): void + private function playerDiedToFlame(Player $playerCulprit, Player $playerDead, Flammable $item): void { if (false === ($item instanceof Grenade)) { throw new GameException("New flammable non grenade type?"); // @codeCoverageIgnore @@ -809,7 +811,7 @@ public function surfaceHit(Point $hitPoint, SolidSurface $hit, int $attackerId, $this->makeSound($soundEvent); } - protected function playerHit(Point $hitPoint, Player $playerHit, Player $playerCulprit, SoundType $soundType, Item $item, Point $origin, int $damage): void + private function playerHit(Point $hitPoint, Player $playerHit, Player $playerCulprit, SoundType $soundType, Item $item, Point $origin, int $damage): void { $attackerId = $playerCulprit->getId(); $soundEvent = new SoundEvent($hitPoint, $soundType); @@ -836,8 +838,8 @@ public function tryPlantBomb(Player $player): void if ($this->lastBombActionTick + Util::millisecondsToFrames(200) < $this->getTickId()) { $bomb->reset(); $player->stop(); - $sound = new SoundEvent($player->getPositionClone()->addY(10), SoundType::BOMB_PLANTING); - $this->makeSound($sound->setPlayer($player)->setItem($bomb)); + $soundEvent = new SoundEvent($player->getPositionClone()->addY(10), SoundType::BOMB_PLANTING); + $this->makeSound($soundEvent->setPlayer($player)->setItem($bomb)); } $this->lastBombActionTick = $this->getTickId(); $this->lastBombPlayerId = $player->getId(); @@ -868,14 +870,14 @@ public function isWallOrFloorCollision(Point $start, Point $candidate, int $radi return true; } - if ($start->x <> $candidate->x) { + if ($start->x !== $candidate->x) { $xGrowing = ($start->x < $candidate->x); $baseX = $candidate->clone()->addX($xGrowing ? $radius : -$radius); if ($this->checkXSideWallCollision($baseX, $radius, $radius)) { return true; } } - if ($start->z <> $candidate->z) { + if ($start->z !== $candidate->z) { $zGrowing = ($start->z < $candidate->z); $baseZ = $candidate->clone()->addZ($zGrowing ? $radius : -$radius); if ($this->checkZSideWallCollision($baseZ, $radius, $radius)) { @@ -904,7 +906,7 @@ public function isCollisionWithOtherPlayers(int $playerIdSkip, Point $point, int /** * @return Wall[] */ - protected function getXWalls(int $x): array + private function getXWalls(int $x): array { return ($this->walls[self::WALL_X][$x] ?? []); } @@ -912,7 +914,7 @@ protected function getXWalls(int $x): array /** * @return Wall[] */ - protected function getZWalls(int $z): array + private function getZWalls(int $z): array { return ($this->walls[self::WALL_Z][$z] ?? []); } @@ -921,6 +923,7 @@ protected function getZWalls(int $z): array * @return array> * @internal * @codeCoverageIgnore + * @infection-ignore-all */ public function getWalls(): array { @@ -940,6 +943,7 @@ public function getWalls(): array * @return array> * @internal * @codeCoverageIgnore + * @infection-ignore-all */ public function getFloors(): array { @@ -975,4 +979,9 @@ public function getBacktrack(): Backtrack return $this->game->getBacktrack(); } + public function activeMolotovExists(): bool + { + return ([] !== $this->activeMolotovs); + } + } diff --git a/server/src/Equipment/Flashbang.php b/server/src/Equipment/Flashbang.php index 15dc5b4..a8fab06 100644 --- a/server/src/Equipment/Flashbang.php +++ b/server/src/Equipment/Flashbang.php @@ -8,6 +8,7 @@ class Flashbang extends Grenade { + /** @var positive-int */ private int $quantity = 1; protected int $price = 200; @@ -45,6 +46,7 @@ public function getMaxBuyCount(): int public function decrementQuantity(): void { + assert($this->quantity > 1); $this->quantity--; } diff --git a/server/src/Event/CrouchEvent.php b/server/src/Event/CrouchEvent.php index b65d9cf..571a36b 100644 --- a/server/src/Event/CrouchEvent.php +++ b/server/src/Event/CrouchEvent.php @@ -15,4 +15,9 @@ public function __construct(public bool $directionDown, Closure $callback) $this->moveOffset = Setting::crouchDistancePerTick(); } + public function restartTimer(): void + { + $this->tickCount = 0; + } + } diff --git a/server/src/Event/DropEvent.php b/server/src/Event/DropEvent.php index 476832b..c3ca31c 100644 --- a/server/src/Event/DropEvent.php +++ b/server/src/Event/DropEvent.php @@ -96,8 +96,8 @@ public function process(int $tick): void $collisionPlayer = $world->isCollisionWithOtherPlayers($playerId, $pos, $radius, $height); if ($collisionPlayer && $collisionPlayer->getInventory()->pickup($item)) { - $sound = new SoundEvent($pos->clone(), SoundType::ITEM_PICKUP); - $this->world->makeSound($sound->setPlayer($collisionPlayer)->setItem($item)->addExtra('id', $this->id)); + $soundEvent = new SoundEvent($pos->clone(), SoundType::ITEM_PICKUP); + $this->world->makeSound($soundEvent->setPlayer($collisionPlayer)->setItem($item)->addExtra('id', $this->id)); $this->finish(); return; } @@ -110,8 +110,8 @@ public function process(int $tick): void if ($this->onLand) { call_user_func($this->onLand, $this); } - $sound = new SoundEvent($pos->clone(), SoundType::ITEM_DROP_LAND); - $this->world->makeSound($sound->setPlayer($player)->setItem($item)->addExtra('id', $this->id)); + $soundEvent = new SoundEvent($pos->clone(), SoundType::ITEM_DROP_LAND); + $this->world->makeSound($soundEvent->setPlayer($player)->setItem($item)->addExtra('id', $this->id)); $this->finish(); return; } @@ -122,8 +122,8 @@ public function process(int $tick): void $dropPosition->setFrom($pos); } - $sound = new SoundEvent($pos->clone(), SoundType::ITEM_DROP_AIR); - $this->world->makeSound($sound->setPlayer($player)->setItem($item)->addExtra('id', $this->id)); + $soundEvent = new SoundEvent($pos->clone(), SoundType::ITEM_DROP_AIR); + $this->world->makeSound($soundEvent->setPlayer($player)->setItem($item)->addExtra('id', $this->id)); } public function getDropItem(): DropItem diff --git a/server/src/Event/GrillEvent.php b/server/src/Event/GrillEvent.php index 3192ff1..f0506cf 100644 --- a/server/src/Event/GrillEvent.php +++ b/server/src/Event/GrillEvent.php @@ -5,7 +5,6 @@ use cs\Core\Column; use cs\Core\Point; use cs\Enum\SoundType; -use cs\Interface\Flammable; final class GrillEvent extends VolumetricEvent { @@ -27,19 +26,19 @@ protected function onProcess(int $tick): void protected function shrinkPart(Column $column): void { - $sound = new SoundEvent($column->center, SoundType::FLAME_EXTINGUISH); - $sound->addExtra('id', $this->id); - $this->world->makeSound($sound); + $soundEvent = new SoundEvent($column->center, SoundType::FLAME_EXTINGUISH); + $soundEvent->addExtra('id', $this->id); + $this->world->makeSound($soundEvent); } protected function expandPart(Point $center): Column { $flame = new Column($center, $this->partRadius, $this->partHeight); if ($this->world->flameCanIgnite($flame)) { - $sound = new SoundEvent($flame->center, SoundType::FLAME_SPAWN); - $sound->addExtra('id', $this->id); - $sound->addExtra('height', $flame->height); - $this->world->makeSound($sound); + $soundEvent = new SoundEvent($flame->center, SoundType::FLAME_SPAWN); + $soundEvent->addExtra('id', $this->id); + $soundEvent->addExtra('height', $flame->height); + $this->world->makeSound($soundEvent); } else { $flame->active = false; } @@ -63,8 +62,4 @@ public function playerHit(int $playerId, int $tickId): void $this->playerTickHits[$playerId] = $tickId; } - public function getItem(): Flammable - { - return parent::getItem(); // @phpstan-ignore return.type - } } diff --git a/server/src/Event/SmokeEvent.php b/server/src/Event/SmokeEvent.php index 539a73f..49d6db1 100644 --- a/server/src/Event/SmokeEvent.php +++ b/server/src/Event/SmokeEvent.php @@ -22,9 +22,9 @@ protected function setup(): void protected function shrinkPart(Column $column): void { - $sound = new SoundEvent($column->center, SoundType::SMOKE_FADE); - $sound->addExtra('id', $this->id); - $this->world->makeSound($sound); + $soundEvent = new SoundEvent($column->center, SoundType::SMOKE_FADE); + $soundEvent->addExtra('id', $this->id); + $this->world->makeSound($soundEvent); $this->parts = []; // just do single shrink event } @@ -47,10 +47,10 @@ protected function expandPart(Point $center): Column } $column = new Column($center, $this->partRadius, $height); - $sound = new SoundEvent($column->center, SoundType::SMOKE_SPAWN); - $sound->addExtra('id', $this->id); - $sound->addExtra('height', $column->height); - $this->world->makeSound($sound); + $soundEvent = new SoundEvent($column->center, SoundType::SMOKE_SPAWN); + $soundEvent->addExtra('id', $this->id); + $soundEvent->addExtra('height', $column->height); + $this->world->makeSound($soundEvent); $this->world->smokeTryToExtinguishFlames($column); diff --git a/server/src/Event/SoundEvent.php b/server/src/Event/SoundEvent.php index a38ca5c..a6591a1 100644 --- a/server/src/Event/SoundEvent.php +++ b/server/src/Event/SoundEvent.php @@ -62,4 +62,9 @@ public function getItem(): ?Item return $this->item; } + public function getPlayerId(): ?int + { + return $this->player?->getId(); + } + } diff --git a/server/src/Event/ThrowEvent.php b/server/src/Event/ThrowEvent.php index 16c7c24..2c5d097 100644 --- a/server/src/Event/ThrowEvent.php +++ b/server/src/Event/ThrowEvent.php @@ -202,7 +202,7 @@ public function applyRecoil(float $offsetHorizontal, float $offsetVertical): voi // no recoil on throw } - protected function setAngles(float $angleHorizontal, float $angleVertical): void + private function setAngles(float $angleHorizontal, float $angleVertical): void { $this->angleHorizontal = $angleHorizontal; $this->angleVertical = $angleVertical; diff --git a/server/src/Event/VolumetricEvent.php b/server/src/Event/VolumetricEvent.php index 2fd1d4b..d93aa5f 100644 --- a/server/src/Event/VolumetricEvent.php +++ b/server/src/Event/VolumetricEvent.php @@ -124,18 +124,20 @@ private function expand(int $tick): void } foreach ($candidates as $candidate) { + $part = $this->expandPart($candidate); + $this->boundaryMin->set( - min($this->boundaryMin->x, $candidate->x - $this->partRadius), + min($this->boundaryMin->x, $candidate->x - $part->radius), min($this->boundaryMin->y, $candidate->y - 0), - min($this->boundaryMin->z, $candidate->z - $this->partRadius), + min($this->boundaryMin->z, $candidate->z - $part->radius), ); $this->boundaryMax->set( - max($this->boundaryMax->x, $candidate->x + $this->partRadius), - max($this->boundaryMax->y, $candidate->y + $this->partHeight), - max($this->boundaryMax->z, $candidate->z + $this->partRadius), + max($this->boundaryMax->x, $candidate->x + $part->radius), + max($this->boundaryMax->y, $candidate->y + $part->height), + max($this->boundaryMax->z, $candidate->z + $part->radius), ); - $this->parts[] = $this->expandPart($candidate); + $this->parts[] = $part; } $this->lastPartSpawnTickId = $tick; } diff --git a/server/src/HitGeometry/SphereGroupHitBox.php b/server/src/HitGeometry/SphereGroupHitBox.php index a1112ef..dbf5dca 100644 --- a/server/src/HitGeometry/SphereGroupHitBox.php +++ b/server/src/HitGeometry/SphereGroupHitBox.php @@ -43,6 +43,7 @@ public function createHitBox(Point $relativeCenter, int $radius): SphereHitBox /** * @return SphereHitBox[] + * @infection-ignore-all */ public function getParts(Player $player): array { diff --git a/server/src/Net/Protocol.php b/server/src/Net/Protocol.php index e71f975..06883a7 100644 --- a/server/src/Net/Protocol.php +++ b/server/src/Net/Protocol.php @@ -104,6 +104,7 @@ public abstract function serializeGameSetting(Player $player, ServerSetting $set public abstract function serializeGameState(Game $game): string; + /** @return positive-int */ public abstract function getRequestMaxSizeBytes(): int; /** diff --git a/server/src/Net/Protocol/TextProtocol.php b/server/src/Net/Protocol/TextProtocol.php index 8a0dd96..9650e74 100644 --- a/server/src/Net/Protocol/TextProtocol.php +++ b/server/src/Net/Protocol/TextProtocol.php @@ -14,6 +14,7 @@ class TextProtocol extends Protocol public const separator = '|'; + /** @inheritDoc */ public function getRequestMaxSizeBytes(): int { return 960; diff --git a/server/src/Net/Server.php b/server/src/Net/Server.php index c70e65d..64316d8 100644 --- a/server/src/Net/Server.php +++ b/server/src/Net/Server.php @@ -14,7 +14,7 @@ use Psr\Log\LogLevel; use Psr\Log\NullLogger; -class Server +final class Server { /** @var Client[] [playerId => Client] */ @@ -66,7 +66,7 @@ public function start(): int return $tickCount; } - protected function startWarmup(): bool + private function startWarmup(): bool { $gameReady = false; while ($this->setting->warmupWaitSecRemains >= 0) { @@ -88,7 +88,7 @@ protected function startWarmup(): bool return $gameReady; } - protected function startGame(): int + private function startGame(): int { $this->sendGameStateToClients(); @@ -261,6 +261,7 @@ public function setLogger(LoggerInterface $logger): void $this->logger = $logger; } + /** @infection-ignore-all */ private function log(string $msg, string $level = LogLevel::INFO): void { $this->logger->log($level, $msg); diff --git a/server/src/Traits/Player/AttackTrait.php b/server/src/Traits/Player/AttackTrait.php index ebc6ee8..6b8c77e 100644 --- a/server/src/Traits/Player/AttackTrait.php +++ b/server/src/Traits/Player/AttackTrait.php @@ -38,8 +38,8 @@ public function attack(): ?AttackResult return null; // @codeCoverageIgnore } if ($item instanceof AmmoBasedWeapon && $item->getAmmo() === 0) { - $sound = new SoundEvent($this->getSightPositionClone(), SoundType::ATTACK_NO_AMMO); - $this->world->makeSound($sound->setPlayer($this)->setItem($item)); + $soundEvent = new SoundEvent($this->getSightPositionClone(), SoundType::ATTACK_NO_AMMO); + $this->world->makeSound($soundEvent->setPlayer($this)->setItem($item)); return null; } if (!$item->canAttack($this->world->getTickId())) { @@ -48,8 +48,8 @@ public function attack(): ?AttackResult $result = $item->attack($this->createAttackEvent($item)); if ($result) { - $sound = new SoundEvent($this->getSightPositionClone(), SoundType::ITEM_ATTACK); - $this->world->makeSound($sound->setPlayer($this)->setItem($item)); + $soundEvent = new SoundEvent($this->getSightPositionClone(), SoundType::ITEM_ATTACK); + $this->world->makeSound($soundEvent->setPlayer($this)->setItem($item)); return $this->processAttackResult($result); } return null; // @codeCoverageIgnore @@ -68,8 +68,8 @@ public function attackSecondary(): ?AttackResult if ($item instanceof Knife || $item instanceof Grenade) { $result = $item->attackSecondary($this->createAttackEvent($item)); if ($result) { - $sound = new SoundEvent($this->getSightPositionClone(), SoundType::ITEM_ATTACK2); - $this->world->makeSound($sound->setPlayer($this)->setItem($item)); + $soundEvent = new SoundEvent($this->getSightPositionClone(), SoundType::ITEM_ATTACK2); + $this->world->makeSound($soundEvent->setPlayer($this)->setItem($item)); return $this->processAttackResult($result); } } @@ -169,8 +169,8 @@ public function reload(): void $event = $item->reload(); if ($event) { $this->addEvent($event, $this->eventIdPrimary); - $sound = new SoundEvent($this->getSightPositionClone(), SoundType::ITEM_RELOAD); - $this->world->makeSound($sound->setPlayer($this)->setItem($item)); + $soundEvent = new SoundEvent($this->getSightPositionClone(), SoundType::ITEM_RELOAD); + $this->world->makeSound($soundEvent->setPlayer($this)->setItem($item)); } } diff --git a/server/src/Traits/Player/CrouchTrait.php b/server/src/Traits/Player/CrouchTrait.php index 1b0343a..3293eaf 100644 --- a/server/src/Traits/Player/CrouchTrait.php +++ b/server/src/Traits/Player/CrouchTrait.php @@ -25,18 +25,16 @@ protected function createCrouchEvent(bool $directionDown): void $this->headHeight = Setting::playerHeadHeightCrouch(); } } else { - $targetHeadHeight = $this->headHeight + $event->moveOffset; + $targetHeadHeight = min(Setting::playerHeadHeightStand(), $this->headHeight + $event->moveOffset); $candidate = $this->position->clone(); - for ($h = $this->headHeight + 1; $h <= min($targetHeadHeight, Setting::playerHeadHeightStand()); $h++) { + for ($h = $this->headHeight + 1; $h <= $targetHeadHeight; $h++) { $candidate->setY($this->position->y + $h); if ($this->world->findFloor($candidate, $this->getBoundingRadius())) { - $event->reset(); - $this->addEvent($event, $this->eventIdCrouch); + $event->restartTimer(); break; } if ($this->world->isCollisionWithOtherPlayers($this->getId(), $candidate, $this->getBoundingRadius(), 2)) { - $event->reset(); - $this->addEvent($event, $this->eventIdCrouch); + $event->restartTimer(); break; } $this->headHeight = $h; diff --git a/server/src/Traits/Player/GravityTrait.php b/server/src/Traits/Player/GravityTrait.php index e216b24..c7e6737 100644 --- a/server/src/Traits/Player/GravityTrait.php +++ b/server/src/Traits/Player/GravityTrait.php @@ -65,8 +65,8 @@ private function checkFallDamage(Floor $floor): void $floorHeight = $floor->getY(); $fallHeight = $this->fallHeight - $floorHeight; if ($fallHeight > 3 * Setting::playerObstacleOvercomeHeight()) { - $sound = new SoundEvent($this->getPositionClone()->setY($floorHeight), SoundType::PLAYER_GROUND_TOUCH); - $this->world->makeSound($sound->setPlayer($this)->setSurface($floor)); + $soundEvent = new SoundEvent($this->getPositionClone()->setY($floorHeight), SoundType::PLAYER_GROUND_TOUCH); + $this->world->makeSound($soundEvent->setPlayer($this)->setSurface($floor)); } $threshold = Setting::playerFallDamageThreshold(); diff --git a/server/src/Traits/Player/InventoryTrait.php b/server/src/Traits/Player/InventoryTrait.php index fa4fbd2..87fdb1f 100644 --- a/server/src/Traits/Player/InventoryTrait.php +++ b/server/src/Traits/Player/InventoryTrait.php @@ -83,8 +83,8 @@ public function buyItem(BuyMenuItem $item): bool $equipEvent = $this->inventory->purchase($this, $item); if ($equipEvent) { $this->addEvent($equipEvent, $this->eventIdPrimary); - $sound = new SoundEvent($this->getSightPositionClone(), SoundType::ITEM_BUY); - $this->world->makeSound($sound->setPlayer($this)); + $soundEvent = new SoundEvent($this->getSightPositionClone(), SoundType::ITEM_BUY); + $this->world->makeSound($soundEvent->setPlayer($this)); return true; } diff --git a/server/src/Traits/Player/JumpTrait.php b/server/src/Traits/Player/JumpTrait.php index 326b978..6b9e274 100644 --- a/server/src/Traits/Player/JumpTrait.php +++ b/server/src/Traits/Player/JumpTrait.php @@ -26,7 +26,7 @@ public function jump(): void $targetYPosition = min($jumpEvent->maxYPosition, $this->position->y + Setting::jumpDistancePerTick()); $candidate = $this->position->clone(); for ($y = $this->position->y + 1; $y <= $targetYPosition; $y++) { - $floorCandidate = $this->world->findFloor($candidate->setY($y), $this->playerBoundingRadius); + $floorCandidate = $this->world->findFloorSquare($candidate->setY($y), $this->playerBoundingRadius); if ($floorCandidate) { $targetYPosition = $y - 1; break; diff --git a/server/src/Traits/Player/MovementTrait.php b/server/src/Traits/Player/MovementTrait.php index 2f156c7..6888dba 100644 --- a/server/src/Traits/Player/MovementTrait.php +++ b/server/src/Traits/Player/MovementTrait.php @@ -238,8 +238,8 @@ private function processMovement(int $moveX, int $moveZ, Point $current): Point } if ($this->isRunning() && !$this->isCrouching() && !$this->isFlying() && !$orig->equals($target)) { - $sound = new SoundEvent($target, SoundType::PLAYER_STEP); - $this->world->makeSound($sound->setPlayer($this)); + $soundEvent = new SoundEvent($target, SoundType::PLAYER_STEP); + $this->world->makeSound($soundEvent->setPlayer($this)); } return $target; diff --git a/server/src/Weapon/PistolGlock.php b/server/src/Weapon/PistolGlock.php index 42bd083..6045562 100644 --- a/server/src/Weapon/PistolGlock.php +++ b/server/src/Weapon/PistolGlock.php @@ -14,7 +14,7 @@ final class PistolGlock extends AmmoBasedWeapon public const reserveAmmo = 120; public const killAward = 300; public const fireRateMs = 150; - public const damage = 61; + public const damage = 110; public const rangeMaxDamage = 2600; public const recoilResetMs = 300; public const recoilPattern = [ diff --git a/server/src/Weapon/PistolP250.php b/server/src/Weapon/PistolP250.php index 8a2d038..1017c4f 100644 --- a/server/src/Weapon/PistolP250.php +++ b/server/src/Weapon/PistolP250.php @@ -14,7 +14,7 @@ final class PistolP250 extends AmmoBasedWeapon public const reserveAmmo = 26; public const killAward = 300; public const fireRateMs = 150; - public const damage = 61; + public const damage = 130; public const rangeMaxDamage = 3000; public const recoilResetMs = 400; public const recoilPattern = [ diff --git a/server/src/Weapon/RifleAWP.php b/server/src/Weapon/RifleAWP.php index b26fb49..0ce170b 100644 --- a/server/src/Weapon/RifleAWP.php +++ b/server/src/Weapon/RifleAWP.php @@ -15,7 +15,7 @@ class RifleAWP extends AmmoBasedWeapon implements ScopeItem public const reserveAmmo = 30; public const killAward = 100; public const fireRateMs = 1463; - public const damage = 270; + public const damage = 350; public const armorPenetration = 90; protected bool $isWeaponPrimary = true; diff --git a/server/src/Weapon/RifleAk.php b/server/src/Weapon/RifleAk.php index f54f5f9..9fcc584 100644 --- a/server/src/Weapon/RifleAk.php +++ b/server/src/Weapon/RifleAk.php @@ -15,7 +15,7 @@ final class RifleAk extends AmmoBasedWeapon public const killAward = 300; public const runningSpeed = 215; public const fireRateMs = 100; - public const damage = 36; + public const damage = 190; public const armorPenetration = 77; public const recoilResetMs = 330; public const recoilPattern = [ diff --git a/server/src/Weapon/RifleM4A4.php b/server/src/Weapon/RifleM4A4.php index 929dfe6..e81fd5d 100644 --- a/server/src/Weapon/RifleM4A4.php +++ b/server/src/Weapon/RifleM4A4.php @@ -15,7 +15,7 @@ final class RifleM4A4 extends AmmoBasedWeapon public const killAward = 300; public const runningSpeed = 215; public const fireRateMs = 90; - public const damage = 33; + public const damage = 170; public const armorPenetration = 67; public const recoilResetMs = 310; public const recoilPattern = [ diff --git a/test/og/BaseTestCase.php b/test/og/BaseTestCase.php index 0c07ff0..5f77b27 100644 --- a/test/og/BaseTestCase.php +++ b/test/og/BaseTestCase.php @@ -75,6 +75,7 @@ protected function createOneRoundGame(int $tickMax = 1, array $gameProperties = GameProperty::FREEZE_TIME_SEC => 0, GameProperty::ROUND_END_COOL_DOWN_SEC => 0, GameProperty::RANDOMIZE_SPAWN_POSITION => false, + GameProperty::ROUND_TIME_MS => 1000, ], ...$gameProperties, ] @@ -121,6 +122,7 @@ protected function createNoPauseGameProperty(int $maxRounds = 1): GameProperty $properties->half_time_freeze_sec = 0; $properties->round_end_cool_down_sec = 0; $properties->randomize_spawn_position = false; + $properties->round_time_ms = 30000; return $properties; } diff --git a/test/og/Game/RoundTest.php b/test/og/Game/RoundTest.php index d79b2f2..42a4f93 100644 --- a/test/og/Game/RoundTest.php +++ b/test/og/Game/RoundTest.php @@ -9,6 +9,7 @@ use cs\Core\Util; use cs\Enum\BuyMenuItem; use cs\Enum\Color; +use cs\Enum\InventorySlot; use cs\Enum\SoundType; use cs\Equipment\Bomb; use cs\Event\GameOverEvent; @@ -200,6 +201,7 @@ public function testHalfTimeSwitch(): void GameProperty::HALF_TIME_FREEZE_SEC => 0, GameProperty::START_MONEY => 3000, ]); + $playerAttackerSpawnPosition = $game->getPlayer(1)->getPositionClone(); $game->setTickMax($maxRounds * 2); $this->assertTrue($game->getPlayer(1)->isPlayingOnAttackerSide()); @@ -215,6 +217,9 @@ public function testHalfTimeSwitch(): void $this->assertFalse($game->getScore()->attackersIsWinning()); $this->assertSame(3, $game->getScore()->getScoreDefenders()); $this->assertSame(2, $game->getScore()->getScoreAttackers()); + $this->assertSame(9500, $game->getPlayer(1)->getMoney()); + $this->assertPositionNotSame($playerAttackerSpawnPosition, $game->getPlayer(1)->getPositionClone()); + $this->assertFalse($game->getPlayer(1)->getInventory()->has(InventorySlot::SLOT_BOMB->value)); } } diff --git a/test/og/Inventory/SimpleInventoryTest.php b/test/og/Inventory/SimpleInventoryTest.php index 73f1c71..d469898 100644 --- a/test/og/Inventory/SimpleInventoryTest.php +++ b/test/og/Inventory/SimpleInventoryTest.php @@ -12,9 +12,11 @@ use cs\Enum\BuyMenuItem; use cs\Enum\Color; use cs\Enum\InventorySlot; +use cs\Enum\SoundType; use cs\Equipment\Decoy; use cs\Equipment\Flashbang; use cs\Equipment\HighExplosive; +use cs\Event\SoundEvent; use cs\Weapon\Knife; use cs\Weapon\PistolGlock; use cs\Weapon\PistolUsp; @@ -54,7 +56,7 @@ public function testPlayerInventorySlots(): void $this->assertInstanceOf(Knife::class, $knife); $this->assertInstanceOf(PistolUsp::class, $pistol); $expectedSlots = [ - InventorySlot::SLOT_KNIFE->value => $knife->toArray(), + InventorySlot::SLOT_KNIFE->value => $knife->toArray(), InventorySlot::SLOT_SECONDARY->value => $pistol->toArray(), ]; $this->assertTrue($p->getInventory()->has(InventorySlot::SLOT_SECONDARY->value)); @@ -111,6 +113,29 @@ public function testPlayerBuyAndDropPrimaryWithEnoughMoney(): void $game->getPlayer(1)->dropEquippedItem(); } + public function testDropResetEquipped(): void + { + $game = $this->createNoPauseGame(); + $glock = null; + $this->playPlayer($game, [ + fn(Player $p) => $p->equipSecondaryWeapon(), + fn(Player $p) => $this->assertFalse($p->getEquippedItem()->isEquipped()), + $this->waitNTicks(PistolGlock::equipReadyTimeMs), + fn(Player $p) => $this->assertTrue($p->getEquippedItem()->isEquipped()), + function (Player $p) use (&$glock) { + $glock = $p->getEquippedItem(); + }, + fn(Player $p) => $this->assertNotNull($p->dropEquippedItem()), + fn(Player $p) => $this->assertFalse($p->getEquippedItem()->isEquipped()), + $this->endGame(), + ]); + + $this->assertInstanceOf(PistolGlock::class, $glock); + $this->assertFalse($glock->isEquipped()); + $this->assertFalse($glock->isReloading()); + $this->assertTrue($glock->isUserDroppable()); + } + public function testPlayerGetPistolOnRoundStartIfHasNone(): void { $game = $this->createNoPauseGame(10); @@ -155,7 +180,16 @@ public function testPlayerBuyAndDropAndUseForPickup(): void $p->getInventory()->earnMoney(15000); $this->playPlayer($game, [ + fn(Player $p) => $this->assertEmpty($game->getWorld()->getDropItems()), fn(Player $p) => $p->getSight()->lookVertical(-60), + fn(Player $p) => $this->assertInstanceOf(Knife::class, $p->getEquippedItem()), + fn(Player $p) => $p->equipSecondaryWeapon(), + fn(Player $p) => $this->assertNotNull($p->dropEquippedItem()), + $this->waitNTicks(200), + fn(Player $p) => $this->assertNotEmpty($game->getWorld()->getDropItems()), + fn(Player $p) => $p->use(), + fn(Player $p) => $this->assertEmpty($game->getWorld()->getDropItems()), + fn(Player $p) => $this->assertInstanceOf(Knife::class, $p->getEquippedItem()), fn(Player $p) => $this->assertTrue($p->buyItem(BuyMenuItem::RIFLE_AK)), fn(Player $p) => $this->assertInstanceOf(RifleAk::class, $p->getEquippedItem()), fn(Player $p) => $this->assertTrue($p->getInventory()->has(InventorySlot::SLOT_PRIMARY->value)), @@ -232,6 +266,18 @@ public function testDropToOtherPlayer(): void $game->addPlayer(new Player(2, Color::GREEN, false)); $game->getPlayer(2)->setPosition(new Point(150, 0, 150)); + $pickEvent = null; + $game->onEvents(function (array $events) use (&$pickEvent): void { + foreach ($events as $event) { + if ($event instanceof SoundEvent && $event->type === SoundType::ITEM_PICKUP) { + $this->assertNull($pickEvent); + $pickEvent = $event; + $this->assertSame(1, $event->getPlayerId()); + $this->assertInstanceOf(RifleM4A4::class, $event->getItem()); + } + } + }); + $this->playPlayer($game, [ fn(Player $p) => $p->getInventory()->earnMoney(5000), fn(Player $p) => $this->assertFalse($p->getInventory()->has(InventorySlot::SLOT_PRIMARY->value)), @@ -247,6 +293,7 @@ public function testDropToOtherPlayer(): void ], 2); $this->assertTrue($game->getPlayer(1)->getInventory()->has(InventorySlot::SLOT_PRIMARY->value)); + $this->assertNotNull($pickEvent); } public function testDropWallCollision(): void @@ -400,6 +447,7 @@ function (Player $p) { $this->assertTrue($p->getInventory()->has(InventorySlot::SLOT_PRIMARY->value)); $this->assertTrue($p->getInventory()->has(InventorySlot::SLOT_SECONDARY->value)); + $this->assertFalse($p->dropItemFromSlot(InventorySlot::SLOT_KIT->value)); $this->assertFalse($p->dropItemFromSlot(InventorySlot::SLOT_KNIFE->value)); $this->assertTrue($p->dropItemFromSlot(InventorySlot::SLOT_PRIMARY->value)); @@ -413,6 +461,24 @@ function (Player $p) { ]); } + public function testIncrementItemQuantity(): void + { + $game = $this->createTestGame(); + $this->playPlayer($game, [ + fn(Player $p) => $p->getSight()->look(0, 90), + fn(Player $p) => $this->assertTrue($p->buyItem(BuyMenuItem::GRENADE_FLASH)), + fn(Player $p) => $this->assertTrue($p->buyItem(BuyMenuItem::GRENADE_FLASH)), + fn(Player $p) => $this->assertInstanceOf(Flashbang::class, $p->getEquippedItem()), + fn(Player $p) => $this->assertSame(2, $p->getEquippedItem()->getQuantity()), + fn(Player $p) => $this->assertNotNull($p->dropEquippedItem()), + fn(Player $p) => $this->assertInstanceOf(Flashbang::class, $p->getEquippedItem()), + fn(Player $p) => $this->assertSame(1, $p->getEquippedItem()->getQuantity()), + $this->waitNTicks(1000), + fn(Player $p) => $this->assertSame(2, $p->getEquippedItem()->getQuantity()), + $this->endGame(), + ]); + } + public function testPlayerBuyTwoFlashes(): void { $startMoney = 600; @@ -477,7 +543,9 @@ public function testPlayerBuyMaxFourGrenades(): void public function testCancelReload(): void { - $playerCommands = [ + $game = $this->createNoPauseGame(); + $this->playPlayer($game, [ + fn(Player $p) => $p->getInventory()->earnMoney(6123), fn(Player $p) => $p->getSight()->lookVertical(-90), fn(Player $p) => $p->buyItem(BuyMenuItem::RIFLE_AK), function (Player $p): void { @@ -496,13 +564,13 @@ function (Player $p): void { }, fn(Player $p) => $this->assertNotNull($p->attack()), fn(Player $p) => $p->reload(), - 2, + fn(Player $p) => $this->assertFalse($game->getWorld()->canAttack($p)), fn(Player $p) => $p->equipKnife(), fn(Player $p) => $p->equipPrimaryWeapon(), $this->waitNTicks(max(RifleAk::reloadTimeMs, RifleAk::equipReadyTimeMs)), - ]; + $this->endGame(), + ]); - $game = $this->simulateGame($playerCommands, [GameProperty::START_MONEY => 6123]); $ak = $game->getPlayer(1)->getEquippedItem(); $this->assertInstanceOf(RifleAk::class, $ak); $this->assertSame(RifleAk::magazineCapacity - 1, $ak->getAmmo()); diff --git a/test/og/Movement/MovementTest.php b/test/og/Movement/MovementTest.php index 52b1acc..70ea629 100644 --- a/test/og/Movement/MovementTest.php +++ b/test/og/Movement/MovementTest.php @@ -12,6 +12,8 @@ use cs\Core\Wall; use cs\Enum\BuyMenuItem; use cs\Enum\Color; +use cs\Enum\SoundType; +use cs\Event\SoundEvent; use Test\BaseTestCase; class MovementTest extends BaseTestCase @@ -132,6 +134,24 @@ public function testPlayerIncrementYBySteppingOnSmallWall(): void $this->assertPlayerPosition($game, new Point(0, $wall->getCeiling(), Setting::moveDistancePerTick())); } + public function testPlayerMakeStepNoise(): void + { + $game = $this->createOneRoundGame(2); + $stepSound = null; + $game->onEvents(function (array $events) use (&$stepSound): void { + foreach ($events as $event) { + if ($event instanceof SoundEvent && $event->type === SoundType::PLAYER_STEP) { + $stepSound = $event; + $this->assertSame(1, $event->getPlayerId()); + } + } + }); + $game->onTick(fn(GameState $state) => $state->getPlayer(1)->moveForward()); + + $game->start(); + $this->assertNotNull($stepSound); + } + public function testPlayerSlowMovementWhenHaveGun(): void { $game = $this->createOneRoundGame(1, [GameProperty::START_MONEY => 8123]); @@ -294,7 +314,11 @@ public function testPlayerSlowMovementWhenTouchingWallAngle1(): void public function testPlayerMultiJump(): void { $pc = [ + fn(Player $p) => $this->assertFalse($p->isJumping()), + fn(Player $p) => $this->assertTrue($p->canJump()), fn(Player $p) => $p->jump(), + fn(Player $p) => $this->assertTrue($p->isJumping()), + fn(Player $p) => $this->assertFalse($p->canJump()), fn(Player $p) => $p->jump(), fn(Player $p) => $p->jump(), function (Player $p) { diff --git a/test/og/Movement/WorldCollisionTest.php b/test/og/Movement/WorldCollisionTest.php index dcb04b0..f98dc79 100644 --- a/test/og/Movement/WorldCollisionTest.php +++ b/test/og/Movement/WorldCollisionTest.php @@ -102,6 +102,8 @@ public function testPlayerDieOnFallDamage(): void $game = $this->simulateGame($playerCommands); $this->assertFalse($game->getPlayer(1)->isAlive()); + $this->assertSame(-1, $game->getScore()->getPlayerStat(1)->getKills()); + $this->assertSame(1, $game->getScore()->getPlayerStat(1)->getDeaths()); } public function testPlayerCollisionWithWallWalkBypass(): void diff --git a/test/og/Shooting/BacktrackTest.php b/test/og/Shooting/BacktrackTest.php index a0f6c62..745f357 100644 --- a/test/og/Shooting/BacktrackTest.php +++ b/test/og/Shooting/BacktrackTest.php @@ -9,6 +9,9 @@ use cs\Core\Wall; use cs\Enum\Color; use cs\Enum\GameOverReason; +use cs\Enum\SoundType; +use cs\Event\GameOverEvent; +use cs\Event\SoundEvent; use cs\Weapon\PistolGlock; use Test\BaseTestCase; use Test\TestGame; @@ -23,19 +26,19 @@ private function _setupGame1(int $backtrackTickCount): TestGame $game = $this->createTestGame(null, $property); $player1 = $game->getPlayer(1); $player1->setPosition($player1->getPositionClone()->addX($player1->getBoundingRadius())); - $player1->getSight()->lookHorizontal(1); + $player1->getSight()->look(0, 0); $player1->equipSecondaryWeapon(); - $game->getWorld()->addWall( - new Wall( - new Point($player1->getBoundingRadius(), 1, $player1->getPositionClone()->z + $player1->getBoundingRadius() + 30), - true, - 20 - ) + $glock = $player1->getEquippedItem(); + $this->assertInstanceOf(PistolGlock::class, $glock); + $wall = new Wall( + new Point($player1->getPositionClone()->x + 1, 0, $player1->getPositionClone()->z + $player1->getBoundingRadius() + 30), true, 800 ); + $game->getWorld()->addWall($wall->setPenetrable(false)); $player2 = new Player(2, Color::GREEN, false); $game->addPlayer($player2); $player2->setPosition($player1->getPositionClone()->addZ($player1->getBoundingRadius() + 100)); + $game->getWorld()->addWall(new Wall(new Point(0, 0, $player2->getPositionClone()->z + 300), true, 800)); $this->assertTrue($player1->isAlive()); $this->assertTrue($player2->isAlive()); @@ -119,7 +122,7 @@ public function test1BacktrackEnableTwoTick(): void $state->getPlayer(2)->moveRight(); if ($i === 2) { - $result = $this->assertPlayerHit($state->getPlayer(1)->attack()); + $result = $this->assertPlayerHit($state->getPlayer(1)->attack()); $this->assertFalse($state->getPlayer(2)->isAlive()); $game->quit(GameOverReason::TIE); } @@ -156,21 +159,40 @@ public function test1BacktrackEnableFourTick(): void $game = $this->_setupGame1(4); $i = 0; $result = null; - $game->onTick(function (GameState $state) use ($game, &$i, &$result) { + $deadSound = null; + $player2InitialPosition = $game->getPlayer(2)->getPositionClone(); + $game->onEvents(function (array $events) use (&$deadSound, $player2InitialPosition): void { + foreach ($events as $event) { + if ($event instanceof SoundEvent && $event->type === SoundType::PLAYER_DEAD) { + $this->assertNull($deadSound); + $deadSound = $event; + $this->assertPositionSame($player2InitialPosition, $deadSound->position); + } + } + }); + $game->onTick(function (GameState $state) use ($game, &$i, &$result, $player2InitialPosition) { if ($state->getTickId() <= Util::millisecondsToFrames(PistolGlock::equipReadyTimeMs)) { return; } $state->getPlayer(2)->moveRight(); if ($i === 3) { + $this->assertPositionNotSame($player2InitialPosition, $state->getPlayer(2)->getPositionClone()); $result = $this->assertPlayerHit($state->getPlayer(1)->attack()); $this->assertFalse($state->getPlayer(2)->isAlive()); + } + if ($i === 4) { $game->quit(GameOverReason::TIE); + $tickEvents = $game->consumeTickEvents(); + $this->assertCount(1, $tickEvents); + $this->assertInstanceOf(GameOverEvent::class, $tickEvents[0]); } $i++; }); $game->start(); + $this->assertPositionNotSame($player2InitialPosition, $game->getPlayer(2)->getPositionClone()); $this->assertNotNull($result); + $this->assertNotNull($deadSound); } } diff --git a/test/og/Shooting/GrenadeTest.php b/test/og/Shooting/GrenadeTest.php index 7623144..697eff5 100644 --- a/test/og/Shooting/GrenadeTest.php +++ b/test/og/Shooting/GrenadeTest.php @@ -12,6 +12,7 @@ use cs\Enum\SoundType; use cs\Equipment\Decoy; use cs\Equipment\Flashbang; +use cs\Equipment\Smoke; use cs\Event\SoundEvent; use Test\BaseTestCase; @@ -439,5 +440,28 @@ public function testExtremePosition(): void $this->assertFalse($test->goingUp); } + public function testSmokeCanBounceOnFloorBeforePopping(): void + { + $bounceCount = 0; + $game = $this->createTestGame(); + $game->onEvents(function (array $events) use (&$bounceCount): void { + foreach ($events as $event) { + if ($event instanceof SoundEvent && $event->type === SoundType::GRENADE_BOUNCE) { + $bounceCount++; + } + } + }); + $this->playPlayer($game, [ + fn(Player $p) => $p->crouch(), + fn(Player $p) => $p->getSight()->look(45, -89), + fn(Player $p) => $this->assertTrue($p->buyItem(BuyMenuItem::GRENADE_SMOKE)), + $this->waitNTicks(Smoke::equipReadyTimeMs), + fn(Player $p) => $this->assertNotNull($p->attack()), + $this->waitNTicks(900), + $this->endGame(), + ]); + + $this->assertGreaterThan(1, $bounceCount); + } } diff --git a/test/og/Shooting/MolotovGrenadeTest.php b/test/og/Shooting/MolotovGrenadeTest.php index a63c33f..f4c824a 100644 --- a/test/og/Shooting/MolotovGrenadeTest.php +++ b/test/og/Shooting/MolotovGrenadeTest.php @@ -3,6 +3,7 @@ namespace Test\Shooting; use cs\Core\Box; +use cs\Core\Column; use cs\Core\Player; use cs\Core\Point; use cs\Core\Ramp; @@ -46,11 +47,50 @@ public function testOwnDamage(): void ]); } + public function testShrinkPhaseDoDamage(): void + { + $game = $this->createNoPauseGame(); + $game->getPlayer(1)->setPosition(new Point(500, 0, 500)); + $game->getWorld()->addBox(new Box(new Point(), 1000, 3000, 1000)); + $health = $game->getPlayer(1)->getHealth(); + + $shrinkPhase = false; + $game->onEvents(function (array $events) use (&$shrinkPhase, $game): void { + foreach ($events as $event) { + if ($shrinkPhase === false && $event instanceof SoundEvent && $event->type === SoundType::FLAME_EXTINGUISH) { + $shrinkPhase = true; + + $p = $game->getPlayer(1); + $this->assertSame(100, $p->getHealth()); + $this->assertTrue($game->getWorld()->activeMolotovExists()); + $p->setPosition(new Point(500, 0, 500)); + } + } + }); + + $this->playPlayer($game, [ + fn(Player $p) => $p->getSight()->look(0, -90), + fn(Player $p) => $this->assertTrue($p->buyItem(BuyMenuItem::GRENADE_MOLOTOV)), + $this->waitNTicks(Molotov::equipReadyTimeMs), + fn(Player $p) => $this->assertSame($health, $p->getHealth()), + fn(Player $p) => $this->assertNotNull($p->attack()), + fn(Player $p) => $p->setPosition(new Point(1000, 0, 1200)), + $this->waitNTicks(2 * Molotov::MAX_TIME_MS), + $this->endGame(), + ]); + + $this->assertTrue($shrinkPhase); + $this->assertFalse($game->getWorld()->activeMolotovExists()); + $this->assertTrue($game->getPlayer(1)->isAlive()); + $this->assertLessThan(100, $game->getPlayer(1)->getHealth()); + } + public function testMolotovOnlyTookMaxOneRound(): void { $game = $this->createNoPauseGame(3); $game->getPlayer(1)->setPosition(new Point(Setting::playerBoundingRadius(), 0, Setting::playerBoundingRadius())); $game->getWorld()->addBox(new Box(new Point(), 1000, 3000, 1000)); + $game->getWorld()->regenerateNavigationMeshes(); $roundEndEvent = null; $game->onEvents(function (array $events) use (&$roundEndEvent): void { @@ -162,9 +202,17 @@ public function testStandOnTallWallAvoidFire(): void fn(Player $p) => $this->assertNotNull($p->attack()), $this->waitNTicks(300), function (Player $p) use (&$health, $game) { + $this->assertSame(1, $game->getRoundNumber()); + $this->assertTrue($game->getWorld()->activeMolotovExists()); $this->assertLessThan($health, $p->getHealth()); $p->setPosition(new Point(500, $game->getWorld()::GRENADE_NAVIGATION_MESH_OBJECT_HEIGHT + 10, 500)); $health = $p->getHealth(); + + $this->assertTrue($game->getWorld()->isCollisionWithMolotov(new Point(500, 0, 460))); + $this->assertFalse($game->getWorld()->isCollisionWithMolotov($p->getPositionClone())); + $this->assertFalse($game->getWorld()->isCollisionWithMolotov(new Point(500, $game->getWorld()::GRENADE_NAVIGATION_MESH_OBJECT_HEIGHT, 500))); + $this->assertFalse($game->getWorld()->isCollisionWithMolotov(new Point(-1, 0, 500))); + $this->assertFalse($game->getWorld()->isCollisionWithMolotov(new Point(500, 0, 1001))); }, $this->waitNTicks(Molotov::MAX_TIME_MS), function (Player $p) use (&$health) { @@ -172,6 +220,8 @@ function (Player $p) use (&$health) { }, $this->endGame(), ]); + + $this->assertFalse($game->getWorld()->activeMolotovExists()); } public function testTunnelExpand(): void @@ -284,6 +334,23 @@ public function testSmokeExtinguishFlames(): void fn(Player $p) => $this->assertTrue($p->equip(InventorySlot::SLOT_GRENADE_MOLOTOV)), $this->waitNTicks(Molotov::equipReadyTimeMs), $this->waitNTicks((int)ceil(Smoke::MAX_TIME_MS / 3)), + function () use ($game) { + $this->assertFalse( + $game->getWorld()->flameCanIgnite(new Column($game->getPlayer(1)->getPositionClone(), 2, 2)) + ); + $this->assertFalse( + $game->getWorld()->flameCanIgnite(new Column($game->getPlayer(1)->getPositionClone()->setY(Smoke::MAX_HEIGHT - 100), 2, 2)) + ); + $this->assertFalse( + $game->getWorld()->flameCanIgnite(new Column($game->getPlayer(1)->getPositionClone()->setY(Smoke::MAX_HEIGHT), 2, 2)) + ); + $this->assertTrue( + $game->getWorld()->flameCanIgnite(new Column($game->getPlayer(1)->getPositionClone()->setY(Smoke::MAX_HEIGHT + 2), 2, 2)) + ); + $this->assertFalse( + $game->getWorld()->flameCanIgnite(new Column($game->getPlayer(1)->getPositionClone()->setY(Smoke::MAX_CORNER_HEIGHT), 2, 2)) + ); + }, fn(Player $p) => $p->getSight()->look(0, -90), fn(Player $p) => $this->assertNotNull($p->attack()), fn(Player $p) => $this->assertSame($health, $p->getHealth()), diff --git a/test/og/Shooting/PlayerKillTest.php b/test/og/Shooting/PlayerKillTest.php index 0dd89d2..cfc1662 100644 --- a/test/og/Shooting/PlayerKillTest.php +++ b/test/og/Shooting/PlayerKillTest.php @@ -66,6 +66,7 @@ public function testOnePlayerCanKillOther(): void $this->assertNull($player2->attack()); $this->assertTrue($headHit->getType() === HitBoxType::HEAD); $this->assertSame($startMoney - $gun->getPrice() + $gun->getKillAward(), $player2->getMoney()); + $this->assertGreaterThan(0, $headHit->getHitAntiForce(new Point())); $this->expectException(GameException::class); $game->addPlayer(new Player($player2->getId(), Color::BLUE, true)); @@ -312,7 +313,10 @@ function (Player $p) { $this->assertInstanceOf(AttackResult::class, $ar); $this->assertTrue($ar->somePlayersWasHit()); $hits = $ar->getHits(); - $this->assertCount(3, $hits); + $this->assertCount(4, $hits); + $hit = array_pop($hits); + $this->assertInstanceOf(HitBox::class, $hit); + $this->assertFalse($hit->playerWasKilled()); foreach ($hits as $hit) { $this->assertTrue($hit->playerWasKilled()); $this->assertTrue($hit->wasHeadShot()); @@ -529,4 +533,110 @@ function (Player $p) { $this->assertSame(3 + 1, $game->getRoundNumber()); } + public function testPlayerCannotKillDeadPlayer(): void + { + $game = $this->createNoPauseGame(15); + $game->addPlayer(new Player(2, Color::GREEN, false)); + $game->getPlayer(2)->setPosition(new Point(200, 0, 500)); + $game->addPlayer(new Player(3, Color::GREEN, false)); + $game->getPlayer(3)->setPosition(new Point(999, 0, 10)); + + $this->playPlayer($game, [ + fn(Player $p) => $p->setPosition(new Point(200, 0, 300)), + fn(Player $p) => $p->getSight()->look(0, 0), + fn(Player $p) => $p->equipSecondaryWeapon(), + $this->waitNTicks(PistolGlock::equipReadyTimeMs), + fn(Player $p) => $this->assertPlayerHit($p->attack()), + fn() => $this->assertFalse($game->getPlayer(2)->isAlive()), + $this->waitNTicks(PistolGlock::fireRateMs), + fn(Player $p) => $this->assertPlayerNotHit($p->attack()), + fn(Player $p) => $this->assertSame(1, $game->getRoundNumber()), + $this->endGame(), + ]); + } + + public function testPlayerHitBoxReset(): void + { + $game = $this->createNoPauseGame(15); + $game->addPlayer(new Player(2, Color::GREEN, false)); + + $this->playPlayer($game, [ + fn() => $game->getPlayer(2)->setPosition(new Point(200, 0, 500)), + fn() => $game->getPlayer(2)->getSight()->lookHorizontal(180), + fn(Player $p) => $p->setPosition(new Point(200, 0, 300)), + fn(Player $p) => $p->getSight()->look(0, -20), + fn(Player $p) => $p->equipSecondaryWeapon(), + $this->waitNTicks(PistolGlock::equipReadyTimeMs), + fn(Player $p) => $this->assertSame(0, $this->assertPlayerHit($p->attack())->getMoneyAward()), + fn(Player $p) => $this->assertSame(1, $game->getRoundNumber()), + $this->waitNTicks(PistolGlock::fireRateMs), + fn(Player $p) => $this->assertSame(0, $this->assertPlayerHit($p->attack())->getMoneyAward()), + fn(Player $p) => $this->assertSame(1, $game->getRoundNumber()), + $this->waitNTicks(PistolGlock::fireRateMs), + fn(Player $p) => $this->assertGreaterThan(0, $this->assertPlayerHit($p->attack())->getMoneyAward()), + fn(Player $p) => $this->assertSame(2, $game->getRoundNumber()), + fn() => $game->getPlayer(2)->setPosition(new Point(200, 0, 500)), + fn() => $game->getPlayer(2)->getSight()->lookHorizontal(180), + fn(Player $p) => $p->setPosition(new Point(200, 0, 300)), + fn(Player $p) => $p->getSight()->look(0, -20), + fn(Player $p) => $p->equipSecondaryWeapon(), + $this->waitNTicks(PistolGlock::equipReadyTimeMs), + function (Player $p) { + $result = $this->assertPlayerHit($p->attack()); + $hits = $result->getHits(); + $this->assertCount(2, $hits); + $this->assertInstanceOf(Floor::class, $hits[1]); + $playerHit = $hits[0]; + $this->assertInstanceOf(HitBox::class, $playerHit); + $this->assertSame(HitBoxType::STOMACH, $playerHit->getType()); + $this->assertFalse($playerHit->playerWasKilled()); + $this->assertSame(0, $playerHit->getMoneyAward()); + }, + fn() => $this->assertTrue($game->getPlayer(2)->isAlive()), + $this->endGame(), + ]); + + $this->assertSame(2, $game->getRoundNumber()); + } + + public function testBulletCanHitTwoPlayers(): void + { + $game = $this->createNoPauseGame(); + $game->addPlayer(new Player(2, Color::BLUE, false)); + $game->addPlayer(new Player(3, Color::GREEN, false)); + + $this->playPlayer($game, [ + fn(Player $p) => $p->setPosition(new Point(600, 0, 500)), + fn(Player $p) => $p->getSight()->look(-90, 0), + fn() => $game->getPlayer(2)->setPosition(new Point(400, 0, 500)), + fn() => $game->getPlayer(3)->setPosition(new Point(200, 0, 500)), + fn(Player $p) => $p->equipSecondaryWeapon(), + $this->waitNTicks(PistolGlock::equipReadyTimeMs), + function (Player $p) use ($game) { + $result = $this->assertPlayerHit($p->attack()); + $hits = $result->getHits(); + $this->assertCount(3, $hits); + $this->assertInstanceOf(Wall::class, $hits[2]); + $this->assertSame(1, $game->getRoundNumber()); + $this->assertGreaterThan(0, $result->getMoneyAward()); + + $playerHit = $hits[1]; + $this->assertInstanceOf(HitBox::class, $playerHit); + $this->assertSame(3, $playerHit->getPlayer()->getId()); + $this->assertFalse($playerHit->playerWasKilled()); + + $playerHit = $hits[0]; + $this->assertInstanceOf(HitBox::class, $playerHit); + $this->assertSame(2, $playerHit->getPlayer()->getId()); + $this->assertTrue($playerHit->playerWasKilled()); + }, + fn() => $this->assertSame(1, $game->getRoundNumber()), + fn() => $this->assertFalse($game->getPlayer(2)->isAlive()), + fn() => $this->assertTrue($game->getPlayer(3)->isAlive()), + fn() => $this->assertLessThan(100, $game->getPlayer(3)->getHealth()), + fn() => $this->assertGreaterThan(25, $game->getPlayer(3)->getHealth()), + $this->endGame(), + ]); + } + } diff --git a/test/og/Shooting/RecoilTest.php b/test/og/Shooting/RecoilTest.php index 965bc3c..368f8ee 100644 --- a/test/og/Shooting/RecoilTest.php +++ b/test/og/Shooting/RecoilTest.php @@ -56,13 +56,17 @@ public function testRifleMovementRecoil(): void $game->onTick(function (GameState $state) use (&$bulletsYCoords, $ak) { $player = $state->getPlayer(1); $player->moveRight(); + $result = $player->attack(); - if ($result) { - $bulletsYCoords[] = $result->getBullet()->getPosition()->y; + if (!$result) { + return; } + $bulletsYCoords[] = $result->getBullet()->getPosition()->y; if ($ak->getAmmo() === 0) { - $state->getPlayer(1)->suicide(); + $player->suicide(); } + $player->equipKnife(); + $player->equipPrimaryWeapon(); }); $game->start(); @@ -80,35 +84,42 @@ public function testPistolMovementJumpRecoil(): void { $game = $this->createNoPauseGame(); $player = $game->getPlayer(1); - $player->setPosition($player->getPositionClone()->addZ($player->getBoundingRadius())); + $player->setPosition(new Point(500, 0, 500)); + $player->getSight()->look(180, 0); $player->equipSecondaryWeapon(); $glock = $player->getEquippedItem(); $this->assertInstanceOf(PistolGlock::class, $glock); - $py = $player->getPositionClone()->y + $player->getSightHeight(); + $px = $player->getPositionClone()->x; - $bulletsYCoords = []; - $game->onTick(function (GameState $state) use (&$bulletsYCoords, $glock) { + $bulletsXCoords = []; + $game->onTick(function (GameState $state) use (&$bulletsXCoords, $glock) { $player = $state->getPlayer(1); - $player->moveRight(); - $player->jump(); + if (!$player->isJumping()) { + $player->jump(); + return; + } + $result = $player->attack(); - if ($result) { - $bulletsYCoords[] = $result->getBullet()->getPosition()->y; + if (!$result) { + return; } + $bulletsXCoords[] = $result->getBullet()->getPosition()->x; if ($glock->getAmmo() === 0) { - $state->getPlayer(1)->suicide(); + $player->suicide(); } + $player->equipKnife(); + $player->equipSecondaryWeapon(); }); $game->start(); - $this->assertCount($glock::magazineCapacity, $bulletsYCoords); - $yMatchPlayer = 0; - foreach ($bulletsYCoords as $y) { - if ($y === $py) { - $yMatchPlayer++; + $this->assertCount($glock::magazineCapacity, $bulletsXCoords); + $xMatchPlayer = 0; + foreach ($bulletsXCoords as $x) { + if ($x === $px) { + $xMatchPlayer++; } } - $this->assertLessThan(ceil($glock::magazineCapacity * .2), $yMatchPlayer); + $this->assertLessThan(ceil($glock::magazineCapacity * .2), $xMatchPlayer); } public function testPistolMovementRecoil(): void @@ -125,13 +136,17 @@ public function testPistolMovementRecoil(): void $game->onTick(function (GameState $state) use (&$bulletsYCoords, $glock) { $player = $state->getPlayer(1); $player->moveRight(); + $result = $player->attack(); - if ($result) { - $bulletsYCoords[] = $result->getBullet()->getPosition()->y; + if (!$result) { + return; } + $bulletsYCoords[] = $result->getBullet()->getPosition()->y; if ($glock->getAmmo() === 0) { - $state->getPlayer(1)->suicide(); + $player->suicide(); } + $player->equipKnife(); + $player->equipSecondaryWeapon(); }); $game->start(); @@ -160,13 +175,17 @@ public function testPistolMovementWalkRecoil(): void $player = $state->getPlayer(1); $player->moveRight(); $player->speedWalk(); + $result = $player->attack(); - if ($result) { - $bulletsYCoords[] = $result->getBullet()->getPosition()->y; + if (!$result) { + return; } + $bulletsYCoords[] = $result->getBullet()->getPosition()->y; if ($glock->getAmmo() === 0) { - $state->getPlayer(1)->suicide(); + $player->suicide(); } + $player->equipKnife(); + $player->equipSecondaryWeapon(); }); $game->start(); diff --git a/test/og/Shooting/SimpleShootTest.php b/test/og/Shooting/SimpleShootTest.php index 1298224..0585eb4 100644 --- a/test/og/Shooting/SimpleShootTest.php +++ b/test/og/Shooting/SimpleShootTest.php @@ -2,12 +2,14 @@ namespace Test\Shooting; +use cs\Core\Box; use cs\Core\GameProperty; use cs\Core\GameState; use cs\Core\Player; use cs\Core\Point; use cs\Core\Util; use cs\Enum\BuyMenuItem; +use cs\Enum\Color; use cs\Enum\GameOverReason; use cs\Enum\SoundType; use cs\Event\SoundEvent; @@ -243,4 +245,47 @@ function (Player $p) { $this->assertSame($gun::magazineCapacity - 2, $gun->getAmmo()); } + public function testTeamDamageIsLowerThanOpponent(): void + { + $game = $this->createTestGame(); + $game->addPlayer(new Player(2, Color::ORANGE, true)); + $game->addPlayer(new Player(3, Color::BLUE, false)); + $game->getWorld()->addBox(new Box(new Point(), 1000, 1000, 1000)); + + $this->playPlayer($game, [ + fn(Player $p) => $p->setPosition(new Point(500, 0, 500)), + fn(Player $p) => $p->equipSecondaryWeapon(), + $this->waitNTicks(PistolGlock::equipReadyTimeMs), + fn(Player $p) => $game->getPlayer(2)->setPosition(new Point(500, 0, 300)), + fn(Player $p) => $game->getPlayer(3)->setPosition(new Point(500, 0, 700)), + fn(Player $p) => $p->getSight()->look(0, -10), + fn(Player $p) => $this->assertPlayerHit($p->attack()), + $this->waitNTicks(PistolGlock::fireRateMs), + fn(Player $p) => $p->getSight()->look(180, -10), + fn(Player $p) => $this->assertPlayerHit($p->attack()), + $this->endGame(), + ]); + + $this->assertLessThan(100, $game->getPlayer(3)->getHealth()); + $this->assertLessThan($game->getPlayer(2)->getHealth(), $game->getPlayer(3)->getHealth()); + } + + public function testDamageLowOnRangeMaxDamage(): void + { + $game = $this->createTestGame(); + $game->addPlayer(new Player(2, Color::ORANGE, true)); + + $this->playPlayer($game, [ + fn(Player $p) => $p->setPosition(new Point(500)), + fn(Player $p) => $game->getPlayer(2)->setPosition(new Point(500, 0, PistolGlock::rangeMaxDamage + $p->getBoundingRadius())), + fn(Player $p) => $p->equipSecondaryWeapon(), + $this->waitNTicks(PistolGlock::equipReadyTimeMs), + fn(Player $p) => $p->getSight()->look(0, 0), + fn(Player $p) => $this->assertPlayerHit($p->attack()), + $this->endGame(), + ]); + + $this->assertSame(99, $game->getPlayer(2)->getHealth()); + } + } diff --git a/test/og/Unit/BoxTest.php b/test/og/Unit/BoxTest.php index 3640245..243c6f0 100644 --- a/test/og/Unit/BoxTest.php +++ b/test/og/Unit/BoxTest.php @@ -70,6 +70,55 @@ public function testBox(): void ], $box->toArray()); } + public function testBoxPenetrableParamPropagation(): void + { + $box = new Box(new Point(), 100, 100, 100, Box::SIDE_BACK | Box::SIDE_BOTTOM); + + $plane = $box->getWalls()[0] ?? null; + $this->assertInstanceOf(Wall::class, $plane); + $plane->setHitAntiForce(101, 12, 1); + $this->assertSame(12, $plane->getHitAntiForce($box->getBase())); + $this->assertSame(12, $plane->getHitAntiForce($box->getBase()->clone()->addX(50))); + $this->assertSame(12, $plane->getHitAntiForce($box->getBase()->clone()->addY(50))); + $this->assertSame(101, $plane->getHitAntiForce($box->getBase()->clone()->addPart(50, 50, 50))); + + $plane = $box->getFloors()[0] ?? null; + $this->assertInstanceOf(Floor::class, $plane); + $plane->setHitAntiForce(101, 12, 1); + $this->assertSame(12, $plane->getHitAntiForce($box->getBase())); + $this->assertSame(12, $plane->getHitAntiForce($box->getBase()->clone()->addX(50))); + $this->assertSame(12, $plane->getHitAntiForce($box->getBase()->clone()->addY(50))); + $this->assertSame(101, $plane->getHitAntiForce($box->getBase()->clone()->addPart(50, 50, 50))); + + $this->expectException(GameException::class); + $this->assertSame(12, $plane->getHitAntiForce($box->getBase()->addPart(-1, -1, -1))); + } + + public function testBoxUnPenetrable(): void + { + $box = new Box(new Point(), 100, 100, 100, Box::SIDE_BACK | Box::SIDE_BOTTOM, false); + $plane = $box->getWalls()[0] ?? null; + $this->assertInstanceOf(Wall::class, $plane); + + $this->assertSame($plane::MAX_HIT_ANTI_FORCE, $plane->getHitAntiForce($box->getBase())); + $this->assertSame($plane::MAX_HIT_ANTI_FORCE, $plane->getHitAntiForce($box->getBase()->clone()->addPart(50, 50, 50))); + $this->assertSame($plane::MAX_HIT_ANTI_FORCE, $plane->getHitAntiForce($box->getBase()->clone()->addPart(-50, -50, -50))); + + $plane = $box->getFloors()[0] ?? null; + $this->assertInstanceOf(Floor::class, $plane); + + $this->assertSame($plane::MAX_HIT_ANTI_FORCE, $plane->getHitAntiForce($box->getBase())); + $this->assertSame($plane::MAX_HIT_ANTI_FORCE, $plane->getHitAntiForce($box->getBase()->clone()->addPart(50, 50, 50))); + $this->assertSame($plane::MAX_HIT_ANTI_FORCE, $plane->getHitAntiForce($box->getBase()->clone()->addPart(-50, -50, -50))); + } + + public function testBoxPlaneCounts(): void + { + $box = new Box(new Point(), 100, 100, 100, Box::SIDE_TOP); + $this->assertCount(1, $box->getFloors()); + $this->assertCount(0, $box->getWalls()); + } + public function testBoxWithoutSideThrow(): void { $this->expectException(GameException::class); diff --git a/test/og/Unit/PerformanceTest.php b/test/og/Unit/PerformanceTest.php index ffa2aab..0334ebe 100644 --- a/test/og/Unit/PerformanceTest.php +++ b/test/og/Unit/PerformanceTest.php @@ -28,7 +28,7 @@ class PerformanceTest extends BaseTest public static function setUpBeforeClass(): void { - if (getenv('XDEBUG_MODE') === 'coverage') { + if (getenv('XDEBUG_MODE') === 'coverage' || getenv('INFECTION') === '1') { self::markTestSkipped(); } @@ -128,7 +128,7 @@ public function testPlayersRangeShooting(): void $this->assertLessThanOrEqual($range + 50, $result->getBullet()->getDistanceTraveled()); } $this->assertGreaterThanOrEqual($range, PistolGlock::range); - $this->assertLessThan(21 * self::$timeScale, $took->asMilliseconds()); + $this->assertLessThan(22 * self::$timeScale, $took->asMilliseconds()); } public function testTwoPlayersRangeShootingEachOther(): void diff --git a/test/og/World/CrouchTest.php b/test/og/World/CrouchTest.php index 06cf0fe..addc529 100644 --- a/test/og/World/CrouchTest.php +++ b/test/og/World/CrouchTest.php @@ -64,6 +64,7 @@ function (Player $p) use ($start) { $this->assertSame($start->z - $p->getBoundingRadius() - 1, $p->getPositionClone()->z); }, fn(Player $p) => $p->crouch(), + fn(Player $p) => $this->assertTrue($p->isCrouching()), $this->waitXTicks(Setting::tickCountCrouch()), fn(Player $p) => $p->moveForward(), fn(Player $p) => $p->moveForward(), @@ -87,6 +88,7 @@ function (Player $p) use ($ceiling) { $this->playPlayer($game, $commands); $this->assertSame($ceiling->getBase()->z + $ceiling->depthZ + $player->getBoundingRadius() + 1, $player->getPositionClone()->z); $this->assertSame(Setting::playerHeadHeightStand(), $player->getHeadHeight()); + $this->assertFalse($game->getPlayer(1)->isCrouching()); } diff --git a/test/og/World/NavigationMeshTest.php b/test/og/World/NavigationMeshTest.php index 1fc7ba3..bc0f9b5 100644 --- a/test/og/World/NavigationMeshTest.php +++ b/test/og/World/NavigationMeshTest.php @@ -92,6 +92,18 @@ public function testBoundary(): void $this->assertLessThan($closestCandidate->x, $validPoint->x); $this->assertNotNull($path->getGraph()->getNodeById($validPoint->hash())); $this->assertSame('2,0,5', $validPoint->hash()); + + $orig = $candidate->clone(); + $candidate->addX(-1); + $validPoint = $path->findTile($candidate, 1); + $this->assertLessThan($closestCandidate->x, $validPoint->x); + $this->assertNotNull($path->getGraph()->getNodeById($validPoint->hash())); + $this->assertSame('2,0,5', $validPoint->hash()); + + $this->assertNotSame('2,0,5', $candidate->hash()); + $path->convertToNavMeshNode($candidate); + $this->assertSame('2,0,5', $candidate->hash()); + $this->assertPositionNotSame($orig, $candidate); } public function testOneWayDirection(): void diff --git a/test/og/World/WorldTest.php b/test/og/World/WorldTest.php index ae14121..fbc4de2 100644 --- a/test/og/World/WorldTest.php +++ b/test/og/World/WorldTest.php @@ -7,7 +7,6 @@ use cs\Core\GameState; use cs\Core\Player; use cs\Core\Point; -use cs\Core\Point2D; use cs\Core\Ramp; use cs\Core\Setting; use cs\Core\Wall; @@ -44,6 +43,7 @@ public function testCanBeSeen(): void { $game = $this->createGame(); $player = $game->getPlayer(1); + $player->getSight()->look(0, 0); $this->assertFalse($game->getWorld()->canBeSeen($player, new Point(999, 999, 999), 10, 200)); $this->assertFalse($game->getWorld()->canBeSeen( $player, $player->getPositionClone()->addY($player->getSightHeight())->addZ(-20), 10, 999) @@ -75,6 +75,9 @@ public function testCanBeSeen(): void $this->assertFalse($game->getWorld()->canBeSeen( $player, $player->getPositionClone()->addY($player->getSightHeight())->addZ(100), 10, 100, true) ); + + $player->getSight()->look(0, -80); + $this->assertFalse($game->getWorld()->canBeSeen($player, $player->getPositionClone()->setY(-1), 10, 999)); } public function testStairCaseUp(): void