From d7c36ffc0754c936e12b5dec282f5e1cce7deacf Mon Sep 17 00:00:00 2001 From: indifferentketchup Date: Thu, 30 Apr 2026 20:42:19 +0000 Subject: [PATCH] Add ProjectZomboidUserLog (user.txt) Two row variants: low-level Connection events and player join/disconnect events. The LINE regex accepts both shapes; analysers route via CONNECTION (action/index/guid/id) and PLAYER_EVENT (steamid/player/event) named-group regexes. Detectors: filename match plus content signatures on either variant. --- .../ProjectZomboid/ProjectZomboidUserLog.php | 47 +++++++++++++++ src/Pattern/ProjectZomboid/UserPattern.php | 22 +++++++ .../ProjectZomboid/fixtures/user-minimal.txt | 9 +++ .../Log/ProjectZomboidUserLogTest.php | 58 +++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 src/Log/ProjectZomboid/ProjectZomboidUserLog.php create mode 100644 src/Pattern/ProjectZomboid/UserPattern.php create mode 100644 test/src/Games/ProjectZomboid/fixtures/user-minimal.txt create mode 100644 test/tests/Games/ProjectZomboid/Log/ProjectZomboidUserLogTest.php diff --git a/src/Log/ProjectZomboid/ProjectZomboidUserLog.php b/src/Log/ProjectZomboid/ProjectZomboidUserLog.php new file mode 100644 index 0000000..fe9e48d --- /dev/null +++ b/src/Log/ProjectZomboid/ProjectZomboidUserLog.php @@ -0,0 +1,47 @@ +setPattern('/_user\.txt$/') + ->setWeight(0.95), + (new WeightedSinglePatternDetector()) + ->setPattern('/^\[[^\]]+\] Connection (?:add|disconnect) index=\d+ guid=\d+/m') + ->setWeight(0.90), + (new WeightedSinglePatternDetector()) + ->setPattern('/^\[[^\]]+\] \d{17} "[^"]+" (?:attempting to join|allowed to join)/m') + ->setWeight(0.85), + ]; + } + + public function getTitle(): string + { + return "Project Zomboid User Log"; + } +} diff --git a/src/Pattern/ProjectZomboid/UserPattern.php b/src/Pattern/ProjectZomboid/UserPattern.php new file mode 100644 index 0000000..cadfd57 --- /dev/null +++ b/src/Pattern/ProjectZomboid/UserPattern.php @@ -0,0 +1,22 @@ +add|disconnect) index=(?\d+) guid=(?\d+) id=(?\d+|null)\.?$/'; + + public const string PLAYER_EVENT = '/^\[\d{2}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}\] (?\d{17}) "(?[^"]+)" (?.+?)\.?$/'; +} diff --git a/test/src/Games/ProjectZomboid/fixtures/user-minimal.txt b/test/src/Games/ProjectZomboid/fixtures/user-minimal.txt new file mode 100644 index 0000000..d7c96c1 --- /dev/null +++ b/test/src/Games/ProjectZomboid/fixtures/user-minimal.txt @@ -0,0 +1,9 @@ +[29-04-26 18:35:41.512] Connection add index=0 guid=144118788000000001 id=null. +[29-04-26 18:35:42.802] 76561198000000001 "Player1" attempting to join. +[29-04-26 18:35:42.804] 76561198000000001 "Player1" allowed to join. +[29-04-26 18:37:14.645] 76561198000000001 "Player1" attempting to join used queue. +[29-04-26 18:39:23.923] Connection disconnect index=0 guid=144118788000000001 id=76561198000000001. +[29-04-26 18:40:00.100] Connection add index=1 guid=144118788000000002 id=null. +[29-04-26 18:40:01.225] 76561198000000002 "Player2" attempting to join. +[29-04-26 18:40:01.500] 76561198000000002 "Player2" allowed to join. +[29-04-26 18:50:30.010] Connection disconnect index=1 guid=144118788000000002 id=76561198000000002. diff --git a/test/tests/Games/ProjectZomboid/Log/ProjectZomboidUserLogTest.php b/test/tests/Games/ProjectZomboid/Log/ProjectZomboidUserLogTest.php new file mode 100644 index 0000000..55a606a --- /dev/null +++ b/test/tests/Games/ProjectZomboid/Log/ProjectZomboidUserLogTest.php @@ -0,0 +1,58 @@ +setLogFile(new PathLogFile($this->fixturePath())); + $log->parse(); + + $this->assertCount(9, $log->getEntries()); + } + + public function testConnectionRegexExtractsAddVariant(): void + { + $line = '[29-04-26 18:35:41.512] Connection add index=0 guid=144118788000000001 id=null.'; + $this->assertSame(1, preg_match(UserPattern::CONNECTION, $line, $m)); + $this->assertSame('add', $m['action']); + $this->assertSame('null', $m['id']); + } + + public function testConnectionRegexExtractsDisconnectVariant(): void + { + $line = '[29-04-26 18:39:23.923] Connection disconnect index=0 guid=144118788000000001 id=76561198000000001.'; + $this->assertSame(1, preg_match(UserPattern::CONNECTION, $line, $m)); + $this->assertSame('disconnect', $m['action']); + $this->assertSame('76561198000000001', $m['id']); + } + + public function testPlayerEventRegexExtracts(): void + { + $line = '[29-04-26 18:35:42.802] 76561198000000001 "Player1" attempting to join.'; + $this->assertSame(1, preg_match(UserPattern::PLAYER_EVENT, $line, $m)); + $this->assertSame('Player1', $m['player']); + $this->assertSame('attempting to join', $m['event']); + } + + public function testDetectiveDispatchesByContent(): void + { + $detective = (new Detective()) + ->setLogFile(new PathLogFile($this->fixturePath())) + ->addPossibleLogClass(ProjectZomboidUserLog::class); + + $this->assertInstanceOf(ProjectZomboidUserLog::class, $detective->detect()); + } +}