Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
6e48f0d
Add submodules for OPResource + OPDB
clouths Mar 15, 2026
5af7381
Add container support using linux containers, add migration script fo…
clouths Mar 15, 2026
26512e6
Update mssql-tools to a more recent version (18) to fix migration, up…
clouths Mar 16, 2026
0689ed4
Fix comment in .env.local, remove preparePatch from the migration scr…
clouths Mar 16, 2026
1073ced
Move db persistent storage into a docker volume
clouths Mar 17, 2026
0fa79c6
Most fo the refactor from System.Drawing to SkiaSharp is done.
clouths Mar 21, 2026
decdcfd
Fix migration order of copy to ensure the generated perpetuum.ini is …
clouths Mar 21, 2026
67f8314
Add DefinitionConfig refactor
clouths Mar 21, 2026
b31e821
Update db submodule + migration script to use P34 and P35 full sql files
clouths Mar 21, 2026
1eba63b
Update port mapping to allow more ports for the server to fix black s…
clouths Mar 24, 2026
984ed0a
Fix port mapping, defined extra SERVER_PORTS for port range to forewa…
clouths Mar 24, 2026
0bf693c
Disable EnlistTransactaction
clouths Mar 25, 2026
c19dedf
Add documentation in the readme for how to setup the containers, make…
clouths Mar 28, 2026
17c38fa
Update db image to use mssql-2025
clouths Mar 28, 2026
afe07ea
Fix WithCanvas extension to preserve the Bitmap using SKCanvas instea…
clouths Mar 28, 2026
cba0e76
Fix font.size to use Size property
clouths Mar 28, 2026
8a40610
Fix pixel check to use Alpha instead of the Luminance
clouths Mar 29, 2026
005b8ce
Fix typo, replace usage of manual creation of Area with size.ToArea()…
clouths Mar 29, 2026
14a1e65
Fix PresenceConfiguration to use the Configuration size instead of th…
clouths Mar 29, 2026
c1a425d
Merge develop branch into linux+containerize
clouths Aug 30, 2026
a10dcd8
Merge branch 'develop' of github.com:OpenPerpetuum/PerpetuumServer2 i…
clouths Aug 30, 2026
3adb6bf
Try fix merge of FakeDb.cs causing ci build error
clouths Aug 30, 2026
d8c5168
Add make commands to run tests (unit+integration) using the docker co…
clouths Aug 30, 2026
0af068c
Add Live_36 to migration, all integration tests passes now
clouths Aug 31, 2026
8256cf6
Add unit and integration tests
clouths Aug 31, 2026
a75e424
Merge branch 'develop' of github.com:OpenPerpetuum/PerpetuumServer2 i…
clouths Sep 2, 2026
4953b3d
Update db submodule
clouths Sep 2, 2026
87cd9d8
Add CI to run tests with docker
clouths Sep 2, 2026
2d884d9
Revert "Add CI to run tests with docker" for now, I'll create a new P…
clouths Sep 2, 2026
c9d5ec0
perf(migration): automate patch discovery and add snapshot caching
clouths Sep 4, 2026
da38e09
perf(server): add SIMD acceleration, terrain metadata, and idle throt…
clouths Sep 4, 2026
96d4826
fix(data): share connection within TransactionScope to prevent MSDTC …
clouths Sep 4, 2026
bb0d416
Update db submodule
clouths Sep 4, 2026
b8911a5
Fix an issue with SQL server when waking up from sleep using 1-core@1…
clouths Sep 5, 2026
54346f3
Merge branch 'develop' of github.com:OpenPerpetuum/PerpetuumServer2 i…
clouths Sep 11, 2026
b7ae627
Add CLI client, developer tooling, smoke tests, and terrain fixes
clouths Sep 17, 2026
7c495b5
Merge branch 'develop' of github.com:OpenPerpetuum/PerpetuumServer2 i…
clouths Sep 22, 2026
94ab729
Add CI for unit and integration tests
clouths Sep 22, 2026
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
52 changes: 52 additions & 0 deletions .env.local
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Environment for local development.
# Compatible with podman/docker with linux containers.

# Database settings
DB_PASSWORD="l3<Nv2-QIat4YK*ydt#u-^+VAAVVdytL"

# Uncomment to force a reset of the DB + run migration
# FORCE_MIGRATION="true"

# Port mapping setting
# Here you can modify the default values
# Only the SERVER and the ASSET ports are required
# The SERVER port is used to allow access to the server when you connect your client
# The SERVER ports is a range that needs to start from the SERVER_PORT + ~300
# Note Without proper SERVER_PORTS, the client will have a black screen when entering a zone
# The ASSET port is used by the client to fetch assets when connecting to the server
# The DB port is optional, used for debugging
SERVER_PORT=17700
SERVER_PORTS=17700-17900
ASSET_PORT=16999
DB_PORT=16998

ASSET_URL="http://localhost:${ASSET_PORT}"

GAME_ROOT="/data"

# Original data directory from Stream: Perpetuum Dedicated Server installer
PERPETUUM_DATA="./perpetuum-data"

# User-provided additional map layers assets
# TODO: Move to a guide/readme
# Required if you want to load the server with Gamma Islands
# Download URL: https://drive.google.com/file/d/1qDjPHbTSdal_aKN6SvYC_EoGW-COkwhJ/view?usp=sharing
# sha256sum:
# f4d42d5dbf6a61d2d7730b2058f5d2bb80a63d0994bbc84b906f19441bb8e425 GAMMA_LAYERS_2021_10_17_P26.rar
CUSTOM_LAYERS="./custom-layers"

# Connection string: Specific changes made to work on linux:
# - Added "sa" user, password to use SQL server authentication;
# - Added TrustServerCertificate=True to trust the self-signed certificate
# - Changed Server to the name of the database container: "db"
# - Removed due to incompatibility on linux: "Connection Reset=True;"
# - Removed Trusted_Connection since we don't want to use Windows Authentication (SPPI)
CONNECTION_STRING="Server=db;Database=perpetuumsa;User Id=sa;Password=${DB_PASSWORD};TrustServerCertificate=True;Pooling=True;Connection Timeout=30;Connection Lifetime=260;Min Pool Size=20;Max Pool Size=60;"


RUNTIME_IDENTIFIER="linux-x64" # TODO env for windows as well (windows-x64)
DISTRIBUTED_TRANSACTIONS=false # .NET on linux does not support Distributed Transactions

# Database memory limit config.
# Set to 4096 for local dev to prevent post-sleep spin loops; 8192+ for production
DB_MEMORY_LIMIT_MB=4096
77 changes: 77 additions & 0 deletions .github/actions/setup-test-data/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: 'Setup Perpetuum Test Data'
description: 'Caches, downloads, or initializes Perpetuum test data and custom gamma layers'

inputs:
download-data:
description: 'Whether to download full server and gamma data (required for integration tests)'
required: false
default: 'false'

runs:
using: 'composite'
steps:
- name: Cache Perpetuum Data and Custom Layers
if: inputs.download-data == 'true'
id: cache-data
uses: actions/cache@v4
with:
path: |
perpetuum-data
custom-layers
key: perpetuum-test-data-v2

- name: Install dependencies for data download
if: inputs.download-data == 'true' && steps.cache-data.outputs.cache-hit != 'true'
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y p7zip-full lib32gcc-s1 curl python3-venv

- name: Download Perpetuum Dedicated Server data (SteamCMD)
if: inputs.download-data == 'true' && steps.cache-data.outputs.cache-hit != 'true'
shell: bash
run: |
mkdir -p /tmp/steamcmd
curl -sqL "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" | tar zxvf - -C /tmp/steamcmd
/tmp/steamcmd/steamcmd.sh +@sSteamCmdForcePlatformType windows +login anonymous +app_info_update 1 +quit || true
for attempt in 1 2 3; do
echo "SteamCMD download attempt $attempt..."
if /tmp/steamcmd/steamcmd.sh +@sSteamCmdForcePlatformType windows +force_install_dir /tmp/perp_server +login anonymous +app_update 693060 validate +quit; then
break
fi
sleep 5
done
mkdir -p perpetuum-data
if [ -f /tmp/perp_server/perpetuumserver_setup.exe ]; then
7z x /tmp/perp_server/perpetuumserver_setup.exe -o/tmp/perp_extracted -y
cp -r /tmp/perp_extracted/data/* ./perpetuum-data/
elif [ -d /tmp/perp_server/data ]; then
cp -r /tmp/perp_server/data/* ./perpetuum-data/
fi
chmod -R 777 ./perpetuum-data

- name: Download custom gamma layers from Google Drive
if: inputs.download-data == 'true' && steps.cache-data.outputs.cache-hit != 'true'
shell: bash
run: |
python3 -m venv /tmp/gdown-env
/tmp/gdown-env/bin/pip install gdown
mkdir -p custom-layers
/tmp/gdown-env/bin/gdown "https://drive.google.com/uc?id=1Xp0T1K57Pv-vjgmpXMG8Iea_ec0bWYR4" -O /tmp/gamma_layers.rar || true
if [ -f /tmp/gamma_layers.rar ]; then
7z x /tmp/gamma_layers.rar -o./custom-layers -y || true
fi
chmod -R 777 ./custom-layers || true

- name: Ensure correct file permissions and directories
shell: bash
run: |
mkdir -p perpetuum-data custom-layers
chmod -R 777 ./perpetuum-data ./custom-layers || true
if [ "${{ inputs.download-data }}" = "true" ]; then
if [ ! -f "./perpetuum-data/database/perpetuumsa.bak" ]; then
echo "ERROR: perpetuumsa.bak is missing from ./perpetuum-data/database/"
exit 1
fi
echo "Perpetuum test data successfully verified."
fi
52 changes: 52 additions & 0 deletions .github/workflows/docker-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Docker Compose Tests

on:
push:
branches: [ "develop" ]
pull_request:
branches: [ "develop" ]

jobs:
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest

steps:
- name: Checkout repository and submodules
uses: actions/checkout@v4
with:
submodules: recursive

- name: Setup environment and directories
uses: ./.github/actions/setup-test-data
with:
download-data: 'false'

- name: Run Unit Tests
run: make test-unit

- name: Docker Compose Teardown
if: always()
run: make delete

integration-tests:
name: Integration Tests
runs-on: ubuntu-latest

steps:
- name: Checkout repository and submodules
uses: actions/checkout@v4
with:
submodules: recursive

- name: Setup Perpetuum test data
uses: ./.github/actions/setup-test-data
with:
download-data: 'true'

- name: Run Integration Tests
run: make test-integration

- name: Docker Compose Teardown
if: always()
run: make delete
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ src/Perpetuum.ServerService2/data/layers/
src/Perpetuum.ServerService2/data/logs/
bin/
Releases/

custom-assets/

# User-provided additional map layers assets
custom-layers/

# Original directory folder from Stream: Perpetuum Dedicated Server installer
perpetuum-data/

.claude/settings.local.json
.planning/
*.log
Expand Down
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[submodule "db"]
path = db
url = https://github.com/OpenPerpetuum/OPDB.git
[submodule "asset"]
path = asset
url = https://github.com/OpenPerpetuum/OPResource.git
3 changes: 2 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ The `docs/` directory is the authoritative source of truth.
## Project Structure
- `docs/codebase/STRUCTURE.md`

## Testing Constraints
## Testing & Coverage
- `docs/codebase/TESTING.md`
- `docs/codebase/COVERAGE.md`

---

Expand Down
58 changes: 58 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
help: ## Show this help message
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "%-20s %s\n", $$1, $$2}'

up: ## Create and start the containers
./script/compose.sh up -d --build --remove-orphans --wait

start: ## Start the containers
./script/compose.sh start

stop: ## Stop the containers
./script/compose.sh stop

down: ## Stop and delete the containers
./script/compose.sh down

delete: ## Stop and delete the containers, also delete the volumes (openperpetuum-data, openperpetuum-db)
./script/compose.sh down -v

restart: down up ## Stop, delete and start the containers

reset: ## Stop, delete and start the containers with forced migration
FORCE_MIGRATION=true $(MAKE) restart

clean-cache: ## Delete migration snapshot cache to force full re-migration on next start
rm -f ./perpetuum-data/database/perpetuumsa_migrated.bak ./perpetuum-data/database/perpetuumsa_migrated.hash 2>/dev/null || true

log-asset: ## Follow asset logs
./script/compose.sh logs asset -f

log-db: ## Follow db logs
./script/compose.sh logs db -f

log-server: ## Follow server logs
./script/compose.sh logs server -f

test-unit: ## Run the unit test tier (2) in the test container, no database required
./script/compose.sh --profile test run --no-deps --build --rm test dotnet test src/Perpetuum.Tests/Perpetuum.Tests.csproj -c Release -p:Platform=x64 --no-build

test-integration: ## Run the integration test tier (3) in the test container, against the live database, bringing up db + migration first (migration is idempotent and exits when already done)
./script/compose.sh up -d db --wait
./script/compose.sh up migration
./script/compose.sh --profile test run --build --rm test dotnet test src/Perpetuum.Tests.Integration/Perpetuum.Tests.Integration.csproj -c Release -p:Platform=x64 --no-build

test-smoke: ## Run the end-to-end smoke test (tier 1) against the docker server stack
./script/smoke-test.sh

check-assets: ## Verify presence and integrity of assets listed in manifest
python3 ./script/check_assets.py --check-sizes

cli: ## Run the CLI client in a container (connect, login, character select)
./script/cli.sh $(ARGS)

create-account: ## Create a new account with optional admin privileges (interactive or EMAIL=... PASSWORD=... ADMIN=true/false)
./script/create-account.sh $(ARGS)

.PHONY: help up start stop down delete restart reset clean-cache log-asset log-db log-server test-smoke test-unit test-integration check-assets extract-models cli create-account


9 changes: 8 additions & 1 deletion PerpetuumServer2.sln
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.11.35431.28
Expand Down Expand Up @@ -27,6 +27,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Perpetuum.Tests", "src\Perp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Perpetuum.Tests.Integration", "src\Perpetuum.Tests.Integration\Perpetuum.Tests.Integration.csproj", "{ABE8E004-66D6-4D40-AEBF-3CFBD041E29B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Perpetuum.CliClient", "src\Perpetuum.CliClient\Perpetuum.CliClient.csproj", "{B9D1A2E3-4F5C-6D7E-8F9A-0B1C2D3E4F5A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Expand Down Expand Up @@ -77,6 +79,10 @@ Global
{ABE8E004-66D6-4D40-AEBF-3CFBD041E29B}.Debug|x64.Build.0 = Debug|x64
{ABE8E004-66D6-4D40-AEBF-3CFBD041E29B}.Release|x64.ActiveCfg = Release|x64
{ABE8E004-66D6-4D40-AEBF-3CFBD041E29B}.Release|x64.Build.0 = Release|x64
{B9D1A2E3-4F5C-6D7E-8F9A-0B1C2D3E4F5A}.Debug|x64.ActiveCfg = Debug|x64
{B9D1A2E3-4F5C-6D7E-8F9A-0B1C2D3E4F5A}.Debug|x64.Build.0 = Debug|x64
{B9D1A2E3-4F5C-6D7E-8F9A-0B1C2D3E4F5A}.Release|x64.ActiveCfg = Release|x64
{B9D1A2E3-4F5C-6D7E-8F9A-0B1C2D3E4F5A}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -93,6 +99,7 @@ Global
{A7D1E3C5-9F4B-42E8-8A6C-B5D7F1E9C2A0} = {0BC991A1-133C-49ED-A141-80E2A906898B}
{C8C45427-6E5C-496C-9446-0817EADC05DD} = {0BC991A1-133C-49ED-A141-80E2A906898B}
{ABE8E004-66D6-4D40-AEBF-3CFBD041E29B} = {0BC991A1-133C-49ED-A141-80E2A906898B}
{B9D1A2E3-4F5C-6D7E-8F9A-0B1C2D3E4F5A} = {0BC991A1-133C-49ED-A141-80E2A906898B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {91874B60-30B0-4B48-9155-370E40BC70E6}
Expand Down
Loading
Loading