# ggj26-comp Extracted components from ggj26: build system, logging, and hub-and-spoke networking. ## Components ### Build System Makefile-based build system for MoonScript/Lua projects: - Compiles `.moon` files to `.lua` - Embeds JavaScript files with jshint validation - Runs tests with busted **Usage:** ```bash make # Build all sources make test # Run tests make clean # Clean build artifacts ``` ### Logging Utility `src/log.moon` - Singleton logger with level-based and tag-based filtering. **Features:** - Log levels: debug, info, warn, error, panic - Tag-based filtering for organizing logs - Observer pattern for real-time monitoring - Message stream with time tracking **Usage:** ```lua log = require "log" -- Log with level and tags log.info("User connected", {"network", "auth"}) log.error("Connection failed", {"network"}) -- Filter by level log.of_level("error", function(msg) print(msg.message) end) -- Filter by tags log.of_tags({"network"}, function(msg) print(msg.message) end) -- Listen to all messages log.listen(function(msg) if msg.level == "panic" then -- handle critical error end end) ``` ### Networking - Hub and Spoke Model #### Core (`src/net.moon`) Low-level WebRTC peer connection abstraction using PeerJS: - Peer creation and connection management - Message validation and routing - JavaScript bridge for browser integration #### Hub (`src/hub.moon`) Server-side hub that manages client connections: - Maintains registry of connected clients - Routes messages between clients (unicast, multicast, broadcast) - Connection/disconnection event handling **Usage:** ```lua Hub = require("hub").Hub hub = Hub() hub:initialize() -- Get hub ID to share with clients hub_id = hub:get_peer_id() -- Listen for client events hub:on_connect(function(client_id) print("Client connected:", client_id) end) hub:on_disconnect(function(client_id) print("Client disconnected:", client_id) end) -- Update loop function love.update(dt) hub:pump() end ``` #### Client (`src/client.moon`) Client-side with router registration system: - Connect to hub - Register message handlers (routers) by message type - Send messages to specific clients or broadcast **Usage:** ```lua Client = require("client").Client client = Client("player1") -- Connect to hub client:connect_to_hub(hub_id) -- Register router for message type client:register_router("chat", function(from_id, data) print("Chat from", from_id, ":", data.message) end) client:register_router("game_state", function(from_id, data) -- handle game state update end) -- Send messages client:send_to(other_client_id, "chat", {message = "Hello!"}) client:broadcast("game_state", {position = {x=10, y=20}}) -- Update loop function love.update(dt) client:pump() end ``` #### Testing Utilities (`src/channel.moon`) Channel abstractions for testing: - `SimpleChannel` - Basic in-memory channel - `FaultyChannel` - Simulates network latency and packet loss ### Utility Functions (`src/util.lua`) Helper functions including: - `typecheck(tbl, ...)` - Validate table fields and types - `peer_to_code(str)` / `code_to_peer(str)` - Convert peer IDs to shareable codes ## Architecture ### Hub-and-Spoke Networking ``` [Client A] | v [Hub] ←-→ [Client B] | v [Client C] ``` - **Hub**: Single peer that accepts all client connections - **Clients**: Connect to hub, register message handlers (routers) - **Message Flow**: Client → Hub → Target Client(s) - **Routing**: Hub handles unicast, multicast, and broadcast This replaces the previous RAFT-based peer-to-peer model with a simpler, centralized approach suitable for game lobbies and small multiplayer sessions. ## Requirements - MoonScript compiler (`moonc`) - Lua - Busted (for unit testing) - Node.js/npm (for jshint) - Python 3.8+ (for integration testing) - Chrome browser (for Selenium tests) ## Installation ```bash # Install Node.js dependencies npm install # Install Python test dependencies (for integration testing) pip install -r requirements-test.txt ``` ## Testing ### Run All Tests Run both unit tests and integration tests: ```bash make test1 ``` ### Unit Tests (Lua/Busted) Run Lua unit tests with busted: ```bash make test ``` ### Integration Tests (Selenium) Run browser-based integration tests: ```bash # Using Make make test-integration # Run with visible browser make test-integration-headless # Run in headless mode ``` Or use the PowerShell script: ```powershell .\run-integration-tests.ps1 # Run all tests .\run-integration-tests.ps1 -Headless # Headless mode .\run-integration-tests.ps1 -Smoke # Smoke tests only .\run-integration-tests.ps1 -UI # UI interaction tests ``` Or use pytest directly: ```bash pytest # Run all integration tests pytest -m smoke # Run smoke tests only pytest -v # Verbose output ``` See `tests/integration/README.md` for more details on integration testing.