⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/udp-ws-bridge.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
$addressUdp = "udp://localhost:{$portUdp}";
///

$udp = (new Factory())->createClient($addressUdp, 4);
$udp = (new Factory())->createClient($addressUdp, 15);
$ws = new Server([
'filter' => ['text'],
'fragment_size' => '8192',
Expand Down
5 changes: 5 additions & 0 deletions infection.json5
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@
"if\\s*\\(\\$this->ball->getResolutionAngleVertical\\(\\) > 0 && \\(.+",
],
},
"LogicalAndNegation": {
"ignoreSourceCodeByRegex": [
".+\\$moveZ !== 0 && \\$planeCollision = \\$this->world->checkZSideWallCollision\\(\\$this->candidate, 2 \\* \\$r, \\$r.+",
]
},
"LogicalNot": {
"ignoreSourceCodeByRegex": [
".+\\$this->lastMoveX === -\\$moveX.+",
Expand Down
1 change: 1 addition & 0 deletions server/src/Core/Floor.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public function __construct(Point $start, public readonly int $width = 1, public
throw new GameException("Width and depth cannot be lower than or equal zero");
}
parent::__construct($start, new Point($start->x + $width, $start->y, $start->z + $depth), 'xz');
$this->setNormal(0, 90);
}

public function getY(): int
Expand Down
35 changes: 35 additions & 0 deletions server/src/Core/Plane.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ abstract class Plane extends SolidSurface
protected int $hitAntiForce = 25123;
protected int $hitAntiForceMargin = 10;
protected int $wallBangEdgeMarginDistance = 8;
protected int $normal;
protected Point2D $point2DStart;
protected Point2D $point2DEnd;

Expand All @@ -33,6 +34,40 @@ public function setHitAntiForce(int $hitAntiForceBody, int $hitAntiForceMargin,
$this->wallBangEdgeMarginDistance = max(0, $wallBangEdgeMarginDistance);
}

public function setNormal(int|float|null $angleHorizontal, int|float $angleVertical): static
{
$angleHorizontal = (int)Util::normalizeAngle($angleHorizontal ?? 0);
$angleHorizontal += $angleHorizontal > 180 ? -180 : 0;
$angleVertical = (int)Util::normalizeAngleVertical($angleVertical);
$this->normal = ($angleHorizontal << 8) | abs($angleVertical);
return $this;
}

/** @return array{int, int} **/
public function getNormal(): array
{
return [$this->normal >> 8, $this->normal & 0xFF];
}

/** @return array{float, float, float} **/
public function getNormalizedNormal(float $targetAngleHorizontal, float $targetAngleVertical, int $precision): array
{
[$normalHorizontal, $normalVertical] = $this->getNormal();
$deltaHorizontal = abs(Util::smallestDeltaAngle((int)round($targetAngleHorizontal), $normalHorizontal));
$deltaVertical = abs(Util::smallestDeltaAngle((int)round($targetAngleVertical), $normalVertical));
if ($deltaHorizontal < 90) {
$normalHorizontal = Util::normalizeAngle($normalHorizontal + 180);
}
if ($deltaVertical < 90) {
$normalVertical *= -1;
}

$normalVec = Util::movementXYZ($normalHorizontal, $normalVertical, $precision);
$precision = (float)$precision;
$normalVec = [$normalVec[0] / $precision, $normalVec[1] / $precision, $normalVec[2] / $precision];
return $normalVec;
}

public function getHitAntiForce(Point $point): int
{
if (!$this->penetrable) {
Expand Down
28 changes: 20 additions & 8 deletions server/src/Core/PlaneBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ final class PlaneBuilder
{
/** @var array<string,Point> */
private array $voxels = [];
/** @var array{?float,float} */
private array $voxelNormal;

/** @return list<Plane> */
public function create(Point $a, Point $b, Point $c, ?Point $d = null, ?float $jaggedness = null): array
Expand All @@ -32,10 +34,10 @@ public function fromTriangle(Point $a, Point $b, Point $c, float $voxelSizeDotTh

$planes = [];
foreach ($this->voxelizeTriangle($a, $b, $c, $voxelSize, $voxelThreshold, $matchSize) as $voxelPoint) {
$planes[] = new Wall($voxelPoint, true, $voxelSize, $voxelSize);
$planes[] = new Wall($voxelPoint, false, $voxelSize, $voxelSize);
$planes[] = new Wall($voxelPoint->clone()->addX($voxelSize), false, $voxelSize, $voxelSize);
$planes[] = new Floor($voxelPoint->clone()->addY($voxelSize), $voxelSize, $voxelSize);
$planes[] = (new Wall($voxelPoint, true, $voxelSize, $voxelSize))->setNormal($this->voxelNormal[0], $this->voxelNormal[1]);
$planes[] = (new Wall($voxelPoint, false, $voxelSize, $voxelSize))->setNormal($this->voxelNormal[0], $this->voxelNormal[1]);
$planes[] = (new Wall($voxelPoint->clone()->addX($voxelSize), false, $voxelSize, $voxelSize))->setNormal($this->voxelNormal[0], $this->voxelNormal[1]);
$planes[] = (new Floor($voxelPoint->clone()->addY($voxelSize), $voxelSize, $voxelSize))->setNormal($this->voxelNormal[0], $this->voxelNormal[1]);
}
return $planes;
}
Expand Down Expand Up @@ -173,7 +175,7 @@ private function rotatedWall(Point $start, Point $end, int $height, float $jagge
$width = abs($widthOnXAxis ? $previous->x - $current[0] : $previous->z - $current[2]);
$leftPoint = ($direction[1] === 1 || $widthOnXAxis ? $previous->clone() : new Point($current[0], $start->y, $current[2]));

$walls[] = new Wall($leftPoint, $widthOnXAxis, $width, $height);
$walls[] = (new Wall($leftPoint, $widthOnXAxis, $width, $height))->setNormal(90 + $angleH, 0);
$previous->set($current[0], $start->y, $current[2]);
$widthOnXAxis = !$widthOnXAxis;
}
Expand All @@ -189,6 +191,8 @@ private function ramp(Point $start, Point $end, int $width, float $jaggedness):
GameException::invalid(); // @codeCoverageIgnore
}
assert($angleV !== 0.0);
$normalH = $angleH + 90; // fixme: embrace jaggedness
$normalV = $angleV + 90; // fixme: embrace jaggedness

$planes = [];
$previous = $start->clone();
Expand Down Expand Up @@ -218,13 +222,13 @@ private function ramp(Point $start, Point $end, int $width, float $jaggedness):
$current = $points[$i - 1];
if ($isFloor) {
if ($wallWidthOnXAxis) {
$planes[] = new Floor($previous->clone(), $width, $current[2] - $previous->z);
$planes[] = (new Floor($previous->clone(), $width, $current[2] - $previous->z))->setNormal($normalH, $normalV);
} else {
$planes[] = new Floor($previous->clone(), $current[0] - $previous->x, $width);
$planes[] = (new Floor($previous->clone(), $current[0] - $previous->x, $width))->setNormal($normalH, $normalV);
}
} else {
$wallStart = ($stairsGoingUp ? $previous->clone() : new Point(...$current));
$planes[] = new Wall($wallStart, $wallWidthOnXAxis, $width, abs($current[1] - $previous->y));
$planes[] = (new Wall($wallStart, $wallWidthOnXAxis, $width, abs($current[1] - $previous->y)))->setNormal($normalH, $normalV);
}

$previous->set($current[0], $current[1], $current[2]);
Expand Down Expand Up @@ -288,6 +292,14 @@ private function stairs(Point $base, Point $top, int $topSize, int $stepHeight,
*/
private function voxelizeTriangle(Point $a, Point $b, Point $c, int $voxelSize, int $voxelThreshold, bool $matchTriangleSize): array
{
$u = [$b->x - $a->x, $b->y - $a->y, $b->z - $a->z];
$v = [$c->x - $a->x, $c->y - $a->y, $c->z - $a->z];
$this->voxelNormal = Util::worldAngle(new Point(
($u[1] * $v[2]) - ($u[2] * $v[1]),
($u[2] * $v[0]) - ($u[0] * $v[2]),
($u[0] * $v[1]) - ($u[1] * $v[0]),
));

$this->voxels = [];
$this->voxelizeLine($a, $b);
$this->voxelizeLine($b, $c);
Expand Down
2 changes: 2 additions & 0 deletions server/src/Core/Wall.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ public function __construct(

if ($widthOnXAxis) {
parent::__construct($start, new Point($start->x + $width, $start->y + $height, $start->z), 'xy');
$this->setNormal(0, 0);
} else {
parent::__construct($start, new Point($start->x, $start->y + $height, $start->z + $width), 'zy');
$this->setNormal(90, 0);
}
}

Expand Down
5 changes: 3 additions & 2 deletions server/src/Event/ThrowEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ public function process(int $tick): void
$pos->z = $z;
}

if (!$this->ball->hasCollision($pos)) {
$ballCollision = $this->ball->hasCollision($pos);
if ($ballCollision === false) {
continue;
}

Expand All @@ -162,7 +163,7 @@ public function process(int $tick): void
$this->setAngles($this->ball->getResolutionAngleHorizontal(), $this->ball->getResolutionAngleVertical());
$this->bounceCount++;
$this->velocity = $this->velocity / ($this->bounceCount > 4 ? $this->bounceCount : 1.5);
if ($this->velocity < 1) { // fixme some value based on velocity and gravity that will give lowest possible (angle 0.01/90) distance < 1
if ($ballCollision === null) {
$this->finishLanding($pos);
return;
}
Expand Down
50 changes: 29 additions & 21 deletions server/src/HitGeometry/BallCollider.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ class BallCollider
private Point $lastValidPosition;
private Point $lastExtremePosition;
private int $lastMoveY;
private bool $yGrowing;

private const int angleWorldPrecision = 1_000_000;
private const int angleRoundDecimalPlaces = 2;

public function __construct(
protected World $world,
Expand All @@ -29,49 +31,55 @@ public function __construct(
}

$this->candidate = new Point();
$this->yGrowing = $this->angleVertical > 0;
$this->lastMoveY = $this->angleVertical <=> 0;
$this->lastValidPosition = $origin->clone();
$this->lastExtremePosition = $origin->clone();
}

public function hasCollision(Point $point): bool
public function hasCollision(Point $point): ?bool
{
$moveX = $point->x <=> $this->lastValidPosition->x;
$moveY = $point->y <=> $this->lastValidPosition->y;
$moveZ = $point->z <=> $this->lastValidPosition->z;

$r = $this->radius;
$isCollision = false;
$planeCollision = null;
$this->candidate->set($point->x + $r * $moveX, $point->y + $r * $moveY, $point->z + $r * $moveZ);

if ($moveY !== 0 && $this->world->findFloorSquare($this->candidate, $r)) {
$this->angleVertical = Util::nearbyInt(Util::worldAngle($point, $this->lastExtremePosition)[1]);
$this->angleVertical = $moveY > 0 ? -abs($this->angleVertical) : abs($this->angleVertical);
$this->yGrowing = $this->angleVertical > 0;
$isCollision = true;
}

if ($moveX !== 0 && $this->world->checkXSideWallCollision($this->candidate, 2 * $r, $r)) {
$this->angleHorizontal = Util::normalizeAngle(360 - $this->angleHorizontal);
$isCollision = true;
} elseif ($moveZ !== 0 && $this->world->checkZSideWallCollision($this->candidate, 2 * $r, $r)) {
$this->angleHorizontal = Util::normalizeAngle(360 - $this->angleHorizontal + 180);
$isCollision = true;
if ($moveY !== 0 && $planeCollision = $this->world->findFloorSquare($this->candidate, $r)) {
} elseif ($moveX !== 0 && $planeCollision = $this->world->checkXSideWallCollision($this->candidate, 2 * $r, $r)) {
} elseif ($moveZ !== 0 && $planeCollision = $this->world->checkZSideWallCollision($this->candidate, 2 * $r, $r)) {
}

if ($isCollision) {
if ($moveY !== 0 && $this->yGrowing === false && $this->angleVertical > 0 && ($moveX !== 0 || $moveZ !== 0)) {
$this->angleVertical = min(-10, Util::nearbyInt(Util::worldAngle($point, $this->lastExtremePosition)[1]));
if ($planeCollision !== null) {
if ($planeCollision->getNormal()[1] !== 0) {
$this->angleVertical = Util::worldAngle($point, $this->lastExtremePosition)[1];
}
$precision = self::angleWorldPrecision;
$normalVec = $planeCollision->getNormalizedNormal($this->angleHorizontal, $this->angleVertical, $precision);
$directionVec = Util::movementXYZ($this->angleHorizontal, $this->angleVertical, $precision);
$doubleDotProduct = 2 * ($directionVec[0] * $normalVec[0] + $directionVec[1] * $normalVec[1] + $directionVec[2] * $normalVec[2]);
assert($doubleDotProduct <= 0);
if ($doubleDotProduct == 0) {
return null;
}
$reflectionVec = [
Util::nearbyInt($directionVec[0] - ($doubleDotProduct * $normalVec[0])),
Util::nearbyInt($directionVec[1] - ($doubleDotProduct * $normalVec[1])),
Util::nearbyInt($directionVec[2] - ($doubleDotProduct * $normalVec[2])),
];

$this->candidate->setFromArray($reflectionVec);
[$h, $v] = Util::worldAngle($this->candidate);
$this->angleHorizontal = round($h ?? 0, self::angleRoundDecimalPlaces);
$this->angleVertical = round($v, self::angleRoundDecimalPlaces);
$this->lastExtremePosition->setFrom($point);
return true;
}

if ($moveY !== 0 && $this->lastMoveY !== $moveY) {
$this->lastMoveY = $moveY;
$this->lastExtremePosition->setFrom($point);
$this->yGrowing = $moveY === 1;
}

$this->lastValidPosition->setFrom($point);
Expand Down
64 changes: 32 additions & 32 deletions server/src/Map/DefaultMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -6795,52 +6795,52 @@ public function __construct()

// t spawn walls.001
$add(
new Point(5871, 1210, 1068),
new Point(5871, 1210, 1232),
new Point(5871, 1960, 1232),
new Point(5871, 1960, 1068),
new Point(5867, 1210, 1068),
new Point(5867, 1210, 1222),
new Point(5867, 1960, 1222),
new Point(5867, 1960, 1068),
);
$add(
new Point(5871, 1960, 1232),
new Point(5871, 1210, 1232),
new Point(5015, 1210, 1232),
new Point(5015, 1960, 1232),
new Point(5867, 1960, 1222),
new Point(5867, 1210, 1222),
new Point(5003, 1210, 1222),
new Point(5003, 1960, 1222),
);
$add(
new Point(5015, 1960, 1232),
new Point(5015, 1210, 1232),
new Point(5015, 1210, 1404),
new Point(5015, 1960, 1404),
new Point(5003, 1960, 1222),
new Point(5003, 1210, 1222),
new Point(5003, 1210, 1361),
new Point(5003, 1960, 1361),
);
$add(
new Point(4809, 1960, 1404),
new Point(4809, 1210, 1404),
new Point(4809, 1210, 1080),
new Point(4809, 1960, 1080),
new Point(4811, 1960, 1361),
new Point(4811, 1210, 1361),
new Point(4811, 1210, 1080),
new Point(4811, 1960, 1080),
);
$add(
new Point(5015, 1960, 1368),
new Point(5015, 1780, 1368),
new Point(5015, 1780, 2062),
new Point(5015, 1960, 2062),
new Point(5003, 1960, 1368),
new Point(5003, 1780, 1368),
new Point(5003, 1780, 2062),
new Point(5003, 1960, 2062),
);
$add(
new Point(4809, 1780, 1368),
new Point(4809, 1960, 1368),
new Point(4809, 1960, 2062),
new Point(4809, 1780, 2062),
new Point(4811, 1780, 1368),
new Point(4811, 1960, 1368),
new Point(4811, 1960, 2062),
new Point(4811, 1780, 2062),
);
$add(
new Point(4809, 1781, 1327),
new Point(5015, 1781, 1327),
new Point(5015, 1781, 2044),
new Point(4809, 1781, 2044),
new Point(4811, 1781, 1327),
new Point(5003, 1781, 1327),
new Point(5003, 1781, 2044),
new Point(4811, 1781, 2044),
);
$add(
new Point(5015, 1960, 1404),
new Point(5015, 1210, 1404),
new Point(4810, 1210, 1404),
new Point(4810, 1960, 1404),
new Point(5003, 1960, 1361),
new Point(5003, 1210, 1361),
new Point(4811, 1210, 1361),
new Point(4811, 1960, 1361),
);

// t spawn walls.002
Expand Down
Loading