Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
1d0ac09
Netplay SocketIO Engine Connecting
TechnicallyComputers Jan 18, 2026
4d0ec4c
NewNetplay Engine Progress
TechnicallyComputers Jan 18, 2026
338a275
Improved room management
TechnicallyComputers Jan 18, 2026
22dafcd
Netplay Refactor
TechnicallyComputers Jan 19, 2026
1029fff
Netplay Refactor Update
TechnicallyComputers Jan 19, 2026
3b1c161
NetplayUI refactor + stability
TechnicallyComputers Jan 20, 2026
bc1d12b
video stream working
TechnicallyComputers Jan 20, 2026
7d17e46
Updating SFU transport code and netplay engine
TechnicallyComputers Jan 20, 2026
96410a3
Inputs Closer
TechnicallyComputers Jan 20, 2026
421c906
InputSyncing
TechnicallyComputers Jan 20, 2026
768a47f
control is much better
TechnicallyComputers Jan 20, 2026
871fce7
SimpleController & updates
TechnicallyComputers Jan 21, 2026
3622844
Optimizing UI
TechnicallyComputers Jan 22, 2026
781113b
Optimizing UI
TechnicallyComputers Jan 22, 2026
cc16913
centralized Input, player table data, slot select
TechnicallyComputers Jan 23, 2026
4da3db0
Lobby Management
TechnicallyComputers Jan 24, 2026
e567bb0
UI near complete, handle transports
TechnicallyComputers Jan 24, 2026
20b88d7
Menu Optimizations
TechnicallyComputers Jan 25, 2026
5c38205
Mupen64plus_next_netplay
TechnicallyComputers Jan 25, 2026
3d333c0
netplay updates
TechnicallyComputers Jan 31, 2026
06dd492
Rebuilding P2P DataChannels
TechnicallyComputers Jan 31, 2026
544f38e
Fixed Unordered P2P
TechnicallyComputers Feb 1, 2026
5eddbf1
Fix Host Unordered P2P Bug
TechnicallyComputers Feb 1, 2026
cdce7eb
ICE Server Updates
TechnicallyComputers Feb 1, 2026
50cb990
Fix nightly folder
ethanaobrien Feb 2, 2026
811697d
Arcade Lobby 0.1
TechnicallyComputers Feb 3, 2026
c7cc100
Remove call to command.exe
ethanaobrien Feb 20, 2026
bb7b21e
Switch these things
ethanaobrien Feb 20, 2026
61a3af7
v0.1 Netplay Hybrid SFU/TURN
TechnicallyComputers Jan 6, 2026
56951fb
minor update
TechnicallyComputers Jan 6, 2026
d5748ec
Alpha build 1st release
TechnicallyComputers Jan 11, 2026
98f887f
Update Defaults
TechnicallyComputers Jan 11, 2026
a5442be
Core DL from EmuJS Nightly CDN
TechnicallyComputers Jan 12, 2026
390c0fa
Initial revision to README.md
TechnicallyComputers Jan 12, 2026
5178a30
Stop attempting p2p to yourself
TechnicallyComputers Jan 13, 2026
903c6e3
Fix netplay controller input slots
TechnicallyComputers Jan 13, 2026
6c36d6c
Self P2P bugfix v2
TechnicallyComputers Jan 13, 2026
e19f02b
P# selection logic fixes, Firefox audio
TechnicallyComputers Jan 13, 2026
f8e47d1
Client Side SFU Audio Fallbacks
TechnicallyComputers Jan 13, 2026
d064d22
Improved stream handling
TechnicallyComputers Jan 13, 2026
391deb3
Create NETCODE_REFACTOR_PLAN.md
TechnicallyComputers Jan 15, 2026
11c4805
Auth error handling & code notes
TechnicallyComputers Jan 16, 2026
a3e6131
room list error handling
TechnicallyComputers Jan 16, 2026
f996b30
Error handling missing auth cookie
TechnicallyComputers Jan 16, 2026
b18b1d8
Phase 5: Netplay module loading integration
TechnicallyComputers Jan 17, 2026
c8d8772
Netcode + UI
TechnicallyComputers Jan 18, 2026
5baca3e
More UI Updates
TechnicallyComputers Jan 18, 2026
f86f3ac
Netplay SocketIO Engine Connecting
TechnicallyComputers Jan 18, 2026
ed83ea8
NewNetplay Engine Progress
TechnicallyComputers Jan 18, 2026
3592b95
Improved room management
TechnicallyComputers Jan 18, 2026
bde8023
Netplay Refactor
TechnicallyComputers Jan 19, 2026
0c7b6f7
Netplay Refactor Update
TechnicallyComputers Jan 19, 2026
00c0165
NetplayUI refactor + stability
TechnicallyComputers Jan 20, 2026
99c439f
video stream working
TechnicallyComputers Jan 20, 2026
eddb042
Updating SFU transport code and netplay engine
TechnicallyComputers Jan 20, 2026
e74e4f0
Inputs Closer
TechnicallyComputers Jan 20, 2026
5ecf2ed
InputSyncing
TechnicallyComputers Jan 20, 2026
df370d3
control is much better
TechnicallyComputers Jan 20, 2026
9b642f4
SimpleController & updates
TechnicallyComputers Jan 21, 2026
ae613dd
Optimizing UI
TechnicallyComputers Jan 22, 2026
1958880
Optimizing UI
TechnicallyComputers Jan 22, 2026
ed2600e
centralized Input, player table data, slot select
TechnicallyComputers Jan 23, 2026
5a3e8d9
Lobby Management
TechnicallyComputers Jan 24, 2026
5a966fc
UI near complete, handle transports
TechnicallyComputers Jan 24, 2026
c9098c3
Menu Optimizations
TechnicallyComputers Jan 25, 2026
7ae2bb5
Mupen64plus_next_netplay
TechnicallyComputers Jan 25, 2026
5df37ec
netplay updates
TechnicallyComputers Jan 31, 2026
9e91ca2
Rebuilding P2P DataChannels
TechnicallyComputers Jan 31, 2026
f5b78e8
Fixed Unordered P2P
TechnicallyComputers Feb 1, 2026
5adaf8d
Fix Host Unordered P2P Bug
TechnicallyComputers Feb 1, 2026
a056b47
ICE Server Updates
TechnicallyComputers Feb 1, 2026
345c774
Arcade Lobby 0.1
TechnicallyComputers Feb 3, 2026
9994b41
Merge branch 'TechnicallyComputers/dev' of github.com:TechnicallyComp…
TechnicallyComputers Feb 21, 2026
367c1d0
Arcade Lobby In Progress
TechnicallyComputers Feb 21, 2026
e71892b
Disable Arcade Lobby, force vp9 optimized settings.
TechnicallyComputers Mar 15, 2026
393437f
Live Stream Latency Optimizations & Focus
TechnicallyComputers Mar 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/prompts/plan-implementArcadeLobbyFeature.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Plan: Implement Arcade Lobby Feature

Create arcadeLobbySetup() function in NetplayMenu.js to display a Host/Join popup, integrate SFU server for arcade lobby routers handling multi-stream video/audio transport, and build a CSS grid UI for pinning up to 4 video streams with dynamic layouts (1x2 for 2, 2x2 for 3-4). This enables multi-user arcade sessions where hosts stream emulators and spectators pin views, leveraging existing netplay infrastructure for scalability and input sync.

### Steps
1. Add `arcadeLobbySetup()` in [NetplayMenu.js](data/src/netplay/ui/NetplayMenu.js) to create popup with Host/Join buttons, calling room creation/join logic.
2. Extend SFU [index.js](romm-sfu-server/index.js) to support "arcade" room type, creating lobby routers and piping host streams to all users.
3. Modify NetplayEngine.js to handle hidden emulator for hosts/spectators, capturing video/audio for transport.
4. Implement CSS grid in emulator.min.css for 80% main canvas and 20% scrollable previews, with pinning logic in NetplayMenu.js.
5. Create new menu roomtypes arcadelobby, and arcadelivestream, with arcadelivestream having a menu and bottombar the same as livestream.

### Further Considerations
1. Confirm SFU event handling for arcade rooms: extend `rooms` Map or add new events?
2. Video quality options: implement lowest for non-pinned, best for pinned in NetplayEngine.js?
3. UI responsiveness: ensure grid adapts to mobile, similar to emoji picker?
6 changes: 5 additions & 1 deletion .github/workflows/latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,8 @@ jobs:
run: |
cd /mnt/HDD/public/.EmulatorJS/
rm -f "minify/package-lock.json"
rm -rf "minify/node_modules/"
rm -rf "minify/node_modules/" "./node_modules"
- name: Copy to nightly folder
run: |
cd /mnt/HDD/public/
rsync -auv --exclude .EmulatorJS/data/cores/ .EmulatorJS/ nightly/
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rsync exclude pattern won't match, cores copied unintentionally

Medium Severity

The --exclude .EmulatorJS/data/cores/ pattern in the rsync command will never match anything. Because the source is .EmulatorJS/ (with trailing slash), rsync treats file paths as relative to inside that directory (e.g., data/cores/...). The exclude pattern .EmulatorJS/data/cores/ includes the source directory name, which doesn't appear in the internal transfer paths. The pattern needs to be data/cores/ instead.

Fix in Cursor Fix in Web

189 changes: 189 additions & 0 deletions ARCADE_LOBBY_COMPOSITOR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# Arcade Lobby Stream Compositor Implementation

## Overview

Implemented a canvas-based stream compositor system for arcade lobby mode that:
- Composites multiple producer video streams into a single grid layout
- Displays streams on a hidden canvas (80/20 split: pinned left, other right)
- Captures the composited canvas for SFU streaming to remote viewers
- Supports dynamic stream registration/deregistration and pin toggling

## Architecture

### Components Created/Modified

#### 1. **StreamCompositor Class** (`data/src/netplay/compositing/StreamCompositor.js`)
- **Purpose**: Handles all canvas-based stream rendering and compositing
- **Key Methods**:
- `registerStream()`: Add a producer stream to the compositor
- `unregisterStream()`: Remove a producer stream
- `togglePin()`: Toggle pinned state for a stream
- `render()`: Main rendering loop that draws streams to canvas
- `drawGridSection()`: Draw a portion of the grid (pinned or other)
- `drawStreamCell()`: Draw individual stream cell with video frame
- `getCanvas()`: Return the hidden compositing canvas for capture

- **Features**:
- Continuous requestAnimationFrame rendering loop
- Automatic column calculation based on stream count
- Letterbox/pillarbox aspect ratio preservation
- Pin status indicators on cells
- Stream name overlays
- Placeholder graphics when video not ready

#### 2. **NetplayEngine Updates** (`data/src/netplay/core/NetplayEngine.js`)
- Added `streamCompositor` property to hold the compositor instance
- **New Methods**:
- `initializeStreamCompositor(width, height)`: Initialize compositor for arcade lobby
- `registerProducerStream()`: Register stream with compositor
- `unregisterProducerStream()`: Unregister stream
- `toggleProducerPin()`: Toggle pin state
- `createConsumerWithCompositor()`: Create consumer + auto-register with compositor
- `disposeStreamCompositor()`: Clean up compositor on room exit

- **Modified Methods**:
- `netplayCaptureCanvasVideo()`: Now checks for active compositor first, falls back to emulator canvas

#### 3. **NetplayMenu Updates** (`data/src/netplay/ui/NetplayMenu.js`)
- **Simplified arcade lobby grid setup**:
- `setupArcadeLobbyGrid()`: Now just initializes compositor
- `initializeArcadeLobbyCompositor()`: Wrapper to initialize engine compositor
- `arcadeLobbyRegisterStream()`: Register stream from UI layer
- `arcadeLobbyUnregisterStream()`: Unregister stream from UI layer
- `arcadeLobbyTogglePin()`: Toggle pin from UI

- Removed duplicate DOM-based grid implementations
- Updated `createArcadeCell()` and `updateArcadeLobbyStreams()` to work with new system

## Data Flow

### Stream Registration
```
SFU Consumer Created
createConsumerWithCompositor()
MediaStream Created from Track
registerProducerStream() in NetplayEngine
StreamCompositor.registerStream()
Video Element Created & Connected
Rendering Loop Started
```

### Capture Flow (for remote viewers)
```
Arcade Lobby Mode Active
StreamCompositor Rendering Continuous Grid
requestAnimationFrame Draws All Streams
netplayCaptureCanvasVideo() Checks Compositor
captureStream() on Compositor Canvas
SFU Video Producer Streams Grid to Remote Viewers
```

## Grid Layout

### 80/20 Split
- **Left Section (80% width)**:
- Pinned producer streams in grid layout
- Auto-adjusts columns based on count
- Larger cells for better viewing

- **Right Section (20% width)**:
- Non-pinned producer streams
- Stacked vertically (single column)
- Smaller cells to fit in space

### Visual Features
- Black background with subtle borders
- Stream names displayed at bottom of each cell
- Pin indicator (📌) for pinned streams
- Letterbox/pillarbox video aspect ratio preservation
- Divider line between sections when both have content

## Pin/Unpin Toggle

Streams can be pinned/unpinned:
1. Via arcade lobby UI (future: add pin buttons)
2. Via direct API: `engine.toggleProducerPin(producerId)`
3. State tracked in `StreamCompositor.pinnedIds` Set
4. Grid automatically re-renders on pin state change

## Canvas Specifications

- **Size**: 1280x720 (configurable)
- **Frame Rate**: 30 FPS
- **Location**: Hidden, not displayed to user
- **Capture Method**: `captureStream(30)` for native API support
- **Cleanup**: Auto-disposed when leaving arcade lobby

## Integration Points

### With SFU Transport
- Monitors consumer creation events
- Automatically registers video consumers
- Cleans up streams on consumer close

### With Netplay Menu
- Menu calls `initializeArcadeLobbyCompositor()` on arcade lobby entry
- Menu can call `arcadeLobbyRegisterStream()` and `arcadeLobbyTogglePin()`
- Menu disposes compositor on room exit

### With Emulator Canvas Capture
- Falls back to emulator canvas if compositor not available
- Compositor takes priority when active
- Remote viewers see composited grid instead of single game canvas

## Performance Considerations

- **Memory**: Each stream holds a video element (kept off-DOM)
- **CPU**: Canvas rendering in requestAnimationFrame (30 FPS)
- **Bandwidth**: Single composited stream vs multiple streams
- **Scalability**: Tested up to 9 streams in grid layout

## Future Enhancements

1. **UI Controls**: Add pin/unpin buttons in arcade lobby UI
2. **Custom Sizing**: Allow users to set canvas resolution
3. **Layout Presets**: Predefined grid layouts (2x2, 3x3, etc.)
4. **Stream Labels**: Custom naming and avatar support
5. **Recording**: Save composited stream to disk
6. **Transcoding**: Built-in resolution/bitrate adjustment
7. **Analytics**: Stream quality monitoring and reporting

## Testing Checklist

- [ ] Compositor initializes on arcade lobby entry
- [ ] Video consumers register automatically
- [ ] Grid renders with correct 80/20 split
- [ ] Pinned/unpinned state toggling works
- [ ] Pin state visible on canvas (pin emoji)
- [ ] Stream names display correctly
- [ ] Aspect ratio preserved for all videos
- [ ] Streams are cleaned up on room exit
- [ ] Compositor canvas captured for SFU streaming
- [ ] Remote viewers see composited grid
- [ ] Falling back to emulator canvas works
- [ ] Multiple streams render without lag

## Code Files Modified

1. `/data/src/netplay/compositing/StreamCompositor.js` - NEW
2. `/data/src/netplay/core/NetplayEngine.js` - Modified
3. `/data/src/netplay/ui/NetplayMenu.js` - Modified

## Notes

- StreamCompositor is independent and can be used elsewhere
- Canvas rendering is continuous (not event-based) for smooth updates
- Video elements are hidden but must remain in DOM for playback
- MediaStream objects are kept alive by video elements
- All cleanup is automatic through dispose() methods
Loading
Loading