From dbc1b2c31e1ce5d2f91ece5f29ae8f39ad7ac30a Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Mon, 8 Dec 2025 13:49:27 -0600 Subject: [PATCH] reorganize --- .github/docker/Dockerfile.alpine | 30 -- .github/docker/Dockerfile.emscripten | 12 - .github/docker/Dockerfile.linux | 34 -- .github/docker/Dockerfile.mingw | 23 -- .github/workflows/build.yml | 304 ---------------- AGENTS.md | 53 --- CLAUDE.md | 375 -------------------- Dockerfile | 55 --- LICENSE | 26 -- mkdocs.yml => docs/mkdocs.yml | 0 requirements.txt => docs/requirements.txt | 0 emscripten.cross | 22 -- Info.plist => help/Info.plist | 0 cell.md => help/cell.md | 0 cell2.md => help/cell2.md | 0 help/cellstructure.md | 28 ++ license.txt => help/license.txt | 0 resource.manifest => help/resource.manifest | 0 resource.rc => help/resource.rc | 0 {todo => help/todo}/graphics.md | 0 {todo => help/todo}/ops.md | 0 {todo => help/todo}/playdate.md | 0 mingw32.cross | 17 - playdate.cross | 20 -- 24 files changed, 28 insertions(+), 971 deletions(-) delete mode 100644 .github/docker/Dockerfile.alpine delete mode 100644 .github/docker/Dockerfile.emscripten delete mode 100644 .github/docker/Dockerfile.linux delete mode 100644 .github/docker/Dockerfile.mingw delete mode 100644 .github/workflows/build.yml delete mode 100644 AGENTS.md delete mode 100644 CLAUDE.md delete mode 100644 Dockerfile delete mode 100644 LICENSE rename mkdocs.yml => docs/mkdocs.yml (100%) rename requirements.txt => docs/requirements.txt (100%) delete mode 100644 emscripten.cross rename Info.plist => help/Info.plist (100%) rename cell.md => help/cell.md (100%) rename cell2.md => help/cell2.md (100%) create mode 100644 help/cellstructure.md rename license.txt => help/license.txt (100%) rename resource.manifest => help/resource.manifest (100%) rename resource.rc => help/resource.rc (100%) rename {todo => help/todo}/graphics.md (100%) rename {todo => help/todo}/ops.md (100%) rename {todo => help/todo}/playdate.md (100%) delete mode 100644 mingw32.cross delete mode 100644 playdate.cross diff --git a/.github/docker/Dockerfile.alpine b/.github/docker/Dockerfile.alpine deleted file mode 100644 index a99591a8..00000000 --- a/.github/docker/Dockerfile.alpine +++ /dev/null @@ -1,30 +0,0 @@ -# Dockerfile.alpine -FROM alpine:edge - -# Enable the edge and edge/community repositories. -# If you already have those in your base image, you might not need these echo lines. -RUN echo "https://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories && \ - echo "https://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories - -# Update indexes and install packages -RUN apk update && \ - apk add --no-cache \ - build-base \ - binutils \ - mold \ - meson \ - cmake \ - ninja \ - git \ - pkgconf \ - ccache \ - nodejs \ - npm \ - zip \ - alsa-lib-dev \ - pulseaudio-dev \ - libudev-zero-dev \ - wayland-dev \ - wayland-protocols \ - mesa-dev \ - sdl3 diff --git a/.github/docker/Dockerfile.emscripten b/.github/docker/Dockerfile.emscripten deleted file mode 100644 index 71725d89..00000000 --- a/.github/docker/Dockerfile.emscripten +++ /dev/null @@ -1,12 +0,0 @@ -# Use the official Emscripten SDK image (includes emcc, emsdk, Python, nodejs, etc) -FROM emscripten/emsdk:latest - -# Install Meson & Ninja if needed (some emsdk tags already bundle them) -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - meson \ - ninja-build \ - python3-pip && \ - rm -rf /var/lib/apt/lists/* - -RUN pip3 install --upgrade meson>=1.4 \ No newline at end of file diff --git a/.github/docker/Dockerfile.linux b/.github/docker/Dockerfile.linux deleted file mode 100644 index fd6eace0..00000000 --- a/.github/docker/Dockerfile.linux +++ /dev/null @@ -1,34 +0,0 @@ -FROM ubuntu:plucky - -RUN apt-get update && apt-get install -y --no-install-recommends \ - python3 python3-pip \ - libasound2-dev \ - libpulse-dev \ - libudev-dev \ - libwayland-dev \ - wayland-protocols \ - libxkbcommon-dev \ - libx11-dev \ - libxext-dev \ - libxrandr-dev \ - libxcursor-dev \ - libxi-dev \ - libxinerama-dev \ - libxss-dev \ - libegl1-mesa-dev \ - libgl1-mesa-dev \ - cmake \ - ninja-build \ - git \ - build-essential \ - binutils \ - mold \ - pkg-config \ - meson \ - ccache \ - mingw-w64 \ - wine \ - libmimalloc-dev \ - npm nodejs zip - -RUN apt-get install -y libunwind-dev libblas-dev liblapacke-dev \ No newline at end of file diff --git a/.github/docker/Dockerfile.mingw b/.github/docker/Dockerfile.mingw deleted file mode 100644 index 9fb5b3fc..00000000 --- a/.github/docker/Dockerfile.mingw +++ /dev/null @@ -1,23 +0,0 @@ -FROM debian:trixie - -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - mingw-w64 \ - cmake \ - ninja-build \ - git \ - build-essential \ - binutils \ - pkg-config \ - zip \ - ccache \ - npm \ - nodejs \ - meson \ - libmimalloc-dev \ - libbsd-dev \ - gcc-mingw-w64-ucrt64 \ - g++-mingw-w64-ucrt64 && \ - rm -rf /var/lib/apt/lists/* diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 5f893449..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,304 +0,0 @@ -name: Build and Deploy - -on: - push: - branches: [ "*" ] - tags: [ "v*" ] - pull_request: - -jobs: - # ────────────────────────────────────────────────────────────── - # LINUX BUILD - # ────────────────────────────────────────────────────────────── - build-linux: - runs-on: ubuntu-latest - container: - image: gitea.pockle.world/john/prosperon/linux:latest - - steps: - - name: Check Out Code - uses: actions/checkout@v4 - with: { fetch-depth: 0 } - - - name: Build Prosperon (Linux) - run: | - meson setup build -Dbuildtype=release -Db_lto=true -Db_lto_mode=thin -Db_ndebug=true - meson compile -C build - - - name: Test Prosperon (Linux) - env: { TRACY_NO_INVARIANT_CHECK: 1 } - run: | - meson test --print-errorlogs -C build - - - name: Upload Test Log (Linux) - if: ${{ always() }} - uses: actions/upload-artifact@v3 - with: - name: testlog-linux - path: build/meson-logs/testlog.txt - - - name: Upload Artifact (Linux) - if: startsWith(github.ref, 'refs/tags/v') - uses: actions/upload-artifact@v3 - with: - name: prosperon-artifacts-linux - path: build/prosperon - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to Gitea Registry - uses: docker/login-action@v3 - with: - registry: gitea.pockle.world - username: ${{ secrets.USER_GITEA }} - password: ${{ secrets.TOKEN_GITEA }} - - - name: Determine Docker Tag - id: docker_tag - run: | - if [[ "${{ github.ref }}" =~ ^refs/tags/v.* ]]; then - TAG=$(echo "${{ github.ref }}" | sed 's#refs/tags/##') - echo "tag=$TAG" >> $GITHUB_OUTPUT - else - echo "tag=latest" >> $GITHUB_OUTPUT - fi - - - name: Build and Push Docker Image - uses: docker/build-push-action@v6 - with: - context: . - file: ./Dockerfile - push: true - tags: gitea.pockle.world/john/prosperon:${{ steps.docker_tag.outputs.tag }} - platforms: linux/amd64 - - # ────────────────────────────────────────────────────────────── - # WINDOWS BUILD (MSYS2 / CLANG64) - # ────────────────────────────────────────────────────────────── - build-windows: - runs-on: win-native - strategy: - matrix: { msystem: [ CLANG64 ] } - - steps: - - name: Check Out Code - uses: actions/checkout@v4 - - - name: Setup MSYS2 - uses: msys2/setup-msys2@v2 - with: - msystem: ${{ matrix.msystem }} - update: true - cache: true - install: | - git zip gzip tar base-devel - pacboy: | - meson - cmake - toolchain - - - name: Build Prosperon (Windows) - shell: msys2 {0} - run: | - meson setup build -Dbuildtype=release -Db_lto=true -Db_lto_mode=thin -Db_ndebug=true -Dtracy:only_localhost=true -Dtracy:no_broadcast=true - meson compile -C build - - - name: Test Prosperon (Windows) - shell: msys2 {0} - env: - TRACY_NO_INVARIANT_CHECK: 1 - run: | - meson test --print-errorlogs -C build - - - name: Upload Test Log (Windows) - if: ${{ always() }} - uses: actions/upload-artifact@v3 - with: - name: testlog-windows - path: build/meson-logs/testlog.txt - - - name: Upload Artifact (Windows) - if: startsWith(github.ref, 'refs/tags/v') - uses: actions/upload-artifact@v3 - with: - name: prosperon-artifacts-windows - path: build/prosperon.exe - - # ────────────────────────────────────────────────────────────── - # MACOS BUILD - # ────────────────────────────────────────────────────────────── - build-macos: - runs-on: macos-latest - - steps: - - name: Check Out Code - uses: actions/checkout@v4 - with: { fetch-depth: 0 } - - - name: Build Prosperon (macOS) - run: | - meson setup build -Dbuildtype=release -Db_lto=true -Db_lto_mode=thin -Db_ndebug=true - meson compile -C build - - - name: Test Prosperon (macOS) - run: | - meson test --print-errorlogs -C build - - - name: Upload Test Log (macOS) - if: ${{ always() }} - uses: actions/upload-artifact@v3 - with: - name: testlog-macos - path: build/meson-logs/testlog.txt - - - name: Upload Artifact (macOS) - if: startsWith(github.ref, 'refs/tags/v') - uses: actions/upload-artifact@v3 - with: - name: prosperon-artifacts-macos - path: build/prosperon - - # ────────────────────────────────────────────────────────────── - # PACKAGE CROSS-PLATFORM DIST - # ────────────────────────────────────────────────────────────── - package-dist: - needs: [ build-linux, build-windows, build-macos ] - if: startsWith(github.ref, 'refs/tags/v') - runs-on: ubuntu-latest - - steps: - - name: Check Out Code - uses: actions/checkout@v3 - with: { fetch-depth: 0 } - - - name: Get Latest Tag - id: get_tag - run: | - TAG=$(git describe --tags --abbrev=0) - echo "tag=$TAG" >> $GITHUB_OUTPUT - - - name: Download Linux Artifacts - uses: actions/download-artifact@v3 - with: - name: prosperon-artifacts-linux - path: linux_artifacts - - - name: Download Windows Artifacts - uses: actions/download-artifact@v3 - with: - name: prosperon-artifacts-windows - path: windows_artifacts - - - name: Download macOS Artifacts - uses: actions/download-artifact@v3 - with: - name: prosperon-artifacts-macos - path: mac_artifacts - - - name: Create Dist Folder - run: | - mkdir -p dist/linux dist/win dist/mac - cp README.md dist/ - cp license.txt dist/ - cp -r examples dist/ - cp linux_artifacts/* dist/linux/ - cp windows_artifacts/* dist/win/ - cp mac_artifacts/* dist/mac/ - - - name: Package Final Dist - run: | - TAG=${{ steps.get_tag.outputs.tag }} - zip -r "prosperon-${TAG}.zip" dist - echo "Created prosperon-${TAG}.zip" - - - name: Upload Final Dist - uses: actions/upload-artifact@v3 - with: - name: "prosperon-${{ steps.get_tag.outputs.tag }}" - path: "prosperon-${{ steps.get_tag.outputs.tag }}.zip" - - # ────────────────────────────────────────────────────────────── - # DEPLOY TO ITCH.IO (single ZIP containing all OSes) - # ────────────────────────────────────────────────────────────── - deploy-itch: - needs: [ package-dist ] - runs-on: ubuntu-latest - - steps: - - name: Check Out Code - uses: actions/checkout@v3 - with: { fetch-depth: 0 } - - - name: Get Latest Tag - id: get_tag - run: | - TAG=$(git describe --tags --abbrev=0) - echo "tag=$TAG" >> $GITHUB_OUTPUT - - - name: Download Final Distribution - uses: actions/download-artifact@v3 - with: - name: "prosperon-${{ steps.get_tag.outputs.tag }}" - path: dist - - - name: Set up Butler - uses: jdno/setup-butler@v1 - - - name: Push to itch.io - run: | - butler push "dist/prosperon-${{ steps.get_tag.outputs.tag }}.zip" \ - ${{ secrets.ITCHIO_USERNAME }}/prosperon:universal \ - --userversion ${{ steps.get_tag.outputs.tag }} - env: - BUTLER_API_KEY: ${{ secrets.ITCHIO_API_KEY }} - - # ────────────────────────────────────────────────────────────── - # DEPLOY TO SELF-HOSTED GITEA - # ────────────────────────────────────────────────────────────── - deploy-gitea: - needs: [ package-dist ] - runs-on: ubuntu-latest - - steps: - - name: Check Out Code - uses: actions/checkout@v3 - with: { fetch-depth: 0 } - - - name: Get Latest Tag & Commit Message - id: get_tag - run: | - TAG=$(git describe --tags --abbrev=0) - COMMIT_MSG=$(git log -1 --pretty=%B "$TAG") - echo "tag=$TAG" >> $GITHUB_OUTPUT - echo "commit_msg=$COMMIT_MSG" >> $GITHUB_OUTPUT - - - name: Download Final Distribution - uses: actions/download-artifact@v3 - with: - name: "prosperon-${{ steps.get_tag.outputs.tag }}" - path: dist - - - name: Create / Update Gitea Release - run: | - TAG=${{ steps.get_tag.outputs.tag }} - ZIP=dist/prosperon-${TAG}.zip - BODY=$(echo "${{ steps.get_tag.outputs.commit_msg }}" | jq -R -s '.') - RELEASE=$(curl -s -H "Authorization: token ${{ secrets.TOKEN_GITEA }}" \ - "https://gitea.pockle.world/api/v1/repos/john/prosperon/releases/tags/$TAG" | jq -r '.id') - - if [ "$RELEASE" = "null" ] || [ -z "$RELEASE" ]; then - RELEASE=$(curl -X POST \ - -H "Authorization: token ${{ secrets.TOKEN_GITEA }}" \ - -H "Content-Type: application/json" \ - -d "{\"tag_name\":\"$TAG\",\"target_commitish\":\"${{ github.sha }}\",\"name\":\"$TAG\",\"body\":$BODY,\"draft\":false,\"prerelease\":false}" \ - "https://gitea.pockle.world/api/v1/repos/john/prosperon/releases" | jq -r '.id') - fi - - curl -X POST \ - -H "Authorization: token ${{ secrets.TOKEN_GITEA }}" \ - -H "Content-Type: application/octet-stream" \ - --data-binary @"$ZIP" \ - "https://gitea.pockle.world/api/v1/repos/john/prosperon/releases/$RELEASE/assets?name=prosperon-${TAG}.zip" - env: - TOKEN_GITEA: ${{ secrets.TOKEN_GITEA }} diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index a1e66e18..00000000 --- a/AGENTS.md +++ /dev/null @@ -1,53 +0,0 @@ -# Agent Development Guide - -## Build Commands -- **Debug build**: `make debug` or `meson setup build_dbg -Dbuildtype=debugoptimized && meson compile -C build_dbg` -- **Release build**: `make release` or `meson setup -Dbuildtype=release -Db_lto=true build_release && meson compile -C build_release` -- **Fast build**: `make fast` or `meson setup build_fast && meson compile -C build_fast` -- **Web build**: `make web` or `meson setup -Deditor=false -Dbuildtype=minsize build_web && meson compile -C build_web` -- **Cross-platform**: `make crosswin` (Windows), `make dockerlinux` (Linux), `make dockeremc` (Emscripten) - -## Test Commands -- **Run all tests**: `meson test -C build_dbg` -- **Run single test**: `./cell tests/` (e.g., `./cell tests/send`, `./cell tests/empty`) -- **Available tests**: spawn_actor, empty, nota, wota, portalspawner, overling, send, delay -- **Test examples**: `./cell examples/nat`, `./cell examples/http_download_actor` - -## Code Style Guidelines - -### C Code Style (K&R) -- **Indentation**: 4 spaces, no tabs -- **Naming**: `snake_case` for identifiers -- **Files**: Small, focused C files with header guards required -- **Formatting**: Use `.clang-format` (GNU style, 2-space continuation, attach braces) -- **Comments**: Focus on "why", keep lines to ~100 columns - -### Cell Language Style (JavaScript-like) -- **Language**: Cell resembles JavaScript but has key differences - equality operators (`==`, `!=`) perform strict comparisons (equivalent to `===`, `!==` in JavaScript, no type coercion) -- **Indentation**: 2 spaces -- **Declarations**: `def` for constants, `var` for block-scoped variables (like `let`) -- **Equality**: Use `==` only (strict equality, no coercion) -- **Null checks**: Use `== null` (no `undefined` in Cell) -- **Imports**: Use `use('path')` for modules (not ES6 import/export) -- **Modules**: `*.cm` files must return values, `*.ce` files are programs (don't return) -- **Patterns**: Prefer objects, prototypes, closures over classes -- **Formatting**: Use `.prettierrc` (semicolons, double quotes, trailing commas, 1000 char width) - -### File Organization -- **Modules**: `*.cm` (return objects, get frozen with `stone()`) -- **Programs**: `*.ce` (execute top-to-bottom, register handlers) -- **Naming**: Lowercase paths with `/` separators -- **Resolution**: Engine appends `.cm`/`.ce` automatically when probing - -### Error Handling -- Use `log.console()` and `log.error()` for logging -- Actor system handles message timeouts automatically -- Check for circular imports (detected and reported) -- Validate module returns before freezing - -### Best Practices -- Keep modules small and composable -- Use actor messaging for communication (no shared objects) -- Follow hierarchical actor system (overlings/underlings) -- Prefer functional programming patterns -- Document with `cell.DOC` system \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index ddc329d8..00000000 --- a/CLAUDE.md +++ /dev/null @@ -1,375 +0,0 @@ -# CLAUDE.md - -## Build Commands -Run 'make' to make cell. - -### Testing -After install with 'make', just run 'cell' and point it at the actor you want to launch. "cell tests/toml" runs the actor "tests/toml.js" - -## Scripting language -This is called "cell", a variant of JavaScript with important differences. See docs/cell.md for detailed language documentation. - -## Architecture Overview - -Prosperon is an actor-based game engine. - -### Actor Model -- Each actor runs on its own thread -- Communication only through message passing (no shared JavaScript objects) -- Hierarchical actor system with spawning/killing -- Actor lifecycle: awake, update, draw, garbage collection - -### Cell Language Style Guide -- Use `use()` function for imports (Misty-style, not ES6 import/export) -- Prefer closures and javascript objects and prototypes over ES6 style classes -- Follow existing JavaScript patterns in the codebase -- Functions as first-class citizens -- Use `def` for constants (not const) -- Use `var` for variables (block-scoped like let) -- Check for null with `== null` (no undefined in Cell) -- Use `==` for equality (always strict, no `===`) -- See docs/cell.md for complete language reference - -### Core Systems -1. **Actor System** (scripts/core/engine.js) - - Message passing via `send()`, `$_.receive()` - - Actor spawning/management - - Register-based component system (update, draw, gui, etc.) - -2. **Module System** - - `use()` function for loading modules - - Module paths: `scripts/modules/`, `scripts/modules/ext/` - - Custom QuickJS build with embedded C modules - -3. **Build System** - - Meson build configuration (Makefile is convenience wrapper) - - Multiple platform targets (Windows, macOS, Linux, Web) - - Custom QuickJS build in `subprojects/` - - Uses SDL3 for cross-platform support - -### Engine Entry Points -- `source/prosperon.c` - Main C entry point -- `scripts/core/engine.js` - JavaScript engine initialization for system -- `scripts/core/base.js` has modifications to this Javascript runtime (for example, additions to the base Array, String, etc) - -### Subprojects -- C code has many subprojects, who's source and sometimes documentation can be found in subprojects. subprojects/quickjs/doc has documentation for quickjs - -### Resource System -- Scripts are bundled into `core.zip` during build -- Runtime module loading via PhysFS -- Resource paths checked in order: `/`, `scripts/modules/`, `scripts/modules/ext/` - -### Notable Dependencies -- QuickJS (custom build) - JavaScript runtime -- SDL3 - Platform abstraction -- Chipmunk2D - Physics -- ENet - Networking -- Soloud - Audio -- Tracy - Profiling (when enabled) - -## Development Tips - -### Running Games -```bash -# Build first -make debug - -# Run example from build directory -./build_dbg/prosperon examples/chess - -# Or copy to game directory -cp build_dbg/prosperon examples/chess/ -cd examples/chess -./prosperon -``` - -### Documentation -- Documentation is found in docs -- Documentation for the JS modules loaded with 'use' is docs/api/modules -- .md files directly in docs gives a high level overview -- docs/cell.md documents the Cell language (JavaScript variant used in Prosperon) - -### Shader Development -- Shaders are in `shaders/` directory as HLSL -- Compile script: `shaders/compile.sh` -- Outputs to platform-specific formats: `dxil/`, `msl/`, `spv/` - -### Example Games -Located in `examples/` directory: -- `chess` - Chess implementation (has its own Makefile) -- `pong` - Classic pong game -- `snake` - Snake game -- `tetris` - Tetris clone -- `bunnymark` - Performance test - -### Testing -```bash -# Run all tests -meson test -C build_dbg - -# Run specific test -./build_dbg/prosperon tests/spawn_actor.js -``` - -### Debugging -- Use debug build: `make debug` -- Tracy profiler support when enabled -- Console logging available via `log.console()`, `log.error()`, etc. -- Log files written to `.prosperon/log.txt` - -# Project Structure Notes - -## Core JavaScript Modules - -- JavaScript modules are defined using the MISTUSE macro in jsffi.c -- The `js_os_funcs`, `js_io_funcs`, etc. arrays define the available functions for each module -- New functions are added with MIST_FUNC_DEF(module, function, args_count) - -## File I/O - -- `io.slurp(path)` - Reads a file as text -- `io.slurp(path)` - Reads a file as an ArrayBuffer -- `io.slurpwrite(path, data)` - Writes data (string or ArrayBuffer) to a file -- `io.exists(path)` - Checks if a file exists - -## Script Loading - -- The `use(path)` function in engine.js loads JavaScript modules -- Script loading happens in prosperon.c and the engine.js script -- jsffi.c contains the C hooks for the QuickJS JavaScript engine -- Added functionality for bytecode compilation and loading: - - `os.compile_bytecode(source, filename)` - Compiles JS to bytecode, returns ArrayBuffer - - `os.eval_bytecode(bytecode)` - Evaluates bytecode from an ArrayBuffer - - `compile(scriptPath)` - Compiles a JS file to a .jso bytecode file - - Modified `use()` to check for .jso files before loading .js files - -## QuickJS Bytecode API - -- `JS_Eval` with JS_EVAL_FLAG_COMPILE_ONLY - Compiles without executing -- `JS_WriteObject` with JS_WRITE_OBJ_BYTECODE - Serializes to bytecode -- `JS_ReadObject` with JS_READ_OBJ_BYTECODE - Deserializes and loads bytecode -- Bytecode files use .jso extension alongside .js files - -## Available JavaScript APIs - -### Core APIs -- `actor` - Base prototype for all actor objects -- `$_` - Special global for actor messaging -- `prosperon` - Global engine interface -- `console` - Logging and debugging interface - -### Rendering -- `draw2d` - 2D drawing primitives -- `render` - Low-level rendering operations -- `graphics` - Higher-level graphics utilities -- `camera` - Camera controls and transformations -- `sprite` - Sprite rendering and management - -### Physics and Math -- `math` - Mathematical utilities -- `geometry` - Geometric calculations and shapes -- `transform` - Object transformations - -### Input and Events -- `input` - Mouse, keyboard, and touch handling -- `event` - Event management system - -### Networking -- `enet` - Networking through ENet library -- `http` - HTTP client capabilities - -### Audio -- `sound` - Audio playback using SoLoud - -### Utility Modules -- `time` - Time management and delays - - **Must be imported with `use('time')`** - - No `time.now()` function - use: - - `time.number()` - Number representation of current time - - `time.record()` - Struct representation of current time - - `time.text()` - Text representation of current time -- `io` - File I/O operations -- `json` - JSON parsing and serialization -- `util` - General utilities -- `color` - Color manipulation -- `miniz` - Compression utilities -- `nota` - Structured data format -- `wota` - Serialization format -- `qr` - QR code generation/reading -- `tween` - Animation tweening -- `spline` - Spline calculations -- `imgui` - Immediate mode GUI - -## Game Development Patterns - -### Project Structure -- Game config is typically in `config.js` -- Main entry point is `main.js` -- Resource loading through `resources.js` - -### Actor Pattern Usage -- Create actors with `actor.spawn(script, config)` -- Start actors with `$_.start(callback, script)` - the system automatically sends a greeting, callback receives {type: 'greet', actor: actor_ref} - - No need to manually send greetings - `$_.start` handles this automatically -- Manage actor hierarchy with overlings and underlings -- Schedule actor tasks with `$_.delay()` method -- Clean up with `kill()` and `garbage()` - -### Actor Messaging with Callbacks -When sending a message with a callback, respond by sending to the message itself: -```javascript -// Sender side: -send(actor, {type: 'status'}, response => { - log.console(response); // Handle the response -}); - -// Receiver side: -$_.receiver(msg => { - if (msg.type === 'status') { - send(msg, {status: 'ok'}); // Send response to the message itself - } -}); -``` - -**Critical Rules for Message Callbacks**: -- **A message can only be used ONCE as a send target** - after sending a response to a message, it cannot be used again -- If you need to send multiple updates (like progress), only the download request message should be used for the final response -- Status requests should each get their own individual response -- Actor objects and message headers are completely opaque - never try to access internal properties -- Never access `msg.__HEADER__` or similar - the actor system handles routing internally -- Use `$_.delay()` to schedule work and avoid blocking the message receiver - -### Game Loop Registration -- Register functions like `update`, `draw`, `gui`, etc. -- Set function.layer property to control execution order -- Use `Register` system to manage callbacks - -### Program vs Module Pattern -- Programs are actor scripts that don't return values, they execute top-to-bottom -- Modules are files that return single values (usually objects) that get frozen -- Programs can spawn other programs as underlings -- Programs have lifecycle hooks: awake, update, draw, garbage, etc. - -## Technical Capabilities - -### Graphics Pipeline -- Supports multiple render backends (Direct3D, Metal, Vulkan via SDL3) -- Custom shader system with cross-platform compilation -- Sprite batching for efficient 2D rendering -- Camera systems for both 2D and 3D - -### Asset Support -- Images: PNG, JPG, QOI, etc. -- Audio: Various formats through SoLoud -- Models: Basic 3D model support -- Custom formats: Aseprite animations, etc. - -### Developer Tools -- Built-in documentation system with `cell.DOC` -- Tracy profiler integration for performance monitoring -- Imgui debugging tools -- Console logging with various severity levels - -## Misty Networking Patterns - -Prosperon implements the Misty actor networking model. Understanding these patterns is critical for building distributed applications. - -### Portal Reply Pattern -Portals must reply with an actor object, not application data: -```javascript -// CORRECT: Portal replies with actor -$_.portal(e => { - send(e, $_); // Reply with server actor -}, 5678); - -// WRONG: Portal sends application data -$_.portal(e => { - send(e, {type: 'game_start'}); // This breaks the pattern -}, 5678); -``` - -### Two-Phase Connection Protocol -Proper Misty networking follows a two-phase pattern: - -**Phase 1: Actor Connection** -- Client contacts portal using `$_.contact()` -- Portal replies with an actor object -- This establishes the communication channel - -**Phase 2: Application Communication** -- Client sends application messages to the received actor -- Normal bidirectional messaging begins -- Application logic handles game/service initialization - -### Message Handling Best Practices -Messages should be treated as opaque objects with your application data: - -```javascript -// CORRECT: Store actor references separately -var players = {}; -$_.receiver(msg => { - if (msg.type === 'join_game' && msg.player_id) { - // Store the message for later response - players[msg.player_id] = msg; - // Later, respond to the stored message - send(players[msg.player_id], {type: 'game_start'}); - } -}); - -// WRONG: Trying to access internal message properties -$_.receiver(msg => { - var sender = msg.__HEADER__.replycc; // Never do this! -}); -``` - -### Return ID Lifecycle -- Each reply callback gets a unique return ID -- Return IDs are consumed once and then deleted -- Reusing message objects with return headers causes "Could not find return function" errors -- Always create clean actor references for ongoing communication - - -**Key Implementation Details:** -- `actor_send()` in `scripts/core/engine.js` handles routing based on available actor data -- Actor objects sent in message data automatically get address/port populated when received over network -- Three communication pathways: `os.mailbox_exist()` check → mailbox send → network send -- Actor objects must contain all necessary routing information for transparent messaging - -### Common Networking Bugs -1. **Portal sending application data**: Portal should only establish actor connections -2. **Return ID collision**: Reusing messages with return headers for multiple sends -3. **Mixed phases**: Trying to do application logic during connection establishment -4. **Header pollution**: Using received message objects as actor references -5. **Missing actor address info**: Actor objects in message data need network address population (fixed in engine.js:746-766) - -### Example: Correct Chess Networking -```javascript -// Server: Portal setup -$_.portal(e => { - send(e, $_); // Just reply with actor -}, 5678); - -// Client: Two-phase connection -$_.contact((actor, reason) => { - if (actor) { - opponent = actor; - send(opponent, {type: 'join_game'}); // Phase 2: app messaging - } -}, {address: "localhost", port: 5678}); - -// Server: Handle application messages -$_.receiver(e => { - if (e.type === 'join_game') { - opponent = e.__HEADER__.replycc; - send(opponent, {type: 'game_start', your_color: 'black'}); - } -}); -``` - -## Memory Management - -- When working with a conversational AI system like Claude, it's important to maintain a clean and focused memory -- Regularly review and update memories to ensure they remain relevant and helpful -- Delete or modify memories that are no longer accurate or useful -- Prioritize information that can genuinely assist in future interactions \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 968015c5..00000000 --- a/Dockerfile +++ /dev/null @@ -1,55 +0,0 @@ -# Builder stage -FROM ubuntu:plucky AS builder - -RUN apt-get update && apt-get install -y --no-install-recommends \ - python3 python3-pip \ - libmimalloc-dev \ - libasound2-dev \ - libpulse-dev \ - libudev-dev \ - libwayland-dev \ - wayland-protocols \ - libxkbcommon-dev \ - libx11-dev \ - libxext-dev \ - libxrandr-dev \ - libxcursor-dev \ - libxi-dev \ - libxinerama-dev \ - libxss-dev \ - libegl1-mesa-dev \ - libgl1-mesa-dev \ - cmake \ - ninja-build \ - git \ - build-essential \ - binutils \ - pkg-config \ - meson \ - zip && \ - rm -rf /var/lib/apt/lists/* - -WORKDIR /app -RUN git clone https://gitea.pockle.world/john/prosperon.git -WORKDIR /app/prosperon -RUN git checkout master -RUN meson setup build -Dbuildtype=release -Db_lto=true -Db_lto_mode=thin -Db_ndebug=true -RUN meson compile -C build - -# Runtime stage -FROM ubuntu:latest - -# Install minimal runtime dependencies (e.g., for dynamically linked libraries) -RUN apt-get update && apt-get install -y libstdc++6 && rm -rf /var/lib/apt/lists/* - -# Copy the compiled prosperon binary from the build stage -COPY --from=builder /app/prosperon/build/prosperon /usr/local/bin/prosperon - -# Create an entrypoint script -RUN echo '#!/bin/bash' > /entrypoint.sh && \ - echo '/usr/local/bin/prosperon "$@" &' >> /entrypoint.sh && \ - echo 'tail -f /dev/null' >> /entrypoint.sh && \ - chmod +x /entrypoint.sh - -WORKDIR /workdir -ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index cf17eaa1..00000000 --- a/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -Prosperon Game Engine - -Copyright (c) 2019-2024 John Alanbrook - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -(1) The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -(2) Any games or other derivative software must display the "Prosperon" logo -at near the beginning of the software's startup, before the chief purpose -of the software is underway. - - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/mkdocs.yml b/docs/mkdocs.yml similarity index 100% rename from mkdocs.yml rename to docs/mkdocs.yml diff --git a/requirements.txt b/docs/requirements.txt similarity index 100% rename from requirements.txt rename to docs/requirements.txt diff --git a/emscripten.cross b/emscripten.cross deleted file mode 100644 index fab53c11..00000000 --- a/emscripten.cross +++ /dev/null @@ -1,22 +0,0 @@ -[binaries] -c = 'emcc' -cpp = 'em++' -ar = 'emar' -strip = 'emstrip' -ranlib = 'emranlib' - -[host_machine] -system = 'emscripten' -cpu_family = 'wasm32' -cpu = 'wasm32' -endian = 'little' - -[built-in options] -c_args = ['-sUSE_PTHREADS=0'] -cpp_args = ['-sUSE_PTHREADS=0'] -c_link_args = ['-sALLOW_MEMORY_GROWTH=1', '-sEXPORTED_RUNTIME_METHODS=ccall,cwrap'] -cpp_link_args = ['-sALLOW_MEMORY_GROWTH=1', '-sEXPORTED_RUNTIME_METHODS=ccall,cwrap'] - -[properties] -needs_exe_wrapper = true -sys_root = '/emsdk/upstream/emscripten/cache/sysroot' diff --git a/Info.plist b/help/Info.plist similarity index 100% rename from Info.plist rename to help/Info.plist diff --git a/cell.md b/help/cell.md similarity index 100% rename from cell.md rename to help/cell.md diff --git a/cell2.md b/help/cell2.md similarity index 100% rename from cell2.md rename to help/cell2.md diff --git a/help/cellstructure.md b/help/cellstructure.md new file mode 100644 index 00000000..b56aa514 --- /dev/null +++ b/help/cellstructure.md @@ -0,0 +1,28 @@ +# Cell structure + +Cell doesn't have the notion of a file system; it has packages. Each package is a directory with a cell.toml file. You cannot have nested packages. + +A package is a collection of actors, modules, and other files. + +Packages are stored in a cell shop, in a development environment, located at ~/.cell. + +Inside the shop there is .cell/packages/ + +A package can be a gitea url, like gitea.pockle.world/john/prosperon, which effectively clones to ~/.cell/packages/gitea.pockle.world/john/prosperon + +Or it can be a local absolute path (on computers with a file system), like .cell/packages/User/john/work/prosperon, which is a symlink to the actual directory. + +Cell itself is stored in .cell/core, and can build itself from there. Updating cell involves getting cell from somewhere, and rebuilding it. The cell core is itself a package. + +When an actor or module is requested, it's loaded first from the package, if not found, it checks in packages, and if not found there, it checks in the cell core scripts (.cell/core/scripts). + +Packages can declare aliases for packages, so the "accio" package can say "prosperon = gitea.pockle.world/john/prosperon", and then load "prosperon/sprite". +A module in prosperon can simply load "sprite" to load its own sprite. + +the "cell upgrade" command is a command to upgrade the cell version in a shop. + +## commands +cell update - update all packages in the shop, and builds their code for local use +cell install - install a package +cell remove - remove a package +cell build - build the package in the current directory into a cell executable \ No newline at end of file diff --git a/license.txt b/help/license.txt similarity index 100% rename from license.txt rename to help/license.txt diff --git a/resource.manifest b/help/resource.manifest similarity index 100% rename from resource.manifest rename to help/resource.manifest diff --git a/resource.rc b/help/resource.rc similarity index 100% rename from resource.rc rename to help/resource.rc diff --git a/todo/graphics.md b/help/todo/graphics.md similarity index 100% rename from todo/graphics.md rename to help/todo/graphics.md diff --git a/todo/ops.md b/help/todo/ops.md similarity index 100% rename from todo/ops.md rename to help/todo/ops.md diff --git a/todo/playdate.md b/help/todo/playdate.md similarity index 100% rename from todo/playdate.md rename to help/todo/playdate.md diff --git a/mingw32.cross b/mingw32.cross deleted file mode 100644 index af60c542..00000000 --- a/mingw32.cross +++ /dev/null @@ -1,17 +0,0 @@ -[binaries] -c = 'x86_64-w64-mingw32-gcc' -cpp = 'x86_64-w64-mingw32-g++' -ar = 'x86_64-w64-mingw32-ar' -windres = 'x86_64-w64-mingw32-windres' -strip = 'x86_64-w64-mingw32-strip' -exe_wrapper = 'wine' -pkg-config = 'pkg-config' - -[host_machine] -system = 'windows' -cpu_family = 'x86_64' -cpu = 'x86_64' -endian = 'little' - -[properties] -needs_exe_wrapper = true diff --git a/playdate.cross b/playdate.cross deleted file mode 100644 index 1a942aad..00000000 --- a/playdate.cross +++ /dev/null @@ -1,20 +0,0 @@ -[binaries] -c = 'arm-none-eabi-gcc' -cpp = 'arm-none-eabi-g++' -ar = 'arm-none-eabi-ar' -strip = 'arm-none-eabi-strip' -objcopy = 'arm-none-eabi-objcopy' -ld = 'arm-none-eabi-ld' - -[host_machine] -system = 'playdate' -cpu_family = 'arm' -cpu = 'cortex-m7' -endian = 'little' - -[properties] -needs_exe_wrapper = true - -[built-in options] -c_args = ['-mcpu=cortex-m7', '-mthumb', '-mfloat-abi=hard', '-mfpu=fpv5-sp-d16', '-fno-exceptions'] -c_link_args = ['-mcpu=cortex-m7', '-mthumb', '-mfloat-abi=hard', '-mfpu=fpv5-sp-d16', '-nostartfiles']