Skip to main content

Architecture Overview

App-Based Modularity

Woodlands uses a modular app-based architecture. Each feature area is an app under src/apps/ with its own client, server, and shared directories. Apps communicate through typed remotes (Remo) and shared reactive state (Charm atoms).

src/apps/
├── chunks/ # Procedural world generation
├── enemies/ # Entity spawning & AI behaviors
├── global/ # Death, respawn, player data
├── lobby/ # Queue & matchmaking
├── quirkymals/ # Player character system
└── devtools/ # Debug tools

Flamework Decorators

DecoratorSidePurpose
@ServiceServerSingleton service with lifecycle hooks
@ControllerClientSingleton controller with lifecycle hooks
@ComponentBothInstance-attached behavior (tag-based)

Lifecycle order: onInit()onStart()onTick() (per frame)

Dependencies are resolved via Dependency<T>() for cross-service communication.

State Management

Charm Atoms

Reactive state containers that trigger effects when values change:

// Define
const gameSeed = atom(0);

// Read
const seed = gameSeed();

// Write
gameSeed(12345);

// React
effect(() => {
const seed = gameSeed();
// runs whenever gameSeed changes
});

Atom Categories

StoreScopeKey Atoms
worldAtomsServer → All ClientsdayNight, pathNodes, gameSeed, chunkPacing
playerAtomsServer → All ClientsdangerZonePlayers, safeZonePlayers, gamePhase
datastoreServer → Owner ClientPlayer save data (quirkymal, settings, stats)

Sync Pipeline

Server atoms → charm-sync producer → network → charm-sync consumer → Client atoms

Networking (Remo)

Each app defines its own remotes in shared/*-remotes.ts:

export const chunksRemotes = createRemotes({
// Server → Client (one-way)
chunkSpawned: remote<Client, [data: {...}]>(),

// Client → Server (one-way)
safeZoneEntered: remote<Server, [data: {...}]>(),

// Request-Response
retrievePacket: remote<Server>().returns<{...}>(),
});

ECS (jecs)

Used exclusively for enemy entities. The ECS world is a singleton in shared/ecs/world.ts.

Components define data (position, state, type). Tags classify entities (IsFlowerTrap, IsWatcher). Systems run behavior logic each frame on the server, with network sync broadcasting to clients.

See ECS System for details.

Build Pipeline

TypeScript → rbxtsc (with Flamework transformer) → Luau → Rojo → Roblox Studio

The default.project.json maps output directories to Roblox services:

  • out/server + out/apps/*/server → ServerScriptService
  • out/client + out/apps/*/client → StarterPlayerScripts
  • out/shared + out/apps/*/shared → ReplicatedStorage