# Roblox2 — Dev Guide

This is everything you (and any new dev) need to build, run, ship and host Roblox2.

The whole thing fits in your head: one C++20 engine, one self-extracting Windows installer, one Cloudflare worker for multiplayer, one Cloudflare Pages site for the download page.

---

## 0. One-time setup

### 0.1 Toolchain
- **Windows 10/11**
- **WinLibs MinGW 16.1.0** (POSIX UCRT) installed in your user profile
- **CMake 3.20+** (any recent version)
- **Ninja** (optional — works with `cmake --build build -j 1` too)
- **Node 20+** + `npx` (for Cloudflare deploys)
- A **Cloudflare account**

### 0.2 Clone the project
```bash
git clone <your-repo-url> roblox2
cd roblox2
```

The first build downloads `glfw` and `glm` via CMake `FetchContent`, so you need network on the first `cmake` run.

### 0.3 First build
```powershell
# from the project root
cmake -S . -B build -G "Ninja"     # or omit -G to use the default generator
cmake --build build -j 1
```
- `build\Roblox2Engine.exe` — the game
- `build\Roblox2Relay.exe` — local TCP relay (port 7777) for local multiplayer
- `build\Roblox2Installer.exe` — self-extracting installer for friends (built separately, see §4)

The engine reads shaders from `Assets/Shaders/*.vert|.frag` if present next to the exe, and otherwise falls back to resources embedded inside the exe by `Engine\Resources.rc`. So you can run the game from `build\` or from a folder with only the .exe.

---

## 1. Layout

```
roblox2/
  CMakeLists.txt
  main.cpp
  Assets/Shaders/        # .vert / .frag source
  Engine/
    Core/                # Application, Window, Timer, Input
    Rendering/           # Renderer, Mesh, Shader, Texture, Font, UIRenderer, Camera
    Physics/             # AABB + gravity + pushables
    Resources.{h,cpp}    # ReadFile fallback (disk → embedded resource)
    Resources.rc         # windres script: embeds shaders into the .exe
  Game/
    MainGame/            # scene management, registry, network glue
    Instance/            # GameModule + BaseplateModule (the only registered game)
    Network/             # NetworkClient, Stream (TcpStream + WssStream), RelayServer
    UI/                  # UISystem, top bar, corner buttons
    Installer/           # Roblox2Installer.cpp + Installer.rc
  cloudflare/            # multiplayer Worker source
  robox2-multiplayer/    # wrangler project for the Worker
  robox2-site/           # wrangler project for the website
  site/                  # static site source (html/css/assets)
  build/                 # generated, never commit
```

---

## 2. Adding a new game (the only thing you really need to know)

A "game" is anything that **clears the world and rebuilds it**. Games are listed in the **G** in-game menu.

### 2.1 Implement the module
`Game/Instance/YourGame.cpp`:
```cpp
#include "Game/Instance/GameModule.h"
class YourGame : public Game::GameModule {
public:
    const char* Name() const override        { return "Your Game"; }
    const char* Description() const override { return "Short player-facing description"; }
    std::string Id() const override         { return "yourgame"; }
    void Build(Engine::World& world, ...) override {
        world.Clear();
        world.AddBaseplate(/* size= */ 80);
        // ... add parts, players, etc.
    }
};
static Game::GameModuleRegistrar<YourGame> _reg("yourgame");
```
The `Build(...)` signature is in `Game/Instance/GameModule.h` — read it once, you'll get it.

### 2.2 Register it
`Game/MainGame/MainGame.cpp` → `MainGame::SetupScene()`:
```cpp
Game::GameRegistry::Instance().Register<YourGame>();
```

### 2.3 Press G, click your game, done.
`MainGame::LoadGame(id)` will clear remotes, rebuild the world, and switch over.

---

## 3. Multiplayer

### 3.1 The wire format (5 bytes header, simple JSON-ish payload)
Defined in `Game/Network/NetworkClient.h`:
```
[1 byte type][4 bytes length (LE)][N bytes UTF-8 payload]
```
Types:
- `'j'` = join (client → server)
- `'p'` = position update
- `'q'` = quit
- (add more freely)

A `Stream` is either a TCP socket or a WSS connection. Both implement the same `Send/Recv/Close` interface. The choice is driven entirely by the `ROBOX2_RELAY` env var:
- unset / `host:port`  → TCP
- `wss://host[:port]/path` → WSS (Schannel + RFC 6455 framing inside the engine, no external lib)

### 3.2 Run two locally
```powershell
start_local_multiplayer.bat
```
It launches a `Roblox2Relay.exe` on port 7777 and starts the engine with `ROBOX2_RELAY=127.0.0.1:7777`. Run the same command a second time on another machine (or another port) and the two engines see each other.

### 3.3 The Cloudflare Worker
- Code: `cloudflare/worker.js`
- Wrangler project: `robox2-multiplayer/`
- Deployed as a Durable Object (`MultiplayerDO`) on the free plan — it stores per-room `Map<id, PlayerState>` and broadcasts on each `t=p|j` event.

To redeploy after editing `worker.js`:
```powershell
redeploy_worker.bat
```

### 3.4 Talk to the live Worker from the engine
`ROBOX2_RELAY=wss://robox2-multiplayer.fuckqualitystudio.workers.dev/ws` — the URL is hard-coded into the default `start_cloud_multiplayer.bat`. The Worker creates rooms on first join and routes by `?room=<id>` (default = `default`).

---

## 4. Building the installer

`build_installer.bat` is a wrapper. The real one-liner is `make_installer.ps1`:
```powershell
.\make_installer.ps1
```
It does:
1. `cmake --build build -j 1` (engine)
2. Copies the .exe next to `Game\Installer\Installer.rc`
3. `windres` compiles the .rc → embeds the exe as `IDR_GAME_PAYLOAD` (RCDATA)
4. `g++` links the installer stub (`Game\Installer\Roblox2Installer.cpp`) into a windowless .exe
5. Output: `build\Roblox2Installer.exe` (~1.9 MB)

### What the installer does
On double-click:
- Writes `Roblox2Engine.exe` to `%APPDATA%\Roblox2\`
- Creates a desktop shortcut `Roblox2.lnk`
- Launches the game

To uninstall: delete `%APPDATA%\Roblox2` and the desktop shortcut. That's it.

### Why not NSIS / Inno Setup?
- One file, no extra dependency, no temp folders, no admin rights needed.
- Rebuilds in 2 seconds.
- Cost: no MSI, no Start Menu entry, no uninstaller panel. We compensate by documenting the manual uninstall in the website FAQ.

### When to switch
Once you have 100+ players, switch to **Inno Setup** for proper Start Menu / uninstaller support. The `make_installer.ps1` can drive it the same way.

---

## 5. The website

`site/` is a static site (HTML + CSS, no framework, no build step). It gets uploaded to Cloudflare Pages.

Files:
- `site/index.html` — page
- `site/styles.css` — styles
- `site/downloads/Roblox2Installer.exe` — copy of the latest installer

### Update + redeploy
```powershell
.\deploy_site.ps1
```
This:
1. Rebuilds the installer if `build\Roblox2Installer.exe` is missing
2. Copies the installer + `site/*` into `robox2-site\public\`
3. `wrangler pages deploy` pushes the new version

### Free Cloudflare Pages URL
`https://robox2-site.pages.dev`

If you later buy a domain, point a CNAME to that URL — Pages handles the certificate automatically.

---

## 6. Code signing (kills the SmartScreen warning)

Until you sign, every user will see the "Windows protected your PC" dialog. They'll click "More info → Run anyway" and it'll work. To get rid of it:

1. Buy a **Code Signing Certificate** from SSL.com / Certum / Sectigo (~50–200 $/yr).
2. Save the `.pfx` file in the project root as `codesign.pfx`.
3. Install **Windows SDK** (gives you `signtool.exe`).
4. Add a signing step to `make_installer.ps1`:
   ```powershell
   & "C:\Program Files (x86)\Windows Kits\10\bin\<ver>\x64\signtool.exe" sign `
       /fd SHA256 /tr http://timestamp.digicert.com /td sha256 `
       /f codesign.pfx /p $env:CODE_SIGN_PWD `
       build\Roblox2Installer.exe
   ```
5. Set `CODE_SIGN_PWD` as a user env var. **Do not commit the .pfx or the password.**

EV certificates skip the reputation-building step entirely. Regular OV certs need ~3 weeks of installs before SmartScreen stops warning.

---

## 7. Style guide (so the codebase doesn't rot)

- **C++20**, no exceptions, no RTTI.
- Engine = `Engine::` namespace, no game logic.
- Game = `Game::` namespace, depends on engine.
- All UI goes through `UIRenderer` (no ImGui, no Slate).
- One file per class, snake_case filenames, PascalCase types.
- Every `GameModule` registers itself via a static `GameModuleRegistrar<T>` — never edit a central list manually.
- Shaders live in `Assets/Shaders/`, get embedded by `Engine/Resources.rc` so the .exe is self-contained.

---

## 8. Common tasks

| Task | How |
|------|-----|
| Add a new game | §2 |
| Edit a shader | Edit `Assets/Shaders/x.frag`, rebuild — embedded resource is updated by `windres` |
| Change the multiplayer URL | Edit `cloudflare/worker.js` + redeploy via `redeploy_worker.bat` |
| Update the website | Edit `site/*`, run `deploy_site.ps1` |
| Ship a new build to friends | `make_installer.ps1`, send `build\Roblox2Installer.exe` |
| Test multiplayer locally | `start_local_multiplayer.bat` (run twice) |
| Test multiplayer online | `start_cloud_multiplayer.bat` |
| Add a new net message type | Add a byte constant in `NetworkClient.h`, handle it in `NetworkClient::OnRecv` |

---

## 9. Gotchas

- **`build/` is huge** (~hundreds of MB from `glfw-src` and `glm-src`). Git-ignore it.
- **`CMAKE_BUILD_TYPE=Release` is set by default** in `CMakeLists.txt`. Debug builds work but are ~10x slower.
- **Path encoding**: your user folder has a non-ASCII character (`Éthan`). CMake handles it, but always pass absolute paths and don't rely on relative paths inside resource-loading code. Use `std::filesystem::u8path`.
- **SmartScreen** will warn on first install. Users click "More info → Run anyway". Document this in your website.
- **The Worker is single-region.** For global low-ping you want Workers + Durable Objects in the closest region. Cloudflare handles this automatically when you use DO with SQLite-backed storage (the migration is already in `wrangler.toml`).

---

## 10. Roadmap (suggested order)

1. ✅ Self-extracting installer + Cloudflare multiplayer + website
2. ☐ Code signing cert (kills SmartScreen warning)
3. ☐ Move to Inno Setup (Start Menu, uninstaller, version metadata)
4. ☐ In-game server browser (replace hardcoded `ROBOX2_RELAY` with a clickable list)
5. ☐ Game module upload — let users submit their own `GameModule`s
6. ☐ Steam release
