Counter-Strike/test/og/BaseTestCase.php

190 lines
5.7 KiB
PHP
Raw Normal View History

2022-08-13 12:40:42 +02:00
<?php
declare(strict_types=1);
namespace Test;
use Closure;
use cs\Core\GameProperty;
use cs\Core\GameState;
use cs\Core\Player;
2022-10-05 16:09:55 +02:00
use cs\Core\Setting;
2022-08-13 12:40:42 +02:00
use cs\Core\Util;
use cs\Enum\Color;
use cs\Map\TestMap;
use InvalidArgumentException;
2022-10-02 20:03:15 +02:00
use ReflectionProperty;
2022-08-13 12:40:42 +02:00
2022-09-21 19:13:50 +02:00
abstract class BaseTestCase extends BaseTest
2022-08-13 12:40:42 +02:00
{
2022-09-23 15:41:27 +02:00
private int $testTickRateMs = 10;
2022-10-05 16:09:55 +02:00
/** @var array<string,int|float> */
2022-10-02 20:03:15 +02:00
private array $defaultTestAction = [
2022-10-05 16:09:55 +02:00
'moveOneMs' => 5,
'moveWalkOneMs' => 4,
'moveCrouchOneMs' => 3,
'fallAmountOneMs' => 6,
'crouchDurationMs' => 40,
'jumpDurationMs' => 50,
2022-10-02 20:03:15 +02:00
// NOTE: Better to use even numbers for player const
2022-10-05 16:09:55 +02:00
'playerHeadRadius' => 30,
'playerBoundingRadius' => 44,
'playerJumpHeight' => 150,
'playerHeadHeightStand' => 190,
'playerHeadHeightCrouch' => 140,
'playerObstacleOvercomeHeight' => 20,
'playerFallDamageThreshold' => 570,
2022-10-02 20:03:15 +02:00
];
2022-08-13 12:40:42 +02:00
2022-10-05 16:09:55 +02:00
protected function setUp(): void
2022-08-13 12:40:42 +02:00
{
2022-09-23 15:41:27 +02:00
Util::$TICK_RATE = $this->testTickRateMs;
2022-10-03 16:49:07 +02:00
Setting::loadConstants($this->defaultTestAction);
2022-08-13 12:40:42 +02:00
}
/**
* @param array<Closure|int|false> $commands
* @param array<string,int|string> $gameProperties
*/
protected function simulateGame(array $commands, array $gameProperties = []): TestGame
{
$tickMax = count($commands);
foreach ($commands as $command) {
if (!is_int($command)) {
continue;
}
$tickMax += $command;
}
2022-10-04 19:45:10 +02:00
$game = $this->createTestGame($tickMax, GameProperty::fromArray($gameProperties));
2022-08-13 12:40:42 +02:00
$this->playPlayer($game, $commands);
return $game;
}
/**
* @param array<string,int|string> $gameProperties
2022-10-04 19:45:10 +02:00
* @deprecated use createTestGame() instead, this only set playerBoundingRadius() to 0
2022-08-13 12:40:42 +02:00
*/
protected function createOneRoundGame(int $tickMax = 1, array $gameProperties = []): TestGame
{
$properties = GameProperty::fromArray([
...[
GameProperty::MAX_ROUNDS => 1,
GameProperty::START_MONEY => 0,
GameProperty::FREEZE_TIME_SEC => 0,
GameProperty::ROUND_END_COOL_DOWN_SEC => 0,
GameProperty::RANDOMIZE_SPAWN_POSITION => false,
],
...$gameProperties,
]
);
$game = new TestGame($properties);
$game->loadMap(new TestMap());
$game->setTickMax($tickMax);
$testPlayer = new Player(1, Color::BLUE, true);
2022-10-02 20:03:15 +02:00
$boundingRadius = new ReflectionProperty($testPlayer, 'playerBoundingRadius');
$boundingRadius->setAccessible(true);
$boundingRadius->setValue($testPlayer, 0);
2022-09-20 13:19:28 +02:00
$testPlayer->equipKnife();
$game->addPlayer($testPlayer);
return $game;
}
protected function createTestGame(?int $tickMax = null, GameProperty $gameProperty = new GameProperty()): TestGame
{
$game = new TestGame($gameProperty);
$game->setTickMax($tickMax ?? PHP_INT_MAX);
$game->loadMap(new TestMap());
$testPlayer = new Player(1, Color::GREEN, true);
$testPlayer->equipKnife();
2022-08-13 12:40:42 +02:00
$game->addPlayer($testPlayer);
return $game;
}
/**
* @param array<string,int|string> $gameProperties
2022-10-04 19:45:10 +02:00
* @deprecated rather use createTestGame() maybe
2022-08-13 12:40:42 +02:00
*/
protected function createGame(array $gameProperties = []): TestGame
{
return $this->createOneRoundGame(PHP_INT_MAX, $gameProperties);
}
/**
* @param array<Closure|int|false> $commands
*/
2022-09-20 13:19:28 +02:00
protected function playPlayerDebug(TestGame $game, array $commands, int $playerId = 1): void
{
$this->playPlayer($game, $commands, $playerId, true);
}
/**
* @param array<Closure|int|false> $commands
*/
protected function playPlayer(TestGame $game, array $commands, int $playerId = 1, bool $debug = false): void
2022-08-13 12:40:42 +02:00
{
$i = 0;
$skipNTicks = 0;
$game->onTick(function (GameState $state) use (&$i, &$skipNTicks, $game, $playerId, $commands): void {
if ($skipNTicks-- > 0) {
return;
}
if (!isset($commands[$i])) {
throw new InvalidArgumentException("No command defined for tick '{$i}' or too many tickMax in Game");
}
if (false === $commands[$i]) {
$game->setTickMax(0);
$i++;
return;
}
if (is_int($commands[$i])) {
if ($commands[$i] <= 0) {
$this->fail("Skip ticks cannot be zero or negative");
}
$skipNTicks = $commands[$i];
$i++;
return;
}
$commands[$i]($state->getPlayer($playerId));
$i++;
});
2022-09-20 13:19:28 +02:00
if ($debug) {
$game->startDebug();
} else {
$game->start();
}
2022-08-13 12:40:42 +02:00
if (isset($commands[$i])) {
throw new InvalidArgumentException("Some command(s) were not processed, starting from tick '{$i}'");
}
}
/**
* @return false
*/
protected function endGame(): bool
{
return false;
}
protected function waitXTicks(int $numberOfTicks): int
{
return $numberOfTicks;
}
protected function waitNTicks(int $waitTimeMs): int
{
$waitTick = Util::millisecondsToFrames($waitTimeMs) - 1;
if ($waitTick < 1) {
throw new InvalidArgumentException("Value too low");
}
return $waitTick;
}
}