From d199818b5d35ed4bfbf1f656928d0adeeaf5ddaa Mon Sep 17 00:00:00 2001
From: Ryan Cooper <198979606+coopryan@users.noreply.github.com>
Date: Thu, 28 Aug 2025 13:09:23 +0200
Subject: [PATCH 1/3] Composer update deps
---
composer.lock | 690 ++++++++++++++++++++++++++++++++++++--------------
1 file changed, 496 insertions(+), 194 deletions(-)
diff --git a/composer.lock b/composer.lock
index 7335e25..f5d6a9c 100644
--- a/composer.lock
+++ b/composer.lock
@@ -409,16 +409,16 @@
},
{
"name": "fidry/cpu-core-counter",
- "version": "1.2.0",
+ "version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/theofidry/cpu-core-counter.git",
- "reference": "8520451a140d3f46ac33042715115e290cf5785f"
+ "reference": "db9508f7b1474469d9d3c53b86f817e344732678"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f",
- "reference": "8520451a140d3f46ac33042715115e290cf5785f",
+ "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678",
+ "reference": "db9508f7b1474469d9d3c53b86f817e344732678",
"shasum": ""
},
"require": {
@@ -428,10 +428,10 @@
"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",
+ "phpstan/phpstan": "^2.0",
+ "phpstan/phpstan-deprecation-rules": "^2.0.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^8.5.31 || ^9.5.26",
"webmozarts/strict-phpunit": "^7.5"
},
@@ -458,7 +458,7 @@
],
"support": {
"issues": "https://github.com/theofidry/cpu-core-counter/issues",
- "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0"
+ "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0"
},
"funding": [
{
@@ -466,7 +466,7 @@
"type": "github"
}
],
- "time": "2024-08-06T10:04:20+00:00"
+ "time": "2025-08-14T07:29:31+00:00"
},
{
"name": "infection/abstract-testframework-adapter",
@@ -647,38 +647,40 @@
},
{
"name": "infection/infection",
- "version": "0.29.14",
+ "version": "0.31.2",
"source": {
"type": "git",
"url": "https://github.com/infection/infection.git",
- "reference": "feea2a48a8aeedd3a4d2105167b41a46f0e568a3"
+ "reference": "242785d48ac2dc00a1d3a77b2048b289dc82cbc9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/infection/infection/zipball/feea2a48a8aeedd3a4d2105167b41a46f0e568a3",
- "reference": "feea2a48a8aeedd3a4d2105167b41a46f0e568a3",
+ "url": "https://api.github.com/repos/infection/infection/zipball/242785d48ac2dc00a1d3a77b2048b289dc82cbc9",
+ "reference": "242785d48ac2dc00a1d3a77b2048b289dc82cbc9",
"shasum": ""
},
"require": {
- "colinodell/json5": "^2.2 || ^3.0",
+ "colinodell/json5": "^3.0",
"composer-runtime-api": "^2.0",
- "composer/xdebug-handler": "^2.0 || ^3.0",
+ "composer/xdebug-handler": "^3.0",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
- "fidry/cpu-core-counter": "^0.4.0 || ^0.5.0 || ^1.0",
+ "fidry/cpu-core-counter": "^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.3 || ^6.0",
+ "justinrainbow/json-schema": "^6.0",
"nikic/php-parser": "^5.3",
"ondram/ci-detector": "^4.1.0",
"php": "^8.2",
- "sanmai/later": "^0.1.1",
- "sanmai/pipeline": "^5.1 || ^6",
- "sebastian/diff": "^3.0.2 || ^4.0 || ^5.0 || ^6.0 || ^7.0",
+ "sanmai/di-container": "^0.1.4",
+ "sanmai/duoclock": "^0.1.0",
+ "sanmai/later": "^0.1.7",
+ "sanmai/pipeline": "^7.0",
+ "sebastian/diff": "^4.0 || ^5.0 || ^6.0 || ^7.0",
"symfony/console": "^6.4 || ^7.0",
"symfony/filesystem": "^6.4 || ^7.0",
"symfony/finder": "^6.4 || ^7.0",
@@ -688,8 +690,7 @@
},
"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"
+ "dg/bypass-finals": "<1.4.1"
},
"require-dev": {
"ext-simplexml": "*",
@@ -699,8 +700,10 @@
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpstan/phpstan-webmozart-assert": "^2.0",
- "phpunit/phpunit": "^11.5",
+ "phpunit/phpunit": "^11.5.27",
"rector/rector": "^2.0",
+ "shipmonk/dead-code-detector": "^0.12.0",
+ "shipmonk/name-collision-detector": "^2.1",
"sidz/phpstan-rules": "^0.5.1",
"symfony/yaml": "^6.4 || ^7.0",
"thecodingmachine/phpstan-safe-rule": "^1.4"
@@ -759,7 +762,7 @@
],
"support": {
"issues": "https://github.com/infection/infection/issues",
- "source": "https://github.com/infection/infection/tree/0.29.14"
+ "source": "https://github.com/infection/infection/tree/0.31.2"
},
"funding": [
{
@@ -771,20 +774,20 @@
"type": "open_collective"
}
],
- "time": "2025-03-02T18:49:12+00:00"
+ "time": "2025-08-21T06:43:51+00:00"
},
{
"name": "infection/mutator",
- "version": "0.4.0",
+ "version": "0.4.1",
"source": {
"type": "git",
"url": "https://github.com/infection/mutator.git",
- "reference": "51d6d01a2357102030aee9d603063c4bad86b144"
+ "reference": "3c976d721b02b32f851ee4e15d553ef1e9186d1d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/infection/mutator/zipball/51d6d01a2357102030aee9d603063c4bad86b144",
- "reference": "51d6d01a2357102030aee9d603063c4bad86b144",
+ "url": "https://api.github.com/repos/infection/mutator/zipball/3c976d721b02b32f851ee4e15d553ef1e9186d1d",
+ "reference": "3c976d721b02b32f851ee4e15d553ef1e9186d1d",
"shasum": ""
},
"require": {
@@ -812,7 +815,7 @@
"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"
+ "source": "https://github.com/infection/mutator/tree/0.4.1"
},
"funding": [
{
@@ -824,20 +827,20 @@
"type": "open_collective"
}
],
- "time": "2024-05-14T22:39:59+00:00"
+ "time": "2025-04-29T08:19:52+00:00"
},
{
"name": "justinrainbow/json-schema",
- "version": "6.3.1",
+ "version": "6.4.2",
"source": {
"type": "git",
"url": "https://github.com/jsonrainbow/json-schema.git",
- "reference": "c9f00dec766a67bf82c277b71d71d254357db92c"
+ "reference": "ce1fd2d47799bb60668643bc6220f6278a4c1d02"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/c9f00dec766a67bf82c277b71d71d254357db92c",
- "reference": "c9f00dec766a67bf82c277b71d71d254357db92c",
+ "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/ce1fd2d47799bb60668643bc6220f6278a4c1d02",
+ "reference": "ce1fd2d47799bb60668643bc6220f6278a4c1d02",
"shasum": ""
},
"require": {
@@ -897,9 +900,9 @@
],
"support": {
"issues": "https://github.com/jsonrainbow/json-schema/issues",
- "source": "https://github.com/jsonrainbow/json-schema/tree/6.3.1"
+ "source": "https://github.com/jsonrainbow/json-schema/tree/6.4.2"
},
- "time": "2025-03-18T19:03:56+00:00"
+ "time": "2025-06-03T18:27:04+00:00"
},
{
"name": "marc-mabe/php-enum",
@@ -976,16 +979,16 @@
},
{
"name": "myclabs/deep-copy",
- "version": "1.13.0",
+ "version": "1.13.4",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "024473a478be9df5fdaca2c793f2232fe788e414"
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414",
- "reference": "024473a478be9df5fdaca2c793f2232fe788e414",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a",
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a",
"shasum": ""
},
"require": {
@@ -1024,7 +1027,7 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
- "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0"
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4"
},
"funding": [
{
@@ -1032,20 +1035,20 @@
"type": "tidelift"
}
],
- "time": "2025-02-12T12:17:51+00:00"
+ "time": "2025-08-01T08:46:24+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v5.4.0",
+ "version": "v5.6.1",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "447a020a1f875a434d62f2a401f53b82a396e494"
+ "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494",
- "reference": "447a020a1f875a434d62f2a401f53b82a396e494",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
+ "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
"shasum": ""
},
"require": {
@@ -1064,7 +1067,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.0-dev"
+ "dev-master": "5.x-dev"
}
},
"autoload": {
@@ -1088,9 +1091,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1"
},
- "time": "2024-12-30T11:07:19+00:00"
+ "time": "2025-08-13T20:13:15+00:00"
},
{
"name": "ondram/ci-detector",
@@ -1290,16 +1293,16 @@
},
{
"name": "phpstan/phpstan",
- "version": "2.1.11",
+ "version": "2.1.22",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "8ca5f79a8f63c49b2359065832a654e1ec70ac30"
+ "reference": "41600c8379eb5aee63e9413fe9e97273e25d57e4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/8ca5f79a8f63c49b2359065832a654e1ec70ac30",
- "reference": "8ca5f79a8f63c49b2359065832a654e1ec70ac30",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/41600c8379eb5aee63e9413fe9e97273e25d57e4",
+ "reference": "41600c8379eb5aee63e9413fe9e97273e25d57e4",
"shasum": ""
},
"require": {
@@ -1344,25 +1347,25 @@
"type": "github"
}
],
- "time": "2025-03-24T13:45:00+00:00"
+ "time": "2025-08-04T19:17:37+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
- "version": "2.0.6",
+ "version": "2.0.7",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
- "reference": "6b92469f8a7995e626da3aa487099617b8dfa260"
+ "reference": "9a9b161baee88a5f5c58d816943cff354ff233dc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/6b92469f8a7995e626da3aa487099617b8dfa260",
- "reference": "6b92469f8a7995e626da3aa487099617b8dfa260",
+ "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/9a9b161baee88a5f5c58d816943cff354ff233dc",
+ "reference": "9a9b161baee88a5f5c58d816943cff354ff233dc",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0",
- "phpstan/phpstan": "^2.0.4"
+ "phpstan/phpstan": "^2.1.18"
},
"conflict": {
"phpunit/phpunit": "<7.0"
@@ -1395,22 +1398,22 @@
"description": "PHPUnit extensions and rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
- "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.6"
+ "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.7"
},
- "time": "2025-03-26T12:47:06+00:00"
+ "time": "2025-07-13T11:31:46+00:00"
},
{
"name": "phpunit/php-code-coverage",
- "version": "12.1.0",
+ "version": "12.3.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "d331a5ced3d9a2b917baa9841b2211e72f9e780d"
+ "reference": "733025d94635a001f67db71a2ed1bab4e7e4a9dc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d331a5ced3d9a2b917baa9841b2211e72f9e780d",
- "reference": "d331a5ced3d9a2b917baa9841b2211e72f9e780d",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/733025d94635a001f67db71a2ed1bab4e7e4a9dc",
+ "reference": "733025d94635a001f67db71a2ed1bab4e7e4a9dc",
"shasum": ""
},
"require": {
@@ -1428,7 +1431,7 @@
"theseer/tokenizer": "^1.2.3"
},
"require-dev": {
- "phpunit/phpunit": "^12.0"
+ "phpunit/phpunit": "^12.1"
},
"suggest": {
"ext-pcov": "PHP extension that provides line coverage",
@@ -1437,7 +1440,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "12.1.x-dev"
+ "dev-main": "12.3.x-dev"
}
},
"autoload": {
@@ -1466,15 +1469,27 @@
"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/12.1.0"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.3.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage",
+ "type": "tidelift"
}
],
- "time": "2025-03-17T13:56:07+00:00"
+ "time": "2025-08-27T14:43:48+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -1723,16 +1738,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "12.0.10",
+ "version": "12.3.7",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "6075843014de23bcd6992842d69ca99d25d6a433"
+ "reference": "b8fa997c49682979ad6bfaa0d7fb25f54954965e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6075843014de23bcd6992842d69ca99d25d6a433",
- "reference": "6075843014de23bcd6992842d69ca99d25d6a433",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b8fa997c49682979ad6bfaa0d7fb25f54954965e",
+ "reference": "b8fa997c49682979ad6bfaa0d7fb25f54954965e",
"shasum": ""
},
"require": {
@@ -1742,23 +1757,23 @@
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
- "myclabs/deep-copy": "^1.13.0",
+ "myclabs/deep-copy": "^1.13.4",
"phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1",
"php": ">=8.3",
- "phpunit/php-code-coverage": "^12.1.0",
+ "phpunit/php-code-coverage": "^12.3.3",
"phpunit/php-file-iterator": "^6.0.0",
"phpunit/php-invoker": "^6.0.0",
"phpunit/php-text-template": "^5.0.0",
"phpunit/php-timer": "^8.0.0",
"sebastian/cli-parser": "^4.0.0",
- "sebastian/comparator": "^7.0.1",
+ "sebastian/comparator": "^7.1.3",
"sebastian/diff": "^7.0.0",
- "sebastian/environment": "^8.0.0",
+ "sebastian/environment": "^8.0.3",
"sebastian/exporter": "^7.0.0",
"sebastian/global-state": "^8.0.0",
"sebastian/object-enumerator": "^7.0.0",
- "sebastian/type": "^6.0.2",
+ "sebastian/type": "^6.0.3",
"sebastian/version": "^6.0.0",
"staabm/side-effects-detector": "^1.0.5"
},
@@ -1768,7 +1783,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "12.0-dev"
+ "dev-main": "12.3-dev"
}
},
"autoload": {
@@ -1800,7 +1815,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/12.0.10"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.7"
},
"funding": [
{
@@ -1811,12 +1826,68 @@
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
"type": "tidelift"
}
],
- "time": "2025-03-23T16:03:59+00:00"
+ "time": "2025-08-28T05:15:46+00:00"
+ },
+ {
+ "name": "psr/clock",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/clock.git",
+ "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+ "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Clock\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for reading the clock.",
+ "homepage": "https://github.com/php-fig/clock",
+ "keywords": [
+ "clock",
+ "now",
+ "psr",
+ "psr-20",
+ "time"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/clock/issues",
+ "source": "https://github.com/php-fig/clock/tree/1.0.0"
+ },
+ "time": "2022-11-25T14:36:26+00:00"
},
{
"name": "psr/container",
@@ -1871,22 +1942,161 @@
},
"time": "2021-11-05T16:47:00+00:00"
},
+ {
+ "name": "sanmai/di-container",
+ "version": "0.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sanmai/di-container.git",
+ "reference": "355534ad7970fc7dab4211ecaf2da5c546855ee8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sanmai/di-container/zipball/355534ad7970fc7dab4211ecaf2da5c546855ee8",
+ "reference": "355534ad7970fc7dab4211ecaf2da5c546855ee8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "psr/container": "^1.1.2 || ^2.0",
+ "sanmai/pipeline": "^6.17 || ^7.0"
+ },
+ "require-dev": {
+ "ergebnis/composer-normalize": "^2.8",
+ "friendsofphp/php-cs-fixer": "^3.17",
+ "infection/infection": ">=0.29",
+ "php-coveralls/php-coveralls": "^2.4.1",
+ "phpstan/extension-installer": "^1.4",
+ "phpunit/phpunit": "^11.5.25",
+ "sanmai/phpstan-rules": "^0.3.10"
+ },
+ "type": "library",
+ "extra": {
+ "preferred-install": "dist"
+ },
+ "autoload": {
+ "psr-4": {
+ "DIContainer\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Alexey Kopytko",
+ "email": "alexey@kopytko.com",
+ "homepage": "https://github.com/sanmai"
+ },
+ {
+ "name": "Maks Rafalko",
+ "homepage": "https://twitter.com/maks_rafalko"
+ },
+ {
+ "name": "Théo FIDRY",
+ "homepage": "https://twitter.com/tfidry"
+ }
+ ],
+ "description": "dependency injection container with automatic constructor dependency resolution",
+ "keywords": [
+ "Autowiring",
+ "constructor di",
+ "di container",
+ "psr 11"
+ ],
+ "support": {
+ "issues": "https://github.com/sanmai/di-container/issues",
+ "source": "https://github.com/sanmai/di-container/tree/0.1.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sanmai",
+ "type": "github"
+ }
+ ],
+ "time": "2025-08-04T09:43:58+00:00"
+ },
+ {
+ "name": "sanmai/duoclock",
+ "version": "0.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sanmai/DuoClock.git",
+ "reference": "30aa40092396dc96b68c8e8d49162619574477e2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sanmai/DuoClock/zipball/30aa40092396dc96b68c8e8d49162619574477e2",
+ "reference": "30aa40092396dc96b68c8e8d49162619574477e2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "psr/clock": "^1.0"
+ },
+ "provide": {
+ "psr/clock-implementation": "1.0"
+ },
+ "require-dev": {
+ "ergebnis/composer-normalize": "^2.8",
+ "friendsofphp/php-cs-fixer": "^3.17",
+ "infection/infection": ">=0.29",
+ "php-coveralls/php-coveralls": "^2.4.1",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2",
+ "phpunit/phpunit": "^11.5.25",
+ "sanmai/phpstan-rules": "^0.3.1",
+ "vimeo/psalm": "^6.12"
+ },
+ "type": "library",
+ "extra": {
+ "preferred-install": "dist"
+ },
+ "autoload": {
+ "psr-4": {
+ "DuoClock\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Alexey Kopytko",
+ "email": "alexey@kopytko.com"
+ }
+ ],
+ "description": "PHP time mocking for tests - PSR-20 clock with mockable sleep(), time(), and TimeSpy for PHPUnit testing",
+ "support": {
+ "issues": "https://github.com/sanmai/DuoClock/issues",
+ "source": "https://github.com/sanmai/DuoClock/tree/0.1.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sanmai",
+ "type": "github"
+ }
+ ],
+ "time": "2025-07-28T02:17:28+00:00"
+ },
{
"name": "sanmai/later",
- "version": "0.1.4",
+ "version": "0.1.7",
"source": {
"type": "git",
"url": "https://github.com/sanmai/later.git",
- "reference": "e24c4304a4b1349c2a83151a692cec0c10579f60"
+ "reference": "72a82d783864bca90412d8a26c1878f8981fee97"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sanmai/later/zipball/e24c4304a4b1349c2a83151a692cec0c10579f60",
- "reference": "e24c4304a4b1349c2a83151a692cec0c10579f60",
+ "url": "https://api.github.com/repos/sanmai/later/zipball/72a82d783864bca90412d8a26c1878f8981fee97",
+ "reference": "72a82d783864bca90412d8a26c1878f8981fee97",
"shasum": ""
},
"require": {
- "php": ">=7.4"
+ "php": ">=8.2"
},
"require-dev": {
"ergebnis/composer-normalize": "^2.8",
@@ -1925,7 +2135,7 @@
"description": "Later: deferred wrapper object",
"support": {
"issues": "https://github.com/sanmai/later/issues",
- "source": "https://github.com/sanmai/later/tree/0.1.4"
+ "source": "https://github.com/sanmai/later/tree/0.1.7"
},
"funding": [
{
@@ -1933,34 +2143,37 @@
"type": "github"
}
],
- "time": "2023-10-24T00:25:28+00:00"
+ "time": "2025-05-11T01:48:00+00:00"
},
{
"name": "sanmai/pipeline",
- "version": "6.12",
+ "version": "7.1",
"source": {
"type": "git",
"url": "https://github.com/sanmai/pipeline.git",
- "reference": "ad7dbc3f773eeafb90d5459522fbd8f188532e25"
+ "reference": "d01565ef9f5cd7d1019c5f8bee09497067511f36"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sanmai/pipeline/zipball/ad7dbc3f773eeafb90d5459522fbd8f188532e25",
- "reference": "ad7dbc3f773eeafb90d5459522fbd8f188532e25",
+ "url": "https://api.github.com/repos/sanmai/pipeline/zipball/d01565ef9f5cd7d1019c5f8bee09497067511f36",
+ "reference": "d01565ef9f5cd7d1019c5f8bee09497067511f36",
"shasum": ""
},
"require": {
- "php": "^7.4 || ^8.0"
+ "php": ">=8.2"
},
"require-dev": {
"ergebnis/composer-normalize": "^2.8",
+ "esi/phpunit-coverage-check": ">2",
"friendsofphp/php-cs-fixer": "^3.17",
- "infection/infection": ">=0.10.5",
+ "infection/infection": ">=0.30.3",
"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",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2",
+ "phpunit/phpunit": ">=9.4 <12",
+ "sanmai/phpstan-rules": "^0.3.0",
+ "sanmai/phpunit-double-colon-syntax": "^0.1.1",
"vimeo/psalm": ">=2"
},
"type": "library",
@@ -1990,7 +2203,7 @@
"description": "General-purpose collections pipeline",
"support": {
"issues": "https://github.com/sanmai/pipeline/issues",
- "source": "https://github.com/sanmai/pipeline/tree/6.12"
+ "source": "https://github.com/sanmai/pipeline/tree/7.1"
},
"funding": [
{
@@ -1998,7 +2211,7 @@
"type": "github"
}
],
- "time": "2024-10-17T02:22:57+00:00"
+ "time": "2025-07-27T07:02:29+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -2059,16 +2272,16 @@
},
{
"name": "sebastian/comparator",
- "version": "7.0.1",
+ "version": "7.1.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "b478f34614f934e0291598d0c08cbaba9644bee5"
+ "reference": "dc904b4bb3ab070865fa4068cd84f3da8b945148"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/b478f34614f934e0291598d0c08cbaba9644bee5",
- "reference": "b478f34614f934e0291598d0c08cbaba9644bee5",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/dc904b4bb3ab070865fa4068cd84f3da8b945148",
+ "reference": "dc904b4bb3ab070865fa4068cd84f3da8b945148",
"shasum": ""
},
"require": {
@@ -2079,7 +2292,7 @@
"sebastian/exporter": "^7.0"
},
"require-dev": {
- "phpunit/phpunit": "^12.0"
+ "phpunit/phpunit": "^12.2"
},
"suggest": {
"ext-bcmath": "For comparing BcMath\\Number objects"
@@ -2087,7 +2300,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "7.0-dev"
+ "dev-main": "7.1-dev"
}
},
"autoload": {
@@ -2127,15 +2340,27 @@
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
"security": "https://github.com/sebastianbergmann/comparator/security/policy",
- "source": "https://github.com/sebastianbergmann/comparator/tree/7.0.1"
+ "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator",
+ "type": "tidelift"
}
],
- "time": "2025-03-07T07:00:32+00:00"
+ "time": "2025-08-20T11:27:00+00:00"
},
{
"name": "sebastian/complexity",
@@ -2264,16 +2489,16 @@
},
{
"name": "sebastian/environment",
- "version": "8.0.0",
+ "version": "8.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "8afe311eca49171bf95405cc0078be9a3821f9f2"
+ "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8afe311eca49171bf95405cc0078be9a3821f9f2",
- "reference": "8afe311eca49171bf95405cc0078be9a3821f9f2",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/24a711b5c916efc6d6e62aa65aa2ec98fef77f68",
+ "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68",
"shasum": ""
},
"require": {
@@ -2316,15 +2541,27 @@
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
"security": "https://github.com/sebastianbergmann/environment/security/policy",
- "source": "https://github.com/sebastianbergmann/environment/tree/8.0.0"
+ "source": "https://github.com/sebastianbergmann/environment/tree/8.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/environment",
+ "type": "tidelift"
}
],
- "time": "2025-02-07T04:56:08+00:00"
+ "time": "2025-08-12T14:11:56+00:00"
},
{
"name": "sebastian/exporter",
@@ -2406,16 +2643,16 @@
},
{
"name": "sebastian/global-state",
- "version": "8.0.0",
+ "version": "8.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "570a2aeb26d40f057af686d63c4e99b075fb6cbc"
+ "reference": "912dd568677a6e13c67c08321710ad6ac81e6dca"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/570a2aeb26d40f057af686d63c4e99b075fb6cbc",
- "reference": "570a2aeb26d40f057af686d63c4e99b075fb6cbc",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/912dd568677a6e13c67c08321710ad6ac81e6dca",
+ "reference": "912dd568677a6e13c67c08321710ad6ac81e6dca",
"shasum": ""
},
"require": {
@@ -2456,15 +2693,27 @@
"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/8.0.0"
+ "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state",
+ "type": "tidelift"
}
],
- "time": "2025-02-07T04:56:59+00:00"
+ "time": "2025-08-28T09:13:48+00:00"
},
{
"name": "sebastian/lines-of-code",
@@ -2640,16 +2889,16 @@
},
{
"name": "sebastian/recursion-context",
- "version": "7.0.0",
+ "version": "7.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
- "reference": "c405ae3a63e01b32eb71577f8ec1604e39858a7c"
+ "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/c405ae3a63e01b32eb71577f8ec1604e39858a7c",
- "reference": "c405ae3a63e01b32eb71577f8ec1604e39858a7c",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/0b01998a7d5b1f122911a66bebcb8d46f0c82d8c",
+ "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c",
"shasum": ""
},
"require": {
@@ -2692,28 +2941,40 @@
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
"security": "https://github.com/sebastianbergmann/recursion-context/security/policy",
- "source": "https://github.com/sebastianbergmann/recursion-context/tree/7.0.0"
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/7.0.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context",
+ "type": "tidelift"
}
],
- "time": "2025-02-07T05:00:01+00:00"
+ "time": "2025-08-13T04:44:59+00:00"
},
{
"name": "sebastian/type",
- "version": "6.0.2",
+ "version": "6.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
- "reference": "1d7cd6e514384c36d7a390347f57c385d4be6069"
+ "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/1d7cd6e514384c36d7a390347f57c385d4be6069",
- "reference": "1d7cd6e514384c36d7a390347f57c385d4be6069",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/e549163b9760b8f71f191651d22acf32d56d6d4d",
+ "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d",
"shasum": ""
},
"require": {
@@ -2749,15 +3010,27 @@
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
"security": "https://github.com/sebastianbergmann/type/security/policy",
- "source": "https://github.com/sebastianbergmann/type/tree/6.0.2"
+ "source": "https://github.com/sebastianbergmann/type/tree/6.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/type",
+ "type": "tidelift"
}
],
- "time": "2025-03-18T13:37:31+00:00"
+ "time": "2025-08-09T06:57:12+00:00"
},
{
"name": "sebastian/version",
@@ -2867,23 +3140,24 @@
},
{
"name": "symfony/console",
- "version": "v7.2.5",
+ "version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "e51498ea18570c062e7df29d05a7003585b19b88"
+ "reference": "5f360ebc65c55265a74d23d7fe27f957870158a1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88",
- "reference": "e51498ea18570c062e7df29d05a7003585b19b88",
+ "url": "https://api.github.com/repos/symfony/console/zipball/5f360ebc65c55265a74d23d7fe27f957870158a1",
+ "reference": "5f360ebc65c55265a74d23d7fe27f957870158a1",
"shasum": ""
},
"require": {
"php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/string": "^6.4|^7.0"
+ "symfony/string": "^7.2"
},
"conflict": {
"symfony/dependency-injection": "<6.4",
@@ -2940,7 +3214,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v7.2.5"
+ "source": "https://github.com/symfony/console/tree/v7.3.2"
},
"funding": [
{
@@ -2951,25 +3225,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2025-03-12T08:11:12+00:00"
+ "time": "2025-07-30T17:13:41+00:00"
},
{
"name": "symfony/deprecation-contracts",
- "version": "v3.5.1",
+ "version": "v3.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
- "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
+ "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
- "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
+ "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
"shasum": ""
},
"require": {
@@ -2982,7 +3260,7 @@
"name": "symfony/contracts"
},
"branch-alias": {
- "dev-main": "3.5-dev"
+ "dev-main": "3.6-dev"
}
},
"autoload": {
@@ -3007,7 +3285,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
},
"funding": [
{
@@ -3023,20 +3301,20 @@
"type": "tidelift"
}
],
- "time": "2024-09-25T14:20:29+00:00"
+ "time": "2024-09-25T14:21:43+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v7.2.0",
+ "version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb"
+ "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
- "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd",
+ "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd",
"shasum": ""
},
"require": {
@@ -3073,7 +3351,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v7.2.0"
+ "source": "https://github.com/symfony/filesystem/tree/v7.3.2"
},
"funding": [
{
@@ -3084,25 +3362,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-10-25T15:15:23+00:00"
+ "time": "2025-07-07T08:17:47+00:00"
},
{
"name": "symfony/finder",
- "version": "v7.2.2",
+ "version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "87a71856f2f56e4100373e92529eed3171695cfb"
+ "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb",
- "reference": "87a71856f2f56e4100373e92529eed3171695cfb",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe",
+ "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe",
"shasum": ""
},
"require": {
@@ -3137,7 +3419,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v7.2.2"
+ "source": "https://github.com/symfony/finder/tree/v7.3.2"
},
"funding": [
{
@@ -3148,16 +3430,20 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-12-30T19:00:17+00:00"
+ "time": "2025-07-15T13:41:35+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.31.0",
+ "version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@@ -3216,7 +3502,7 @@
"portable"
],
"support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
},
"funding": [
{
@@ -3227,6 +3513,10 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
@@ -3236,16 +3526,16 @@
},
{
"name": "symfony/polyfill-intl-grapheme",
- "version": "v1.31.0",
+ "version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
- "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe"
+ "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe",
- "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70",
+ "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70",
"shasum": ""
},
"require": {
@@ -3294,7 +3584,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0"
},
"funding": [
{
@@ -3305,16 +3595,20 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-09-09T11:45:10+00:00"
+ "time": "2025-06-27T09:58:17+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
- "version": "v1.31.0",
+ "version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
@@ -3375,7 +3669,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0"
},
"funding": [
{
@@ -3386,6 +3680,10 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
@@ -3475,16 +3773,16 @@
},
{
"name": "symfony/process",
- "version": "v7.2.5",
+ "version": "v7.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "87b7c93e57df9d8e39a093d32587702380ff045d"
+ "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d",
- "reference": "87b7c93e57df9d8e39a093d32587702380ff045d",
+ "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af",
+ "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af",
"shasum": ""
},
"require": {
@@ -3516,7 +3814,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v7.2.5"
+ "source": "https://github.com/symfony/process/tree/v7.3.0"
},
"funding": [
{
@@ -3532,20 +3830,20 @@
"type": "tidelift"
}
],
- "time": "2025-03-13T12:21:46+00:00"
+ "time": "2025-04-17T09:11:12+00:00"
},
{
"name": "symfony/service-contracts",
- "version": "v3.5.1",
+ "version": "v3.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0"
+ "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0",
- "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
+ "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
"shasum": ""
},
"require": {
@@ -3563,7 +3861,7 @@
"name": "symfony/contracts"
},
"branch-alias": {
- "dev-main": "3.5-dev"
+ "dev-main": "3.6-dev"
}
},
"autoload": {
@@ -3599,7 +3897,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v3.5.1"
+ "source": "https://github.com/symfony/service-contracts/tree/v3.6.0"
},
"funding": [
{
@@ -3615,20 +3913,20 @@
"type": "tidelift"
}
],
- "time": "2024-09-25T14:20:29+00:00"
+ "time": "2025-04-25T09:37:31+00:00"
},
{
"name": "symfony/string",
- "version": "v7.2.0",
+ "version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82"
+ "reference": "42f505aff654e62ac7ac2ce21033818297ca89ca"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82",
- "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82",
+ "url": "https://api.github.com/repos/symfony/string/zipball/42f505aff654e62ac7ac2ce21033818297ca89ca",
+ "reference": "42f505aff654e62ac7ac2ce21033818297ca89ca",
"shasum": ""
},
"require": {
@@ -3686,7 +3984,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v7.2.0"
+ "source": "https://github.com/symfony/string/tree/v7.3.2"
},
"funding": [
{
@@ -3697,12 +3995,16 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-11-13T13:31:26+00:00"
+ "time": "2025-07-10T08:47:49+00:00"
},
{
"name": "textalk/websocket",
@@ -3755,16 +4057,16 @@
},
{
"name": "thecodingmachine/safe",
- "version": "v3.0.2",
+ "version": "v3.3.0",
"source": {
"type": "git",
"url": "https://github.com/thecodingmachine/safe.git",
- "reference": "22ffad3248982a784f9870a37aeb2e522bd19645"
+ "reference": "2cdd579eeaa2e78e51c7509b50cc9fb89a956236"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/22ffad3248982a784f9870a37aeb2e522bd19645",
- "reference": "22ffad3248982a784f9870a37aeb2e522bd19645",
+ "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/2cdd579eeaa2e78e51c7509b50cc9fb89a956236",
+ "reference": "2cdd579eeaa2e78e51c7509b50cc9fb89a956236",
"shasum": ""
},
"require": {
@@ -3874,7 +4176,7 @@
"description": "PHP core functions that throw exceptions instead of returning FALSE on error",
"support": {
"issues": "https://github.com/thecodingmachine/safe/issues",
- "source": "https://github.com/thecodingmachine/safe/tree/v3.0.2"
+ "source": "https://github.com/thecodingmachine/safe/tree/v3.3.0"
},
"funding": [
{
@@ -3890,7 +4192,7 @@
"type": "github"
}
],
- "time": "2025-02-19T19:23:00+00:00"
+ "time": "2025-05-14T06:15:44+00:00"
},
{
"name": "theseer/tokenizer",
From 6af8470b0c6df7dd3d3a4923fe58bbacc024e678 Mon Sep 17 00:00:00 2001
From: Ryan Cooper <198979606+coopryan@users.noreply.github.com>
Date: Thu, 28 Aug 2025 13:10:40 +0200
Subject: [PATCH 2/3] qa: mutation testing with phsptan
---
.github/workflows/test.yml | 6 ++--
cli/server.php | 3 +-
composer.json | 8 +++---
infection.json5 | 18 +++++-------
phpunit.xml | 1 -
server/src/Core/BuyMenu.php | 2 +-
server/src/Core/HitBox.php | 2 ++
server/src/Core/PathFinder.php | 10 +++----
server/src/Core/PlayerStat.php | 5 ++++
server/src/Core/Score.php | 4 +--
server/src/Equipment/Grenade.php | 2 ++
server/src/Equipment/HighExplosive.php | 2 +-
server/src/Equipment/Incendiary.php | 1 +
server/src/Equipment/Kevlar.php | 7 +++--
server/src/Event/GrillEvent.php | 4 +--
server/src/Event/PauseStartEvent.php | 2 +-
server/src/Event/ThrowEvent.php | 1 +
server/src/Net/ClueSocket.php | 2 +-
server/src/Net/NetConnector.php | 2 +-
server/src/Net/TestConnector.php | 2 +-
test/og/Game/RoundTest.php | 39 ++++++++++++++++++++------
test/og/Inventory/InventoryTest.php | 17 +++++++++++
test/og/Shooting/BombTest.php | 3 ++
test/og/Shooting/PlayerKillTest.php | 4 ++-
test/og/Shooting/ShootTest.php | 1 +
test/og/Unit/CollisionTest.php | 9 ++++++
26 files changed, 109 insertions(+), 48 deletions(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 02f0327..168c0d6 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -1,7 +1,7 @@
name: "Tests"
on:
push:
- branches: [master]
+ branches: ['*']
paths-ignore:
- '**.md'
- 'cli/'
@@ -24,7 +24,7 @@ jobs:
persist-credentials: false
- name: "Install Linux dependencies"
- timeout-minutes: 2
+ timeout-minutes: 4
run: |
sudo apt-get update && sudo apt-get install -y \
composer
@@ -36,7 +36,7 @@ jobs:
composer install
- name: "Run Composer check-full"
- timeout-minutes: 10
+ timeout-minutes: 20
run: |
grep '"timeout": 20,' infection.json5
sed -i 's/"timeout": 20,/"timeout": 40,/' infection.json5
diff --git a/cli/server.php b/cli/server.php
index 7b336d3..c849cd8 100644
--- a/cli/server.php
+++ b/cli/server.php
@@ -14,6 +14,7 @@
$port = (int)($argv[2] ?? 8080);
$debug = in_array('--debug', $argv);
$bindAddress = "udp://0.0.0.0:$port";
+$map = new Maps\DefaultMap();
/////
$settings = new ServerSetting($playersMax); // must be first for correctly setting the global tickRate (Util::$TICK_RATE)
@@ -22,7 +23,7 @@
$logger->info("Preparing game for launch, please wait...");
$game = ($debug ? GameFactory::createDebug() : GameFactory::createDefaultCompetitive());
-$game->loadMap(new Maps\DefaultMap());
+$game->loadMap($map);
$logger->info("Starting server on '{$bindAddress}', waiting maximum of '{$settings->warmupWaitSec}' sec for '{$playersMax}' player" . ($playersMax > 1 ? 's' : '') . " to connect.");
$net = new ClueSocket($bindAddress);
diff --git a/composer.json b/composer.json
index a5aee2b..8b8b056 100644
--- a/composer.json
+++ b/composer.json
@@ -2,8 +2,8 @@
"scripts": {
"post-install-cmd": "@php -d memory_limit=200M cli/generateNavmesh.php",
"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 --show-mutations --only-covered --threads=max --min-covered-msi=100",
+ "unit": "@php vendor/bin/phpunit -d memory_limit=200M",
+ "infection": "@php -d memory_limit=300M vendor/bin/infection --show-mutations --threads=max --min-covered-msi=100",
"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",
@@ -28,7 +28,7 @@
"check-full": [
"@check",
"@coverage",
- "@infection-cache"
+ "@infection-cache --skip-initial-tests"
]
},
"require": {
@@ -60,7 +60,7 @@
"platform": {
"php": "8.3"
},
- "process-timeout": 720,
+ "process-timeout": 0,
"allow-plugins": {
"infection/extension-installer": false
}
diff --git a/infection.json5 b/infection.json5
index 40eea29..eac77c4 100644
--- a/infection.json5
+++ b/infection.json5
@@ -7,6 +7,8 @@
},
"timeout": 20,
"testFramework": "phpunit",
+ "staticAnalysisTool": "phpstan",
+ "staticAnalysisToolOptions": "--memory-limit=300M",
"mutators": {
"global-ignoreSourceCodeByRegex": [
"\\$this->log\\(.*\\);",
@@ -14,26 +16,22 @@
"GameException::invalid\\(.*\\);",
"GameException::notImplementedYet\\(.*\\);",
"assert\\(.+?\\);",
+ "if\\s*\\(\\$count > 10 && \\$count % 2 === 0\\)\\s\\{",
],
"@default": true,
"@conditional_boundary": false,
"@conditional_negotiation": false,
- "CastInt": false,
"Continue_": false,
"DecrementInteger": false,
"FalseValue": false,
- "IfNegation": false,
"Increment": false,
"IncrementInteger": false,
- "LogicalAnd": false,
"LogicalAndAllSubExprNegation": false,
"LogicalOr": false,
- "LogicalOrAllSubExprNegation": false,
"Minus": false,
- "Modulus": false,
"Multiplication": false,
- "NullSafeMethodCall": false,
"Plus": false,
+ "ReturnRemoval": false,
"RoundingFamily": false,
"TrueValue": false,
"ArrayItem": {
@@ -69,11 +67,6 @@
"if\\s*\\(\\$this->ball->getResolutionAngleVertical\\(\\) > 0 && \\(.+",
],
},
- "LogicalAndNegation": {
- "ignoreSourceCodeByRegex": [
- "if\\s*\\(\\$count > 10 && \\$count % 2 === 0\\)\\s\\{",
- ],
- },
"LogicalNot": {
"ignoreSourceCodeByRegex": [
".+\\$this->lastMoveX === -\\$moveX.+",
@@ -85,6 +78,9 @@
],
},
"MethodCallRemoval": {
+ "ignore": [
+ "cs\\Equipment\\Bomb::unEquip",
+ ],
"ignoreSourceCodeByRegex": [
"\\$this->setActiveFloor\\(.+\\);",
"\\$prevPos->setFrom\\(\\$candidate\\);",
diff --git a/phpunit.xml b/phpunit.xml
index 7a48895..5c9804c 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -25,7 +25,6 @@
server/src/
- server/src/Equipment/
server/src/Map/
server/src/Weapon/
diff --git a/server/src/Core/BuyMenu.php b/server/src/Core/BuyMenu.php
index 5ac4319..3371b67 100644
--- a/server/src/Core/BuyMenu.php
+++ b/server/src/Core/BuyMenu.php
@@ -29,7 +29,7 @@ public function reset(bool $forAttackerStore, array $alreadyHaveItems): void
foreach ($alreadyHaveItems as $item) {
if ($item->getType() === ItemType::TYPE_GRENADE) {
- $this->grenadeCount++;
+ $this->grenadeCount += $item->getQuantity();
}
if (!isset($this->itemBuyCount[$item->getId()])) {
diff --git a/server/src/Core/HitBox.php b/server/src/Core/HitBox.php
index 31ec0d5..69931ef 100644
--- a/server/src/Core/HitBox.php
+++ b/server/src/Core/HitBox.php
@@ -34,6 +34,7 @@ public function reset(): void
$this->damage = 0;
}
+ /** @infection-ignore-all */
public function getHitAntiForce(Point $point): int
{
if ($this->type === HitBoxType::HEAD) {
@@ -84,6 +85,7 @@ public function registerHit(Bullet $bullet): void
}
}
+ /** @infection-ignore-all */
private function calculateArmorDamage(BaseWeapon $shootItem, ArmorType $armorType, HitBoxType $hitBoxType): int
{
if ($armorType->hasNoArmor() || $hitBoxType === HitBoxType::LEG) {
diff --git a/server/src/Core/PathFinder.php b/server/src/Core/PathFinder.php
index 8077a95..ae458ea 100644
--- a/server/src/Core/PathFinder.php
+++ b/server/src/Core/PathFinder.php
@@ -9,7 +9,7 @@
final class PathFinder
{
private Graph $graph;
- /** @var array */
+ /** @var array */
private array $visited = [];
private readonly int $obstacleOvercomeHeight;
/** @var array */
@@ -105,8 +105,8 @@ public function findTile(Point $pointOnFloor, int $radius): ?Point
return $floorNavmeshPoint;
}
- $maxDistance = $this->navigationMesh->tileSize * 2;
- $maxY = $this->obstacleOvercomeHeight * 2;
+ $maxDistance = $this->navigationMesh->tileSize + $this->navigationMesh->tileSize;
+ $maxY = $this->obstacleOvercomeHeight + $this->obstacleOvercomeHeight;
$checkAbove = function (Point $start, int $maxY, int $radius): ?Point {
$yCandidate = $start->clone();
$navMeshCenter = $yCandidate->clone();
@@ -188,7 +188,7 @@ public function buildNavigationMesh(Point $start, int $objectHeight, int $maxNod
continue;
}
- $this->visited[$currentKey] = true;
+ $this->visited[$currentKey] = null;
$currentNode = $this->graph->getNodeById($currentKey);
if ($currentNode === null) {
$currentNode = new Node($currentKey, $current);
@@ -210,7 +210,7 @@ public function buildNavigationMesh(Point $start, int $objectHeight, int $maxNod
$this->graph->addEdge(new DirectedEdge($currentNode, $newNode, 1));
$queue->enqueue($newNeighbour);
}
- if (++$nodeCount === $maxNodeCount) {
+ if (++$nodeCount === $maxNodeCount) { // @codeCoverageIgnore
GameException::notImplementedYet('MaxNodeCount hit - new map, tileSize or bad test (no boundary box, bad starting point)?'); // @codeCoverageIgnore
}
}
diff --git a/server/src/Core/PlayerStat.php b/server/src/Core/PlayerStat.php
index be45ced..2f819b4 100644
--- a/server/src/Core/PlayerStat.php
+++ b/server/src/Core/PlayerStat.php
@@ -41,6 +41,11 @@ public function getKills(): int
return $this->kills;
}
+ public function getHeadshotKills(): int
+ {
+ return $this->killsHeadshot;
+ }
+
public function getDeaths(): int
{
return $this->deaths;
diff --git a/server/src/Core/Score.php b/server/src/Core/Score.php
index 8a63113..eac530c 100644
--- a/server/src/Core/Score.php
+++ b/server/src/Core/Score.php
@@ -73,7 +73,7 @@ public function roundEnd(RoundEndEvent $event): void
}
if ($this->secondHalfScore !== []) {
- $this->secondHalfScore[(int)$attackersWins]++;
+ $this->secondHalfScore[$attackersWins ? 1 : 0]++;
}
$this->lastRoundAttackerWins = $attackersWins;
$this->roundsHistory[$this->roundNumber] = [
@@ -145,7 +145,7 @@ public function toArray(): array
$scoreboard = [[], []];
foreach ($this->playerStats as $playerId => $playerStat) {
$key = sprintf('%d-%d-%d', $playerStat->getKills(), $playerStat->getDamage(), $playerId);
- $scoreboard[(int)$playerStat->isAttacker()][$key] = $playerStat->toArray();
+ $scoreboard[$playerStat->isAttacker() ? 1 : 0][$key] = $playerStat->toArray();
}
$teamDefenders = $scoreboard[0];
$teamAttackers = $scoreboard[1];
diff --git a/server/src/Equipment/Grenade.php b/server/src/Equipment/Grenade.php
index 4137963..a78a86c 100644
--- a/server/src/Equipment/Grenade.php
+++ b/server/src/Equipment/Grenade.php
@@ -35,6 +35,7 @@ public function attackSecondary(Attackable $event): ?AttackResult
return $event->fire();
}
+ /** @codeCoverageIgnore **/
public function getDamageValue(HitBoxType $hitBox, ArmorType $armor): int
{
GameException::invalid();
@@ -55,6 +56,7 @@ public function getSpeedMultiplier(): float
return ($this->primaryAttack ? 1.0 : 0.5);
}
+ /** @codeCoverageIgnore **/
public function createBullet(): Bullet
{
GameException::invalid(get_class($this));
diff --git a/server/src/Equipment/HighExplosive.php b/server/src/Equipment/HighExplosive.php
index a303a46..ca33174 100644
--- a/server/src/Equipment/HighExplosive.php
+++ b/server/src/Equipment/HighExplosive.php
@@ -27,7 +27,7 @@ public function calculateDamage(int $distanceSquared, bool $harArmor): int
{
$distanceSquared = max(1, $distanceSquared);
if ($distanceSquared >= self::MAX_BLAST_RADIUS_SQUARED) {
- return 0;
+ return 0; // @codeCoverageIgnore
}
$damage = self::DAMAGE * (1 - ($distanceSquared / self::MAX_BLAST_RADIUS_SQUARED));
diff --git a/server/src/Equipment/Incendiary.php b/server/src/Equipment/Incendiary.php
index 9690f3f..fab2f45 100644
--- a/server/src/Equipment/Incendiary.php
+++ b/server/src/Equipment/Incendiary.php
@@ -31,6 +31,7 @@ public function getMaxAreaMetersSquared(): int
return 200_000;
}
+ /** @codeCoverageIgnore **/
public function calculateDamage(bool $hasKevlar): int
{
return $hasKevlar ? 7 : 3;
diff --git a/server/src/Equipment/Kevlar.php b/server/src/Equipment/Kevlar.php
index 4f63c83..2cf6f30 100644
--- a/server/src/Equipment/Kevlar.php
+++ b/server/src/Equipment/Kevlar.php
@@ -29,6 +29,7 @@ public function repairArmor(): void
$this->armor = 100;
}
+ /** @codeCoverageIgnore **/
public function lowerArmor(int $armorDamage): void
{
assert($armorDamage >= 0);
@@ -86,12 +87,12 @@ public function canPurchaseMultipleTime(Item $newSlotItem): bool
public function getPrice(?Item $alreadyHaveSlotItem = null): int
{
/** @var ?self $alreadyHaveSlotItem */
- if ($alreadyHaveSlotItem && $this->type === ArmorType::BODY_AND_HEAD && $alreadyHaveSlotItem->type === ArmorType::BODY && $alreadyHaveSlotItem->armor === 100) {
- return 350;
- }
if ($alreadyHaveSlotItem && $alreadyHaveSlotItem->type === ArmorType::BODY_AND_HEAD) {
return 650;
}
+ if ($alreadyHaveSlotItem && $this->type === ArmorType::BODY_AND_HEAD && $alreadyHaveSlotItem->type === ArmorType::BODY && $alreadyHaveSlotItem->armor === 100) {
+ return 350;
+ }
return $this->bodyPlusHelmet ? 1000 : 650;
}
diff --git a/server/src/Event/GrillEvent.php b/server/src/Event/GrillEvent.php
index 99124a0..92787cf 100644
--- a/server/src/Event/GrillEvent.php
+++ b/server/src/Event/GrillEvent.php
@@ -4,7 +4,6 @@
use cs\Core\Column;
use cs\Core\Point;
-use cs\Core\Setting;
use cs\Enum\SoundType;
final class GrillEvent extends VolumetricEvent
@@ -35,7 +34,6 @@ protected function shrinkPart(Column $column): void
protected function expandPart(Point $center): Column
{
- assert($this->partHeight < Setting::playerHeadHeightCrouch());
$flame = new Column($center, $this->partRadius, $this->partHeight);
if ($this->world->flameCanIgnite($flame)) {
$soundEvent = new SoundEvent($flame->center, SoundType::FLAME_SPAWN);
@@ -57,7 +55,7 @@ public function extinguish(Column $flame): void
public function canHitPlayer(int $playerId, int $tickId): bool
{
- return (($this->playerTickHits[$playerId] ?? 0) + $this->damageCoolDownTickCount <= $tickId);
+ return (($this->playerTickHits[$playerId] ?? -$this->damageCoolDownTickCount) + $this->damageCoolDownTickCount <= $tickId);
}
public function playerHit(int $playerId, int $tickId): void
diff --git a/server/src/Event/PauseStartEvent.php b/server/src/Event/PauseStartEvent.php
index 6be9197..30f29b0 100644
--- a/server/src/Event/PauseStartEvent.php
+++ b/server/src/Event/PauseStartEvent.php
@@ -10,7 +10,7 @@ final class PauseStartEvent extends TimeoutEvent
{
/** @param Closure(static,int):void $callback */
- public function __construct(private Game $game, private PauseReason $reason, Closure $callback, int $timeoutMs)
+ public function __construct(private Game $game, public readonly PauseReason $reason, Closure $callback, int $timeoutMs)
{
parent::__construct($callback, $timeoutMs);
}
diff --git a/server/src/Event/ThrowEvent.php b/server/src/Event/ThrowEvent.php
index 929fd56..ab80174 100644
--- a/server/src/Event/ThrowEvent.php
+++ b/server/src/Event/ThrowEvent.php
@@ -143,6 +143,7 @@ public function process(int $tick): void
continue;
}
+ /** @infection-ignore-all */
if (
$this->ball->getResolutionAngleVertical() > 0
&& ($this->item instanceof Flammable || $this->item instanceof Smoke)
diff --git a/server/src/Net/ClueSocket.php b/server/src/Net/ClueSocket.php
index b931763..947defe 100644
--- a/server/src/Net/ClueSocket.php
+++ b/server/src/Net/ClueSocket.php
@@ -36,7 +36,7 @@ public function sendTo(Client $client, string &$msg): void
}
}
- public function receive(?string &$peerAddress, ?int &$peerPort, int $readMaxBytes = 100): ?string
+ public function receive(?string &$peerAddress, ?int &$peerPort, int $readMaxBytes): ?string
{
$ret = @socket_recvfrom($this->resource, $buffer, $readMaxBytes, 0, $peerAddress, $peerPort); // @phpstan-ignore-line
if ($ret === false) {
diff --git a/server/src/Net/NetConnector.php b/server/src/Net/NetConnector.php
index 3c03013..82a870a 100644
--- a/server/src/Net/NetConnector.php
+++ b/server/src/Net/NetConnector.php
@@ -8,7 +8,7 @@ interface NetConnector
/**
* @throws NetException
*/
- public function receive(?string &$peerAddress, ?int &$peerPort, int $readMaxBytes = 100): ?string;
+ public function receive(?string &$peerAddress, ?int &$peerPort, int $readMaxBytes): ?string;
/**
* @throws NetException
diff --git a/server/src/Net/TestConnector.php b/server/src/Net/TestConnector.php
index a7eb4d7..824936e 100644
--- a/server/src/Net/TestConnector.php
+++ b/server/src/Net/TestConnector.php
@@ -20,7 +20,7 @@ public function __construct(private array $requests)
{
}
- public function receive(?string &$peerAddress, ?int &$peerPort, int $readMaxBytes = 100): ?string
+ public function receive(?string &$peerAddress, ?int &$peerPort, int $readMaxBytes): ?string
{
if (!$this->expectReceive) {
return null;
diff --git a/test/og/Game/RoundTest.php b/test/og/Game/RoundTest.php
index 70ec630..0702d66 100644
--- a/test/og/Game/RoundTest.php
+++ b/test/og/Game/RoundTest.php
@@ -12,8 +12,10 @@
use cs\Enum\Color;
use cs\Enum\GameOverReason;
use cs\Enum\InventorySlot;
+use cs\Enum\PauseReason;
use cs\Enum\SoundType;
use cs\Equipment\Bomb;
+use cs\Equipment\DefuseKit;
use cs\Event\GameOverEvent;
use cs\Event\KillEvent;
use cs\Event\PauseEndEvent;
@@ -425,7 +427,7 @@ function () use ($enemy) {
public function testMultipleRoundsScoreAndEvents(): void
{
- $maxRounds = 4;
+ $maxRounds = 5;
$gameProperty = $this->createNoPauseGameProperty($maxRounds);
$gameProperty->bomb_plant_time_ms = 0;
$gameProperty->bomb_defuse_time_ms = 0;
@@ -443,13 +445,16 @@ public function testMultipleRoundsScoreAndEvents(): void
$eventCounts = [];
$eventObjects = [];
- $game->onEvents(function (array $events) use (&$eventCounts, &$eventObjects): void {
+ $game->onEvents(function (array $events) use ($game, &$eventCounts, &$eventObjects): void {
foreach ($events as $event) {
if (!isset($eventCounts[$event::class])) {
$eventCounts[$event::class] = 0;
}
$eventCounts[$event::class]++;
$eventObjects[$event::class] = $event;
+ if ($event instanceof PauseStartEvent && $event->reason === PauseReason::HALF_TIME) {
+ $this->assertTrue($game->isPaused());
+ }
}
});
@@ -475,11 +480,18 @@ function () use ($p2) {
fn() => $this->assertTrue($p1->buyItem(BuyMenuItem::GRENADE_FLASH)),
fn() => $p1->buyItem(BuyMenuItem::DEFUSE_KIT),
fn() => $this->assertTrue($p1->getInventory()->has(InventorySlot::SLOT_KIT->value)),
+ function () use ($p1) {
+ $kit = $p1->getInventory()->getItemSlot(InventorySlot::SLOT_KIT);
+ $this->assertInstanceOf(DefuseKit::class, $kit);
+ $this->assertFalse($kit->isUserDroppable());
+ $this->assertFalse($kit->canPurchaseMultipleTime($kit));
+ },
fn() => $p2->buyItem(BuyMenuItem::DEFUSE_KIT),
fn() => $this->assertFalse($p2->getInventory()->has(InventorySlot::SLOT_KIT->value)),
fn() => $this->assertTrue($p2->buyItem(BuyMenuItem::GRENADE_FLASH)),
fn() => $this->assertTrue($p2->buyItem(BuyMenuItem::GRENADE_FLASH)),
fn() => $this->assertTrue($p2->buyItem(BuyMenuItem::GRENADE_DECOY)),
+ fn() => $this->assertTrue($p2->buyItem(BuyMenuItem::GRENADE_HE)),
fn() => $p1->suicide(),
fn() => $this->assertSame(4, $game->getRoundNumber()),
function () use ($p1, $p2) {
@@ -489,9 +501,14 @@ function () use ($p1, $p2) {
$this->assertTrue($p2->getInventory()->has(InventorySlot::SLOT_BOMB->value));
$this->assertTrue($p2->getInventory()->has(InventorySlot::SLOT_GRENADE_FLASH->value));
$this->assertTrue($p2->getInventory()->has(InventorySlot::SLOT_GRENADE_DECOY->value));
+ $this->assertTrue($p2->getInventory()->has(InventorySlot::SLOT_GRENADE_HE->value));
+ $this->assertFalse($p2->buyItem(BuyMenuItem::GRENADE_MOLOTOV));
$this->assertFalse($p1->getInventory()->has(InventorySlot::SLOT_GRENADE_FLASH->value));
},
$this->waitNTicks(800),
+ fn() => $this->assertTrue($game->getScore()->isTie()),
+ fn() => $p1->suicide(),
+ $this->endGame(),
]);
$this->assertNotEmpty($eventCounts);
@@ -502,11 +519,11 @@ function () use ($p1, $p2) {
$this->assertSame($maxRounds, $eventCounts[RoundEndEvent::class]);
$this->assertSame(2, $eventCounts[PlantEvent::class]);
$this->assertSame($maxRounds - 2, $eventCounts[RoundEndCoolDownEvent::class]);
- $this->assertTrue($game->getScore()->isTie());
+ $this->assertFalse($game->getScore()->isTie());
$expectedScoreBoard = [
- 'score' => [2, 2],
- 'lossBonus' => [1400, 1400],
+ 'score' => [2, 3],
+ 'lossBonus' => [1400, 1900],
'history' => [
1 => [
'attackersWins' => false,
@@ -532,16 +549,22 @@ function () use ($p1, $p2) {
'scoreAttackers' => 2,
'scoreDefenders' => 2,
],
+ 5 => [
+ 'attackersWins' => true,
+ 'reason' => 0,
+ 'scoreAttackers' => 3,
+ 'scoreDefenders' => 2,
+ ],
],
'firstHalfScore' => [1, 1],
- 'secondHalfScore' => [1, 1],
+ 'secondHalfScore' => [1, 2],
'halfTimeRoundNumber' => 2,
'scoreboard' => [
[
[
'id' => 1,
- 'kills' => -1,
- 'deaths' => 1,
+ 'kills' => -2,
+ 'deaths' => 2,
'damage' => 0,
],
],
diff --git a/test/og/Inventory/InventoryTest.php b/test/og/Inventory/InventoryTest.php
index ec60e2a..c3e85a3 100644
--- a/test/og/Inventory/InventoryTest.php
+++ b/test/og/Inventory/InventoryTest.php
@@ -18,6 +18,7 @@
use cs\Equipment\Decoy;
use cs\Equipment\Flashbang;
use cs\Equipment\HighExplosive;
+use cs\Equipment\Kevlar;
use cs\Event\SoundEvent;
use cs\Weapon\Knife;
use cs\Weapon\PistolGlock;
@@ -227,6 +228,18 @@ public function testPlayerBuyAndDropAndUseForPickup(): void
fn(Player $p) => $p->getSight()->lookHorizontal(45),
fn(Player $p) => $p->use(),
fn(Player $p) => $this->assertTrue($p->getInventory()->has(InventorySlot::SLOT_SECONDARY->value)),
+ // non primary nor secondary item already had in inventory pickup
+ fn(Player $p) => $p->getSight()->lookVertical(-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->assertSame(2, $p->getEquippedItem()->getQuantity()),
+ fn(Player $p) => $this->assertNotNull($p->dropEquippedItem()),
+ fn(Player $p) => $this->assertSame(1, $p->getEquippedItem()->getQuantity()),
+ fn(Player $p) => $this->assertTrue($p->getInventory()->has(InventorySlot::SLOT_GRENADE_FLASH->value)),
+ $this->waitNTicks(200),
+ fn(Player $p) => $this->assertSame(1, $p->getEquippedItem()->getQuantity()),
+ fn(Player $p) => $p->use(),
+ fn(Player $p) => $this->assertSame(2, $p->getEquippedItem()->getQuantity()),
$this->endGame(),
]);
}
@@ -692,6 +705,10 @@ function (Player $p): void {
$this->assertSame(1651, $p->getMoney());
$this->assertSame(ArmorType::BODY, $p->getArmorType());
$this->assertSame(100, $p->getArmorValue());
+ $kevlar = $p->getInventory()->getItemSlot(InventorySlot::SLOT_KEVLAR);
+ $this->assertInstanceOf(Kevlar::class, $kevlar);
+ $this->assertFalse($kevlar->isUserDroppable());
+ $this->assertFalse($kevlar->canPurchaseMultipleTime($kevlar));
},
fn(Player $p) => $p->lowerArmor(10),
function (Player $p): void {
diff --git a/test/og/Shooting/BombTest.php b/test/og/Shooting/BombTest.php
index d803b7b..c7a284d 100644
--- a/test/og/Shooting/BombTest.php
+++ b/test/og/Shooting/BombTest.php
@@ -178,6 +178,7 @@ public function testBombPlantReset(): void
$gameProperty->bomb_plant_time_ms = self::TEST_TICK_RATE * 2;
$gameProperty->bomb_explode_time_ms = 100;
$game = $this->createTestGame(null, $gameProperty);
+ $game->addPlayer(new Player(2, Color::GREEN, false));
$start = new Point(321, 0, 300);
$this->playPlayer($game, [
@@ -203,6 +204,8 @@ function (Player $p) use ($game) {
function (Player $p) use ($game) {
$this->assertFalse($game->isBombActive());
$p->attack();
+ $this->assertTrue($p->isPlantingOrDefusing());
+ $this->assertFalse($game->getPlayer(2)->isPlantingOrDefusing());
$this->assertFalse($game->isBombActive());
},
fn(Player $p) => $p->attack(),
diff --git a/test/og/Shooting/PlayerKillTest.php b/test/og/Shooting/PlayerKillTest.php
index 7d73622..bd98957 100644
--- a/test/og/Shooting/PlayerKillTest.php
+++ b/test/og/Shooting/PlayerKillTest.php
@@ -437,6 +437,7 @@ public function testArmorShooting(): void
$p2->getSight()->look(-90, -90);
$p2->setPosition(new Point(300, 0, 500));
$p2->buyItem(BuyMenuItem::KEVLAR_BODY);
+ $this->assertSame(150, $p2->getMoney());
$game->addPlayer(new Player(3, Color::ORANGE, false));
$game->getPlayer(3)->setPosition(new Point(350, 0, 500));
@@ -458,7 +459,7 @@ function (Player $p) use ($p2) {
$this->assertSame(HitBoxType::BACK, $bodyShot->getType());
$this->assertLessThan(100, $p2->getHealth());
- $this->assertLessThan(100, $p2->getArmorValue());
+ $this->assertSame(90, $p2->getArmorValue());
$this->assertTrue($p->isAlive());
$this->assertTrue($p2->isAlive());
},
@@ -610,6 +611,7 @@ function (Player $p) {
$this->assertSame(3, $killEventsCount);
$this->assertSame(3, $game->getScore()->getScoreDefenders());
+ $this->assertSame(3, $game->getScore()->getPlayerStat(2)->getHeadshotKills());
$this->assertSame(3 + 1, $game->getRoundNumber());
$this->assertSame(6500, $p1->getMoney());
$this->assertSame(11450, $player2->getMoney());
diff --git a/test/og/Shooting/ShootTest.php b/test/og/Shooting/ShootTest.php
index fc425cd..03eaab3 100644
--- a/test/og/Shooting/ShootTest.php
+++ b/test/og/Shooting/ShootTest.php
@@ -315,6 +315,7 @@ public function testDamageLowOnRangeMaxDamage(): void
$this->assertSame(99, $game->getPlayer(2)->getHealth());
$this->assertSame(1, $bulletHitHeadShotsCount);
+ $this->assertSame(0, $game->getScore()->getPlayerStat(1)->getHeadshotKills());
}
}
diff --git a/test/og/Unit/CollisionTest.php b/test/og/Unit/CollisionTest.php
index 87200cd..e16cda0 100644
--- a/test/og/Unit/CollisionTest.php
+++ b/test/og/Unit/CollisionTest.php
@@ -47,9 +47,14 @@ public function testPointWithCircle(): void
$this->assertTrue(Collision::pointWithCircle(10, 10, 10, 10, 1));
$this->assertTrue(Collision::pointWithCircle(11, 10, 10, 10, 1));
$this->assertTrue(Collision::pointWithCircle(10, 11, 10, 10, 1));
+ $this->assertTrue(Collision::pointWithCircle(15, 10, 10, 10, 5));
+ $this->assertTrue(Collision::pointWithCircle(10, 15, 10, 10, 6));
$this->assertFalse(Collision::pointWithCircle(10, 13, 10, 10, 2));
$this->assertFalse(Collision::pointWithCircle(13, 10, 10, 10, 2));
+ $this->assertFalse(Collision::pointWithCircle(15, 15, 10, 10, 4));
+ $this->assertFalse(Collision::pointWithCircle(15, 10, 10, 10, 4));
+ $this->assertFalse(Collision::pointWithCircle(10, 15, 10, 10, 4));
}
public function testCircleWithPlaneFalse(): void
@@ -360,6 +365,10 @@ public function testBoxWithBox(): void
new Point(-5, 0, -5), new Point(5, 4, 5),
new Point(1, -6, -5), new Point(3, -3, -3),
));
+ $this->assertFalse(Collision::boxWithBox(
+ new Point(0, 0, 0), new Point(5, 1, 1),
+ new Point(-10, 0, 0), new Point(-3, 1, 1),
+ ));
}
From c29ab06d5c6097fb7c71d16d5a7795e79e2c9b26 Mon Sep 17 00:00:00 2001
From: Ryan Cooper <198979606+coopryan@users.noreply.github.com>
Date: Sat, 30 Aug 2025 14:52:46 +0200
Subject: [PATCH 3/3] refactor Package handling
---
server/src/Core/Game.php | 2 +-
server/src/Core/World.php | 46 +++++------------
server/src/Equipment/Bomb.php | 63 +++++++++++++++++++-----
server/src/Traits/Player/AttackTrait.php | 2 +-
4 files changed, 63 insertions(+), 50 deletions(-)
diff --git a/server/src/Core/Game.php b/server/src/Core/Game.php
index 4604340..2d2c2c0 100644
--- a/server/src/Core/Game.php
+++ b/server/src/Core/Game.php
@@ -29,7 +29,7 @@
class Game
{
- private Bomb $bomb;
+ public readonly Bomb $bomb;
private World $world;
private Score $score;
private GameState $state;
diff --git a/server/src/Core/World.php b/server/src/Core/World.php
index d1f95af..ba9c2f7 100644
--- a/server/src/Core/World.php
+++ b/server/src/Core/World.php
@@ -46,14 +46,12 @@ final class World
/** @var array */
private array $activeMolotovs = [];
private Bomb $bomb;
- private int $lastBombActionTick = -1;
- private int $lastBombPlayerId = -1;
- private int $bombActionTickBuffer = 1;
private ?NavigationMesh $grenadeNavigationMesh = null;
private ?PathFinder $grenadePathFinder = null;
public function __construct(private Game $game)
{
+ $this->bomb = $game->bomb;
}
public function roundReset(): void
@@ -293,21 +291,11 @@ public function playerUse(Player $player): void
if (!$player->isPlayingOnAttackerSide() && $this->game->isBombActive()
&& $this->canBeSeen($player, $this->bomb->getPosition(), self::BOMB_RADIUS, self::BOMB_DEFUSE_MAX_DISTANCE)
) {
- $bomb = $this->bomb;
- $tickId = $this->getTickId();
- $playerId = $player->getId();
- if ($playerId !== $this->lastBombPlayerId || $this->lastBombActionTick + $this->bombActionTickBuffer < $tickId) {
- $player->stop();
- $bomb->startDefusing($tickId, $player->hasDefuseKit());
+ $defused = $this->bomb->tryDefuse($player, $this->getTickId());
+ if ($defused === null) {
$soundEvent = new SoundEvent($player->getPositionClone()->addY(10), SoundType::BOMB_DEFUSING);
- $this->makeSound($soundEvent->setPlayer($player)->setItem($bomb));
- }
- $this->lastBombActionTick = $tickId;
- $this->lastBombPlayerId = $playerId;
-
- if ($bomb->isDefused($tickId)) {
- $this->lastBombActionTick = -1;
- $this->lastBombPlayerId = -1;
+ $this->makeSound($soundEvent->setPlayer($player)->setItem($this->bomb));
+ } elseif ($defused === true) {
$this->game->bombDefused($player);
}
return;
@@ -802,37 +790,25 @@ private function playerHit(Point $hitPoint, Player $playerHit, Player $playerCul
}
}
- public function tryPlantBomb(Player $player, Bomb $bomb): void
+ public function tryPlantBomb(Player $player): void
{
if (!$this->canPlant($player)) {
return;
}
- $tickId = $this->getTickId();
- $playerId = $player->getId();
- if ($playerId !== $this->lastBombPlayerId || $this->lastBombActionTick + $this->bombActionTickBuffer < $tickId) {
- $player->stop();
- $bomb->startPlanting($tickId);
+ $planted = $this->bomb->tryPlant($player, $this->getTickId());
+ if ($planted === null) {
$soundEvent = new SoundEvent($player->getPositionClone()->addY(10), SoundType::BOMB_PLANTING);
- $this->makeSound($soundEvent->setPlayer($player)->setItem($bomb));
- }
- $this->lastBombActionTick = $this->getTickId();
- $this->lastBombPlayerId = $playerId;
-
- if ($bomb->isPlanted($tickId)) {
+ $this->makeSound($soundEvent->setPlayer($player)->setItem($this->bomb));
+ } elseif ($planted === true) {
$player->equip($player->getInventory()->removeBomb());
- $bomb->setPosition($player->getPositionClone());
$this->game->bombPlanted($player);
-
- $this->bomb = $bomb;
- $this->lastBombActionTick = -1;
- $this->lastBombPlayerId = -1;
}
}
public function isPlantingOrDefusing(Player $player): bool
{
- return ($this->lastBombPlayerId === $player->getId() && $this->bombActionTickBuffer >= $this->getTickId() - $this->lastBombActionTick);
+ return $this->bomb->isPlantingOrDefusing($player->getId(), $this->getTickId());
}
public function isWallOrFloorCollision(Point $start, Point $candidate, int $radius): bool
diff --git a/server/src/Equipment/Bomb.php b/server/src/Equipment/Bomb.php
index 4ca61e7..98b1c20 100644
--- a/server/src/Equipment/Bomb.php
+++ b/server/src/Equipment/Bomb.php
@@ -13,17 +13,22 @@ class Bomb extends BaseEquipment
public const int equipReadyTimeMs = 80;
private Point $position;
- private int $plantTickStart = 0;
+ private int $plantTickStart;
private int $plantTickCountMax;
- private int $defuseTickStart = 0;
+ private int $defuseTickStart;
private int $defuseTickCountMax;
private int $tickToDefuseCount;
+ private int $lastBombActionTick = -1;
+ private int $lastBombPlayerId = -1;
- public function __construct(int $plantTimeMs, int $defuseTimeMs, private int $maxBlastDistance = 1000)
+ public function __construct(int $plantTimeMs, int $defuseTimeMs, private int $maxBlastDistance = 1000, private int $bombActionTickBuffer = 1)
{
parent::__construct();
+ $this->position = new Point();
$this->plantTickCountMax = Util::millisecondsToFrames($plantTimeMs);
+ $this->plantTickStart = -$this->plantTickCountMax;
$this->defuseTickCountMax = Util::millisecondsToFrames($defuseTimeMs);
+ $this->defuseTickStart = -$this->defuseTickCountMax;
}
public function setMaxBlastDistance(int $maxBlastDistance): void
@@ -56,30 +61,61 @@ public function unEquip(): void
$this->reset();
}
- public function startPlanting(int $tickStart): void
+ public function tryPlant(Player $player, int $tickId): ?bool
{
- $this->plantTickStart = $tickStart;
+ $planted = false;
+ $playerId = $player->getId();
+ if ($playerId !== $this->lastBombPlayerId || $this->lastBombActionTick + $this->bombActionTickBuffer < $tickId) {
+ $player->stop();
+ $this->plantTickStart = $tickId;
+ $planted = null;
+ }
+ $this->lastBombActionTick = $tickId;
+ $this->lastBombPlayerId = $playerId;
+
+ if ($this->isPlanted($tickId)) {
+ $this->position->setFrom($player->getReferenceToPosition());
+ $this->lastBombActionTick = -1;
+ $this->lastBombPlayerId = -1;
+ $planted = true;
+ }
+ return $planted;
}
- public function isPlanted(int $tickId): bool
+ public function tryDefuse(Player $player, int $tickId): ?bool
{
- return ($tickId - $this->plantTickStart >= $this->plantTickCountMax);
+ $defused = false;
+ $playerId = $player->getId();
+ if ($playerId !== $this->lastBombPlayerId || $this->lastBombActionTick + $this->bombActionTickBuffer < $tickId) {
+ $player->stop();
+ $this->defuseTickStart = $tickId;
+ $this->tickToDefuseCount = $player->hasDefuseKit() ? (int)ceil($this->defuseTickCountMax / 2) : $this->defuseTickCountMax;;
+ $defused = null;
+ }
+ $this->lastBombActionTick = $tickId;
+ $this->lastBombPlayerId = $playerId;
+
+ if ($this->isDefused($tickId)) {
+ $this->lastBombActionTick = -1;
+ $this->lastBombPlayerId = -1;
+ $defused = true;
+ }
+ return $defused;
}
- public function startDefusing(int $tickId, bool $hasDefuseKit): void
+ private function isPlanted(int $tickId): bool
{
- $this->defuseTickStart = $tickId;
- $this->tickToDefuseCount = $hasDefuseKit ? (int)ceil($this->defuseTickCountMax / 2) : $this->defuseTickCountMax;;
+ return ($tickId - $this->plantTickStart >= $this->plantTickCountMax);
}
- public function isDefused(int $tickId): bool
+ private function isDefused(int $tickId): bool
{
return ($tickId - $this->defuseTickStart >= $this->tickToDefuseCount);
}
- public function setPosition(Point $position): void
+ public function isPlantingOrDefusing(int $playerId, int $tickId): bool
{
- $this->position = $position;
+ return ($this->lastBombPlayerId === $playerId && $this->bombActionTickBuffer >= $tickId - $this->lastBombActionTick);
}
public function getPosition(): Point
@@ -87,6 +123,7 @@ public function getPosition(): Point
return $this->position;
}
+ /** @codeCoverageIgnore **/
public function explodeDamageToPlayer(Player $player): void
{
$distanceSquared = Util::distanceSquared($player->getPositionClone(), $this->position);
diff --git a/server/src/Traits/Player/AttackTrait.php b/server/src/Traits/Player/AttackTrait.php
index fd4e8f4..a5a97d4 100644
--- a/server/src/Traits/Player/AttackTrait.php
+++ b/server/src/Traits/Player/AttackTrait.php
@@ -31,7 +31,7 @@ public function attack(): ?AttackResult
if ($item instanceof Bomb) {
if ($item->canAttack($this->world->getTickId())) {
- $this->world->tryPlantBomb($this, $item);
+ $this->world->tryPlantBomb($this);
}
return null;
}