From 690f690faa12c0903e9bc18e3aa43d5e364862a7 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 2 Sep 2026 21:43:38 -0700 Subject: [PATCH 1/4] Publish: Game server orchestration --- _notes/game-server-orchestration.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/_notes/game-server-orchestration.md b/_notes/game-server-orchestration.md index cb1f32f..b9f9813 100644 --- a/_notes/game-server-orchestration.md +++ b/_notes/game-server-orchestration.md @@ -2,21 +2,20 @@ title: Game server orchestration --- -To me, *game server orchestration* is solving the problem of provisioning dedicated game servers in a scalable manner for a multiplayer game. +Game server orchestration is solving the problem of provisioning dedicated game servers in a scalable manner for a multiplayer game. -When I added dedicated server builds through [[PurrNet]] for [[Resonance]], a cyberpunk-themed first person shooter, I did not realize the work I was giving myself later when it came to launching the game. Pre-rewrite, the [vibe-coded prototype](https://github.com/brendan-ch/ResonanceServerOrchestrator/tree/2d71f0491830dfa91d7887c208c14c52d6513202) I created comes nowhere close to being production ready. +When I added dedicated server builds for [[Resonance]], a cyberpunk-themed first person shooter, I did not realize the work I was giving myself later. I created a [vibe-coded prototype](https://github.com/brendan-ch/ResonanceServerOrchestrator/tree/2d71f0491830dfa91d7887c208c14c52d6513202) of a server orchestrator that was nowhere close to being production ready. -Previously the game used [PurrLay](https://github.com/PurrNet/PurrLay), a peer-to-peer relay that clients connect to, where one of the clients becomes the *host* for a match. With the *dedicated server* architecture, all clients connect directly to the game server which can run game logic.[^1][^2] Adding the game server orchestrator means knowing when to start and stop a server, and how to point players to the server with the correct match. +Previously the game used [PurrLay](https://github.com/PurrNet/PurrLay), a peer-to-peer relay that clients connect to, where one of the clients becomes the *host* for a match. With the dedicated server architecture, all clients connect directly to the game server which can run game logic.[^1] Adding the game server orchestrator means knowing when to start and stop a server, and how to point players to the server with the correct match. I decided to try and turn the aforementioned prototype into a [custom backend](https://github.com/brendan-ch/ResonanceServerOrchestrator/tree/2d71f0491830dfa91d7887c208c14c52d6513202) for the orchestration. The basic flows look something like this: -- Players *join* a match in the orchestrator after having been in the same lobby, so the orchestrator doesn't depend on the lobby backend -- When all players have joined, the orchestrator provisions the dedicated server, and players *connect to the dedicated server* to play the game -- When the game ends, players *leave* the match in the orchestrator, and the server exits +- Players join a match in the orchestrator after having been in the same lobby, so the orchestrator doesn't depend on the lobby backend +- When all players have joined, the orchestrator provisions the dedicated server, and players connect to the dedicated server to play the game +- When the game ends, players leave the match in the orchestrator, and the server exits -[Edgegap](https://edgegap.com) is currently planned as the dedicated server platform. But, hopefully, with the custom orchestrator, we retain some ability to switch to other providers. +[Edgegap](https://edgegap.com) is currently planned as the dedicated server platform. But, hopefully, with the custom orchestrator, there is some ability to switch to other providers. -Right now this system works fine in development when conditions are predictable, but there is still much work to be done. I am *not* a backend engineer by trade. +Right now this system works fine in development when conditions are predictable, but there is still much work to be done. [^1]: I didn't realize that I could drop [PurrLay](https://github.com/PurrNet/PurrLay) when adding the dedicated server until later. -[^2]: With Unity, a dedicated server build generates a Linux executable that can be put into a Docker container. From 4f6d9d8ab6c448285fb261b5086f4d38ae802c3a Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Thu, 3 Sep 2026 12:58:08 +0000 Subject: [PATCH 2/4] Add Cloudflare Pages step to deployment --- .../{jekyll.yml => jekyll-publish.yml} | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) rename .github/workflows/{jekyll.yml => jekyll-publish.yml} (71%) diff --git a/.github/workflows/jekyll.yml b/.github/workflows/jekyll-publish.yml similarity index 71% rename from .github/workflows/jekyll.yml rename to .github/workflows/jekyll-publish.yml index 7be260c..52d36e0 100644 --- a/.github/workflows/jekyll.yml +++ b/.github/workflows/jekyll-publish.yml @@ -1,10 +1,4 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -# Sample workflow for building and deploying a Jekyll site to GitHub Pages -name: Deploy Jekyll site to Pages +name: Deploy Jekyll site to Cloudflare Pages on: # Runs on pushes targeting the default branch @@ -41,6 +35,7 @@ jobs: ruby-version: '3.4.1' # Not needed with a .ruby-version file bundler-cache: true # runs 'bundle install' and caches installed gems automatically cache-version: 0 # Increment this number if you need to re-download cached gems + - name: Setup Pages id: pages uses: actions/configure-pages@v5 @@ -49,6 +44,7 @@ jobs: run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}" env: JEKYLL_ENV: production + - name: Push image optimizations onto main continue-on-error: true run: | @@ -58,18 +54,11 @@ jobs: git add assets/img git commit -m "chore: optimize images" git push - - name: Upload artifact - # Automatically uploads an artifact from the './_site' directory by default - uses: actions/upload-pages-artifact@v3 + + - name: Publish to Cloudflare Pages + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + command: pages deploy _site --project-name=${{ vars.CLOUDFLARE_PROJECT_NAME }} - # Deployment job - deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - needs: build - steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v5 From 7d09d4b69a83090f524f4fc361a2b5a60b2940d2 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Thu, 3 Sep 2026 13:02:52 +0000 Subject: [PATCH 3/4] Remove GitHub Pages setup --- .github/workflows/jekyll-publish.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/jekyll-publish.yml b/.github/workflows/jekyll-publish.yml index 52d36e0..f9b7220 100644 --- a/.github/workflows/jekyll-publish.yml +++ b/.github/workflows/jekyll-publish.yml @@ -36,9 +36,6 @@ jobs: bundler-cache: true # runs 'bundle install' and caches installed gems automatically cache-version: 0 # Increment this number if you need to re-download cached gems - - name: Setup Pages - id: pages - uses: actions/configure-pages@v5 - name: Build with Jekyll # Outputs to the './_site' directory by default run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}" From c46226842933f6e83b3e71796cce94e13e5e05fa Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Thu, 3 Sep 2026 21:18:50 +0000 Subject: [PATCH 4/4] Delete _notes/game-server-orchestration.md --- _notes/game-server-orchestration.md | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 _notes/game-server-orchestration.md diff --git a/_notes/game-server-orchestration.md b/_notes/game-server-orchestration.md deleted file mode 100644 index b9f9813..0000000 --- a/_notes/game-server-orchestration.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Game server orchestration ---- - -Game server orchestration is solving the problem of provisioning dedicated game servers in a scalable manner for a multiplayer game. - -When I added dedicated server builds for [[Resonance]], a cyberpunk-themed first person shooter, I did not realize the work I was giving myself later. I created a [vibe-coded prototype](https://github.com/brendan-ch/ResonanceServerOrchestrator/tree/2d71f0491830dfa91d7887c208c14c52d6513202) of a server orchestrator that was nowhere close to being production ready. - -Previously the game used [PurrLay](https://github.com/PurrNet/PurrLay), a peer-to-peer relay that clients connect to, where one of the clients becomes the *host* for a match. With the dedicated server architecture, all clients connect directly to the game server which can run game logic.[^1] Adding the game server orchestrator means knowing when to start and stop a server, and how to point players to the server with the correct match. - -I decided to try and turn the aforementioned prototype into a [custom backend](https://github.com/brendan-ch/ResonanceServerOrchestrator/tree/2d71f0491830dfa91d7887c208c14c52d6513202) for the orchestration. The basic flows look something like this: - -- Players join a match in the orchestrator after having been in the same lobby, so the orchestrator doesn't depend on the lobby backend -- When all players have joined, the orchestrator provisions the dedicated server, and players connect to the dedicated server to play the game -- When the game ends, players leave the match in the orchestrator, and the server exits - -[Edgegap](https://edgegap.com) is currently planned as the dedicated server platform. But, hopefully, with the custom orchestrator, there is some ability to switch to other providers. - -Right now this system works fine in development when conditions are predictable, but there is still much work to be done. - -[^1]: I didn't realize that I could drop [PurrLay](https://github.com/PurrNet/PurrLay) when adding the dedicated server until later.