- TypeScript 58.4%
- C 16.9%
- PLpgSQL 7.9%
- JavaScript 6.9%
- PowerShell 3.3%
- Other 6.6%
|
|
||
|---|---|---|
| .agents/skills/zedwatch-api | ||
| .forgejo/workflows | ||
| e2e | ||
| helper_scripts | ||
| markdown | ||
| mod | ||
| mod_expansion | ||
| scripts/e2e | ||
| webapp | ||
| .gitattributes | ||
| .gitignore | ||
| .ignore | ||
| 00_build_deploy_start-server_expansion.bat | ||
| 00_build_deploy_start-server_vanilla.bat | ||
| 1_build_pbo_expansion.bat | ||
| 1_build_pbo_vanilla.bat | ||
| 2_deploy_mod_expansion.bat | ||
| 2_deploy_mod_vanilla.bat | ||
| AGENTS.md | ||
| convert_wiki_to_md.py | ||
| convoy_classnames.txt | ||
| EXPANSION_TRACKING_OPPORTUNITIES.md | ||
| extract_event_classnames.py | ||
| mod.cpp | ||
| README.md | ||
| server.toml | ||
| start_server.bat | ||
| test_settings_api.sh | ||
| zedwatch-api-guide.md | ||
VertexWatch
VertexWatch is a DayZ statistics mod with an API and web dashboard. The core mod records vanilla events. The companion mod records DayZ Expansion events.
Components
mod/: Core Enforce Script source.mod_expansion/: DayZ Expansion source.webapp/backend/: Express and TypeScript API.webapp/frontend/: React and Vite dashboard.webapp/backend/database/schemas/: PostgreSQL schemas.@VertexWatch/and@VertexWatch-Expansion/: Generated PBO output. These directories are not tracked.
Development targets
| System | Role | Path |
|---|---|---|
| Coding VM | Source editing and web application work | Repository checkout |
STEPONE-LAPTOP |
PBO creation and DayZ testing | D:\dayz_stuff\VertexWatch |
STEPONE-LAPTOP |
DayZ test server | D:\dayz_stuff\test_server |
STEPONE-LAPTOP |
DayZ Tools | D:\SteamLibrary\steamapps\common\DayZ Tools |
STEPONE-LAPTOP |
DayZ client | D:\SteamLibrary\steamapps\common\DayZ |
STEPONE-LAPTOP |
PBO signing keys | D:\dayz_stuff\signing_keys |
| Linux PC | DayZ test client | /mnt/data/SteamLibrary/steamapps/common/DayZ |
Do not build PBOs on Linux. Use the Windows laptop because Addon Builder and the extracted DayZ project data are installed there.
Windows project drive
DayZ Tools maps a physical directory to a virtual drive letter. Keep the extracted game data outside the repository at D:\DayZFiles. Map P: to that directory. Use the repository's ignored P_Drive path only as a junction to the same physical directory.
- Place the Windows checkout at
D:\dayz_stuff\VertexWatch. - Create
D:\DayZFilesif it does not exist. - Open DayZ Tools from Steam.
- Open Settings.
- Clear Default for the Project Drive path.
- Set the Project Drive path to
D:\DayZFiles. - Set the drive letter to
P:and apply the settings. - Select Tools > Extract Game Data and wait for it to finish.
- Open an Administrator Command Prompt and create the repository and source junctions:
mklink /J "D:\dayz_stuff\VertexWatch\P_Drive" "D:\DayZFiles"
mklink /J "D:\DayZFiles\VertexWatch" "D:\dayz_stuff\VertexWatch\mod"
mklink /J "D:\DayZFiles\VertexWatch_Expansion" "D:\dayz_stuff\VertexWatch\mod_expansion"
The resulting paths are:
D:\DayZFiles Physical extracted data
P:\ Virtual drive mapped to D:\DayZFiles
repository\P_Drive Junction to D:\DayZFiles
P:\VertexWatch Junction to repository\mod
P:\VertexWatch_Expansion Junction to repository\mod_expansion
P_Drive is ignored by Git. Never commit extracted game data or the junctions. Keeping D:\DayZFiles outside the checkout prevents a repository replacement from deleting the extracted data.
This setup follows Bohemia Interactive's DayZ project-drive procedure.
Build, deploy, and test
Run these commands from D:\dayz_stuff\VertexWatch on the laptop.
The build scripts require VertexWatch.biprivatekey and VertexWatch.bikey in D:\dayz_stuff\signing_keys. Keep the private key outside Git. Back it up securely because all future PBO builds must use the same key.
Create the signing key once if it does not exist:
mkdir D:\dayz_stuff\signing_keys
pushd D:\dayz_stuff\signing_keys
"D:\SteamLibrary\steamapps\common\DayZ Tools\Bin\DsUtils\DSCreateKey.exe" VertexWatch
popd
Build the core mod:
1_build_pbo_vanilla.bat
Build the core and Expansion mods:
1_build_pbo_expansion.bat
Deploy without starting the server:
2_deploy_mod_vanilla.bat
2_deploy_mod_expansion.bat
Start the test server after deployment:
start_server.bat vanilla
start_server.bat expansion
Run the complete workflow:
00_build_deploy_start-server_vanilla.bat
00_build_deploy_start-server_expansion.bat
The scripts use these verified laptop paths:
- Addon Builder:
D:\SteamLibrary\steamapps\common\DayZ Tools\Bin\AddonBuilder\AddonBuilder.exe - Server:
D:\dayz_stuff\test_server - Client mod directory:
D:\SteamLibrary\steamapps\common\DayZ\!Workshop
The build signs each PBO with VertexWatch.biprivatekey. The output includes each .bisign file and the public Keys\VertexWatch.bikey file. Deployment installs the public key in the server keys directory and verifies the deployed files.
BattlEye RCON
The test server exposes BattlEye RCON on UDP port 2305. The public endpoint 205.147.200.16:2305 forwards UDP traffic to 192.168.20.97:2305. A TCP forward does not provide RCON connectivity.
Keep BEServer_x64.dll and BEServer_x64.cfg in this directory:
D:\dayz_stuff\test_server\battleye
The configuration must define RConPassword, RConPort 2305, and RestrictRCon 0. Do not copy the password into Git or command output.
Use the absolute BattlEye directory in start_server.bat:
set "BE_PATH=%SERVER_ROOT%\battleye"
Pass it to DayZ with -BEpath=%BE_PATH%. A relative battleye path can resolve below the profiles directory. BattlEye then loads a different DLL location and does not bind UDP port 2305 from the intended configuration.
After each server restart, verify the loaded module and UDP listener in PowerShell:
$dayzProcess = Get-Process -Name DayZServer_x64
$dayzProcess.Modules | Where-Object ModuleName -Like 'BEServer*' | Select-Object FileName
Get-NetUDPEndpoint -OwningProcess $dayzProcess.Id | Sort-Object LocalPort
The module path must be D:\dayz_stuff\test_server\battleye\BEServer_x64.dll. The UDP endpoint list must contain 2305.
The setup RCON test requires the BattlEye RConPassword. An empty password returns a validation error before any network connection starts.
Linux test client
Copy unpublished test builds into the DayZ root. Place each mod directory beside the game Addons directory:
/mnt/data/SteamLibrary/steamapps/common/DayZ/@VertexWatch
/mnt/data/SteamLibrary/steamapps/common/DayZ/@VertexWatch-Expansion
Do not copy mod PBOs into the game Addons directory. Use Mods > Add local mod in the DayZ launcher. Load only @VertexWatch for vanilla mode. Load both local VertexWatch mods for Expansion mode.
After each build, replace the complete local mod directory. Keep each PBO with its matching .bisign file. Error 0x00040074 can mean the client PBO is unsigned, its signature does not match, or the server lacks VertexWatch.bikey.
Test checks
- Confirm the PBO timestamp changed after the build.
- Confirm each PBO has a matching
.bisignfile. - Confirm the deployed PBO, signature, and public key match the build output.
- Start the required server mode.
- Inspect the server RPT for script compile errors and VertexWatch initialization.
- Join with a client that has the same signed PBO and exercise the changed event path.
- Confirm the expected event reaches the API or persists in the recovery queue.
Addon Builder packages scripts but does not compile Enforce Script. A successful PBO build is not sufficient. Start the server and confirm that the Game, World, and Mission modules compile.
Force Sync performs two separate actions. It saves a local player JSON file and queues a player_stats_update event. A new JSON file proves only the local save. Confirm API delivery from a successful HTTP result. If the backend is unavailable, confirm that the batch exists under profiles\VertexWatch\data\pending_events.
The generated configuration leaves APIKey empty. Generate a server-bound key in the dashboard, set it in the server configuration, and restart the server. The mod does not print the key or store it in pending and debug batch files. The DayZ REST client sends it in the JSON request body because it cannot set a custom authorization header.
Automated E2E gates
Validate the capability catalog:
scripts/e2e/run.sh catalog
Run the local backend and frontend campaign:
scripts/e2e/run.sh local
Test existing immutable production images with an isolated PostgreSQL volume:
scripts/e2e/run.sh production-stack \
git.step1.ro/stanta/vertexwatch/backend:sha-<full-commit-sha> \
git.step1.ro/stanta/vertexwatch/frontend:sha-<full-commit-sha>
Each production image tag must contain sha- followed by the full 40-character lowercase hexadecimal commit SHA.
The backend and frontend tags must use the same SHA. Run the command from a clean checkout of that exact revision.
The production campaign first checks the fresh setup flow. It then creates isolated operator sessions and event fixtures. Chromium verifies session scope, Expansion gates, persisted event views, API outage errors, and API recovery. The campaign stops only its own temporary backend container for the outage check.
Build, deploy, and start a clean committed revision on STEPONE-LAPTOP:
scripts/e2e/run.sh windows-live vanilla
scripts/e2e/run.sh windows-live expansion
The Windows checkout must be clean and at the same full Git revision as the local checkout. The command refuses an existing DayZ server or occupied UDP port. It verifies fresh signed build outputs and server and client deployment hashes. It also verifies the server process, BattlEye, UDP listeners, current-run logs, reconnect status, client files, and public API health.
The client preflight verifies the signed client files and required Workshop dependencies. It does not launch DayZ through OpenSSH. Launch the client from the interactive Windows session, join the test server, and perform each gameplay input listed in the capability catalog.
Set VERTEXWATCH_E2E_RUN_ID to a unique value when a stable run name is required. Each campaign writes run.json, steps.jsonl, summary.json, and step logs under e2e-artifacts/<run-id>/. The directory is local and is not tracked by Git. A failed campaign stops at the first failed gate and records that step in summary.json.
The production-stack command uses the existing isolated runtime test. It does not use or delete the deployed PostgreSQL volume. The Windows campaign does not clean server profiles, stop an existing server, or automate keyboard and mouse input.
Record campaign findings in e2e/findings.json. A verified finding must identify its fix revision, verification run, regression step, and command. Check whether any major finding remains:
scripts/e2e/run.sh major-gate
The final completion gate requires every capability to reach its target. It also requires one clean, passed, committed run-evidence manifest for each target capability. All manifests must identify the same tested revision.
scripts/e2e/run.sh completion-gate \
--revision <full-commit-sha> \
--run-evidence e2e/evidence/<run-id>/<capability-manifest>.json
Repeat --run-evidence for each target capability.
Set each manifest subject type to capability and its subject ID to the capability ID. Use <capability-id>@<target-level>:<step> as each regression test name. The regression step and command must match the catalog evidence record.
Web application
The web stack runs independently of the Windows PBO workflow. See webapp/README.md for setup and validation.
Active documentation
- This file defines the supported development workflow.
AGENTS.mdcontains project-specific coding constraints.webapp/README.mddescribes the web stack.markdown/AUTHENTICATION_ARCHITECTURE.mddefines the web authentication boundary.