feat: Implement networking and collaboration features for z3ed
- Introduced a comprehensive networking system for real-time collaboration across the yaze app, z3ed CLI, and yaze-server using WebSocket. - Added `WebSocketClient` and `CollaborationService` classes to manage connections, session hosting, proposal submissions, and automatic ROM synchronization. - Enhanced the z3ed CLI with commands for connecting to the server, submitting proposals, and checking approval statuses. - Updated documentation to include detailed usage instructions for the new networking features and collaboration workflows. - Improved CMake configuration to support necessary libraries for networking, including JSON and OpenSSL.
This commit is contained in:
@@ -1,252 +1,181 @@
|
||||
# API Reference
|
||||
|
||||
Comprehensive reference for the YAZE C API and C++ interfaces.
|
||||
This document provides a reference for the yaze C and C++ APIs, intended for developers creating extensions or contributing to the core application.
|
||||
|
||||
## C API (`incl/yaze.h`, `incl/zelda.h`)
|
||||
## C API (`incl/yaze.h`)
|
||||
|
||||
The C API provides a stable, language-agnostic interface for interacting with yaze's core functionalities.
|
||||
|
||||
### Core Library Functions
|
||||
```c
|
||||
// Initialization
|
||||
/**
|
||||
* @brief Initializes the yaze library. Must be called before any other API function.
|
||||
* @return YAZE_OK on success, or an error code on failure.
|
||||
*/
|
||||
yaze_status yaze_library_init(void);
|
||||
|
||||
/**
|
||||
* @brief Shuts down the yaze library and releases all resources.
|
||||
*/
|
||||
void yaze_library_shutdown(void);
|
||||
|
||||
// Version management
|
||||
/**
|
||||
* @brief Gets the current version of the yaze library as a string.
|
||||
* @return A constant string representing the version (e.g., "0.3.2").
|
||||
*/
|
||||
const char* yaze_get_version_string(void);
|
||||
int yaze_get_version_number(void);
|
||||
bool yaze_check_version_compatibility(const char* expected_version);
|
||||
|
||||
// Status utilities
|
||||
const char* yaze_status_to_string(yaze_status status);
|
||||
```
|
||||
|
||||
### ROM Operations
|
||||
```c
|
||||
// ROM loading and management
|
||||
/**
|
||||
* @brief Loads a Zelda 3 ROM from a file.
|
||||
* @param filename The path to the ROM file.
|
||||
* @return A pointer to a zelda3_rom object, or NULL on failure.
|
||||
*/
|
||||
zelda3_rom* yaze_load_rom(const char* filename);
|
||||
|
||||
/**
|
||||
* @brief Unloads a ROM and frees associated memory.
|
||||
* @param rom A pointer to the zelda3_rom object to unload.
|
||||
*/
|
||||
void yaze_unload_rom(zelda3_rom* rom);
|
||||
|
||||
/**
|
||||
* @brief Saves a ROM to a file.
|
||||
* @param rom A pointer to the ROM to save.
|
||||
* @param filename The path to save the file to.
|
||||
* @return YAZE_OK on success.
|
||||
*/
|
||||
yaze_status yaze_save_rom(zelda3_rom* rom, const char* filename);
|
||||
bool yaze_is_rom_modified(const zelda3_rom* rom);
|
||||
```
|
||||
|
||||
### Graphics Operations
|
||||
```c
|
||||
// SNES color management
|
||||
snes_color yaze_rgb_to_snes_color(uint8_t r, uint8_t g, uint8_t b);
|
||||
void yaze_snes_color_to_rgb(snes_color color, uint8_t* r, uint8_t* g, uint8_t* b);
|
||||
|
||||
// Bitmap operations
|
||||
yaze_bitmap* yaze_create_bitmap(int width, int height, uint8_t bpp);
|
||||
void yaze_free_bitmap(yaze_bitmap* bitmap);
|
||||
```
|
||||
|
||||
### Palette System
|
||||
```c
|
||||
// Palette creation and management
|
||||
snes_palette* yaze_create_palette(uint8_t id, uint8_t size);
|
||||
void yaze_free_palette(snes_palette* palette);
|
||||
snes_palette* yaze_load_palette_from_rom(const zelda3_rom* rom, uint8_t palette_id);
|
||||
```
|
||||
|
||||
### Message System
|
||||
```c
|
||||
// Message handling
|
||||
zelda3_message* yaze_load_message(const zelda3_rom* rom, uint16_t message_id);
|
||||
void yaze_free_message(zelda3_message* message);
|
||||
yaze_status yaze_save_message(zelda3_rom* rom, const zelda3_message* message);
|
||||
```
|
||||
|
||||
## C++ API
|
||||
|
||||
The C++ API offers a more powerful, object-oriented interface. The primary entry point for many operations is the `yaze::core::AsarWrapper` class.
|
||||
|
||||
### AsarWrapper (`src/app/core/asar_wrapper.h`)
|
||||
|
||||
Complete cross-platform ROM patching with assembly code support, symbol extraction, and validation.
|
||||
This class provides a complete, cross-platform interface for applying assembly patches, extracting symbols, and validating assembly code using the Asar library.
|
||||
|
||||
#### Quick Examples
|
||||
#### CLI Examples (`z3ed`)
|
||||
|
||||
While the `AsarWrapper` can be used programmatically, the `z3ed` CLI is the most common way to interact with it.
|
||||
|
||||
**Command Line**
|
||||
```bash
|
||||
# Apply assembly patch to ROM
|
||||
# Apply an assembly patch to a ROM file.
|
||||
z3ed asar my_patch.asm --rom=zelda3.sfc
|
||||
|
||||
# Extract symbols without patching
|
||||
z3ed extract my_patch.asm
|
||||
|
||||
# Validate assembly syntax
|
||||
z3ed validate my_patch.asm
|
||||
# For more complex operations, use the AI agent.
|
||||
z3ed agent chat --rom zelda3.sfc
|
||||
```
|
||||
> **Prompt:** "Apply the patch `mosaic_change.asm` to my ROM."
|
||||
|
||||
**C++ API**
|
||||
#### C++ API Example
|
||||
```cpp
|
||||
#include "app/core/asar_wrapper.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
// Assume rom_data is a std::vector<uint8_t> holding the ROM content.
|
||||
yaze::core::AsarWrapper wrapper;
|
||||
wrapper.Initialize();
|
||||
|
||||
// Apply patch to ROM
|
||||
// Apply a patch to the ROM data in memory.
|
||||
auto result = wrapper.ApplyPatch("patch.asm", rom_data);
|
||||
|
||||
if (result.ok() && result->success) {
|
||||
// On success, print the symbols generated by the patch.
|
||||
for (const auto& symbol : result->symbols) {
|
||||
std::cout << symbol.name << " @ $" << std::hex << symbol.address << std::endl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### AsarWrapper Class
|
||||
#### Class Definition
|
||||
```cpp
|
||||
namespace yaze::core {
|
||||
|
||||
class AsarWrapper {
|
||||
public:
|
||||
// Initialization
|
||||
/** @brief Initializes the Asar library. */
|
||||
absl::Status Initialize();
|
||||
|
||||
/** @brief Shuts down the Asar library. */
|
||||
void Shutdown();
|
||||
bool IsInitialized() const;
|
||||
|
||||
// Core functionality
|
||||
|
||||
/**
|
||||
* @brief Applies an assembly patch to ROM data.
|
||||
* @param patch_path Path to the main .asm file.
|
||||
* @param rom_data A vector of bytes representing the ROM data.
|
||||
* @param include_paths Optional paths for Asar to search for included files.
|
||||
* @return A StatusOr containing the patch result, including success status and symbols.
|
||||
*/
|
||||
absl::StatusOr<AsarPatchResult> ApplyPatch(
|
||||
const std::string& patch_path,
|
||||
std::vector<uint8_t>& rom_data,
|
||||
const std::vector<std::string>& include_paths = {});
|
||||
|
||||
|
||||
/**
|
||||
* @brief Extracts symbols from an assembly file without patching.
|
||||
* @param asm_path Path to the .asm file.
|
||||
* @return A StatusOr containing a vector of extracted symbols.
|
||||
*/
|
||||
absl::StatusOr<std::vector<AsarSymbol>> ExtractSymbols(
|
||||
const std::string& asm_path,
|
||||
const std::vector<std::string>& include_paths = {});
|
||||
|
||||
// Symbol management
|
||||
std::optional<AsarSymbol> FindSymbol(const std::string& name);
|
||||
std::vector<AsarSymbol> GetSymbolsAtAddress(uint32_t address);
|
||||
std::map<std::string, AsarSymbol> GetSymbolTable();
|
||||
|
||||
// Utility functions
|
||||
|
||||
/**
|
||||
* @brief Validates the syntax of an assembly file.
|
||||
* @param asm_path Path to the .asm file.
|
||||
* @return An OK status if syntax is valid, or an error status if not.
|
||||
*/
|
||||
absl::Status ValidateAssembly(const std::string& asm_path);
|
||||
std::string GetVersion();
|
||||
void Reset();
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace yaze::core
|
||||
```
|
||||
|
||||
#### Error Handling
|
||||
## Data Structures
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `Unknown command` | Invalid opcode | Check 65816 instruction reference |
|
||||
| `Label not found` | Undefined label | Define the label or check spelling |
|
||||
| `Invalid hex value` | Bad hex format | Use `$1234` format |
|
||||
| `Buffer too small` | ROM needs expansion | Check if ROM needs to be larger |
|
||||
|
||||
|
||||
### Data Structures
|
||||
|
||||
#### ROM Version Support
|
||||
```c
|
||||
typedef enum zelda3_version {
|
||||
ZELDA3_VERSION_US = 1,
|
||||
ZELDA3_VERSION_JP = 2,
|
||||
ZELDA3_VERSION_SD = 3,
|
||||
ZELDA3_VERSION_RANDO = 4,
|
||||
// Legacy aliases maintained for compatibility
|
||||
US = ZELDA3_VERSION_US,
|
||||
JP = ZELDA3_VERSION_JP,
|
||||
SD = ZELDA3_VERSION_SD,
|
||||
RANDO = ZELDA3_VERSION_RANDO,
|
||||
} zelda3_version;
|
||||
```
|
||||
|
||||
#### SNES Graphics
|
||||
### `snes_color`
|
||||
Represents a 15-bit SNES color, composed of 5 bits for each red, green, and blue component.
|
||||
```c
|
||||
typedef struct snes_color {
|
||||
uint16_t raw; // Raw 15-bit SNES color
|
||||
uint8_t red; // Red component (0-31)
|
||||
uint8_t green; // Green component (0-31)
|
||||
uint8_t blue; // Blue component (0-31)
|
||||
uint16_t raw; //!< Raw 15-bit BGR color value (0bbbbbgggggrrrrr).
|
||||
uint8_t red; //!< Red component (0-31).
|
||||
uint8_t green; //!< Green component (0-31).
|
||||
uint8_t blue; //!< Blue component (0-31).
|
||||
} snes_color;
|
||||
|
||||
typedef struct snes_palette {
|
||||
uint8_t id; // Palette ID
|
||||
uint8_t size; // Number of colors
|
||||
snes_color* colors; // Color array
|
||||
} snes_palette;
|
||||
```
|
||||
|
||||
#### Message System
|
||||
### `zelda3_message`
|
||||
Represents an in-game text message.
|
||||
```c
|
||||
typedef struct zelda3_message {
|
||||
uint16_t id; // Message ID (0-65535)
|
||||
uint32_t rom_address; // Address in ROM
|
||||
uint16_t length; // Length in bytes
|
||||
uint8_t* raw_data; // Raw ROM data
|
||||
char* parsed_text; // Decoded UTF-8 text
|
||||
bool is_compressed; // Compression flag
|
||||
uint8_t encoding_type; // Encoding type
|
||||
} zelda3_message;
|
||||
uint16_t id; //!< The message ID (0-65535).
|
||||
uint32_t rom_address; //!< The address of the message data in the ROM.
|
||||
uint16_t length; //!< The length of the raw message data in bytes.
|
||||
uint8_t* raw_data; //!< A pointer to the raw, compressed message data.
|
||||
char* parsed_text; //!< The decoded, human-readable UTF-8 text.
|
||||
bool is_compressed; //!< Flag indicating if the message data is compressed.
|
||||
}
|
||||
zelda3_message;
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Status Codes
|
||||
```c
|
||||
typedef enum yaze_status {
|
||||
YAZE_OK = 0, // Success
|
||||
YAZE_ERROR_UNKNOWN = -1, // Unknown error
|
||||
YAZE_ERROR_INVALID_ARG = 1, // Invalid argument
|
||||
YAZE_ERROR_FILE_NOT_FOUND = 2, // File not found
|
||||
YAZE_ERROR_MEMORY = 3, // Memory allocation failed
|
||||
YAZE_ERROR_IO = 4, // I/O operation failed
|
||||
YAZE_ERROR_CORRUPTION = 5, // Data corruption detected
|
||||
YAZE_ERROR_NOT_INITIALIZED = 6, // Component not initialized
|
||||
} yaze_status;
|
||||
```
|
||||
The C API uses an enum `yaze_status` for error handling, while the C++ API uses `absl::Status` and `absl::StatusOr`.
|
||||
|
||||
### Error Handling Pattern
|
||||
### C API Error Pattern
|
||||
```c
|
||||
yaze_status status = yaze_library_init();
|
||||
if (status != YAZE_OK) {
|
||||
printf("Failed to initialize YAZE: %s\n", yaze_status_to_string(status));
|
||||
fprintf(stderr, "Failed to initialize YAZE: %s\n", yaze_status_to_string(status));
|
||||
return 1;
|
||||
}
|
||||
|
||||
zelda3_rom* rom = yaze_load_rom("zelda3.sfc");
|
||||
if (rom == nullptr) {
|
||||
printf("Failed to load ROM file\n");
|
||||
return 1;
|
||||
}
|
||||
// ... operations ...
|
||||
|
||||
// Use ROM...
|
||||
yaze_unload_rom(rom);
|
||||
yaze_library_shutdown();
|
||||
```
|
||||
|
||||
## Extension System
|
||||
|
||||
### Plugin Architecture
|
||||
```c
|
||||
typedef struct yaze_extension {
|
||||
const char* name; // Extension name
|
||||
const char* version; // Version string
|
||||
const char* description; // Description
|
||||
const char* author; // Author
|
||||
int api_version; // Required API version
|
||||
|
||||
yaze_status (*initialize)(yaze_editor_context* context);
|
||||
void (*cleanup)(void);
|
||||
uint32_t (*get_capabilities)(void);
|
||||
} yaze_extension;
|
||||
```
|
||||
|
||||
### Capability Flags
|
||||
```c
|
||||
#define YAZE_EXT_CAP_ROM_EDITING 0x0001 // ROM modification
|
||||
#define YAZE_EXT_CAP_GRAPHICS 0x0002 // Graphics operations
|
||||
#define YAZE_EXT_CAP_AUDIO 0x0004 // Audio processing
|
||||
#define YAZE_EXT_CAP_SCRIPTING 0x0008 // Scripting support
|
||||
#define YAZE_EXT_CAP_IMPORT_EXPORT 0x0010 // Data import/export
|
||||
```
|
||||
|
||||
## Backward Compatibility
|
||||
|
||||
All existing code continues to work without modification due to:
|
||||
- Legacy enum aliases (`US`, `JP`, `SD`, `RANDO`)
|
||||
- Original struct field names maintained
|
||||
- Duplicate field definitions for old/new naming conventions
|
||||
- Typedef aliases for renamed types
|
||||
|
||||
@@ -2,61 +2,59 @@
|
||||
|
||||
**Last Updated: October 4, 2025**
|
||||
|
||||
This document outlines the development roadmap for YAZE. The project has made significant strides in core features, AI integration, and testing infrastructure. The immediate focus is on stabilizing the test suite and completing key editor functionalities.
|
||||
This document outlines the development roadmap for yaze. The project has achieved stability in its core editors and testing infrastructure. The focus now shifts to completing advanced AI features, polishing UI/UX, and expanding editor capabilities.
|
||||
|
||||
## Current Focus: Stability & Core Features
|
||||
## Current Focus: AI & Editor Polish
|
||||
|
||||
The highest priority is to fix the broken test suites to ensure the stability and correctness of the existing, largely complete, feature set. Alongside this, work will continue on completing the core AI and editor functionalities.
|
||||
With the core systems stable, the immediate priority is to enhance the `z3ed` AI agent, finalize the Tile16 editor, and improve the user experience.
|
||||
|
||||
---
|
||||
|
||||
## 0.4.X (Next Major Release) - Stability & Core Tooling
|
||||
## 0.4.X (Next Major Release) - Advanced Tooling & UX
|
||||
|
||||
### Priority 1: Testing & Stability (BLOCKER)
|
||||
- **Fix Dungeon Editor Test Suite**: Resolve the critical `SIGBUS` and `SIGSEGV` crashes that are blocking all integration tests for the dungeon system.
|
||||
- **Refactor Integration Tests**: Migrate tests from the unstable `MockRom` to use the `TestRomManager` with real ROM files, following the pattern set by the passing rendering tests.
|
||||
- **Expand E2E Coverage**: Create a comprehensive end-to-end smoke test for the Dungeon Editor and expand coverage for the Overworld editor.
|
||||
### Priority 1: Editor Features & UX
|
||||
- **Tile16 Palette System**: Resolve the remaining color consistency issues in the Tile16 editor's source tile view and implement the palette-switching functionality.
|
||||
- **Overworld Sprite Editing**: Complete the workflow for adding, removing, and moving sprites directly on the overworld canvas.
|
||||
- **Dungeon Editor UI**: Add human-readable labels for rooms/entrances and implement tab management for a better multi-room workflow.
|
||||
- **Performance**: Address the slow initial load time (~2.6 seconds) by implementing lazy loading for rooms.
|
||||
|
||||
### Priority 2: `z3ed` AI Agent
|
||||
- **Complete Live LLM Testing**: Verify and harden the function-calling loop with live Ollama and Gemini models.
|
||||
- **Enhance GUI Chat Widget**: Implement state persistence and integrate proposal review shortcuts directly into the editor's chat window.
|
||||
- **Expand Agent Toolset**: Add new read-only tools for inspecting dialogue, sprite properties, and other game resources.
|
||||
- **Live LLM Hardening**: Finalize testing of the native Gemini function-calling loop and the proactive v3 system prompt.
|
||||
- **AI-Driven Editing**: Integrate the AI with the GUI test harness to allow for automated, mouse-driven edits based on natural language commands.
|
||||
- **Expand Agent Toolset**: Add new read-only tools for inspecting dialogue, music data, and sprite properties.
|
||||
|
||||
### Priority 3: Editor Features
|
||||
- **Dungeon Editor**: Implement missing features identified from the ZScream comparison, such as custom collision and object limits tracking.
|
||||
- **Overworld Sprites**: Complete the sprite editing workflow, including adding, removing, and moving sprites on the canvas.
|
||||
- **Sprite Property Editor**: Create a UI to edit sprite attributes and behavior.
|
||||
### Priority 3: Testing & Stability
|
||||
- **Windows Validation**: Perform a full testing cycle on Windows to validate the `z3ed` CLI, GUI test harness, and collaboration features.
|
||||
- **Expand E2E Coverage**: Create comprehensive end-to-end smoke tests for the Dungeon and Overworld editors.
|
||||
|
||||
---
|
||||
|
||||
## 0.5.X - Feature Expansion
|
||||
|
||||
- **Plugin Architecture**: Design and implement the initial framework for community-developed extensions and custom tools.
|
||||
- **Advanced Graphics Editing**:
|
||||
- Finalize the Tile16 Editor palette system, fixing all known color consistency bugs.
|
||||
- Implement functionality to edit and re-import full graphics sheets.
|
||||
- **Advanced Graphics Editing**: Implement functionality to edit and re-import full graphics sheets.
|
||||
- **`z3ed` AI Agent Enhancements**:
|
||||
- **Collaborative Sessions**: Investigate and implement infrastructure for multi-user collaborative editing and AI interaction.
|
||||
- **Collaborative Sessions**: Enhance the network collaboration mode with shared AI proposals and ROM synchronization.
|
||||
- **Multi-modal Input**: Integrate screenshot capabilities to send visual context to Gemini for more accurate, context-aware commands.
|
||||
|
||||
---
|
||||
|
||||
## 0.6.X - Polish & Integration
|
||||
## 0.6.X - Content & Integration
|
||||
|
||||
- **Cross-Platform Stability**: Conduct full testing and bug fixing cycles for Windows and Linux to ensure a stable experience equivalent to macOS.
|
||||
- **Advanced Content Editors**:
|
||||
- Implement a user interface for the music editing system.
|
||||
- Enhance the Hex Editor with better search and data interpretation features.
|
||||
- **Documentation Overhaul**:
|
||||
- Implement a system to auto-generate C++ API documentation.
|
||||
- Implement a system to auto-generate C++ API documentation from Doxygen comments.
|
||||
- Write a comprehensive user guide for ROM hackers, covering all major editor workflows.
|
||||
|
||||
---
|
||||
|
||||
## 0.7.X and Beyond - Path to 1.0
|
||||
## Recently Completed (v0.3.2)
|
||||
|
||||
- **Performance Optimization**: Implement high-priority items from the graphics performance plan, such as lazy loading of graphics and streaming assets from the ROM.
|
||||
- **UI/UX Refinements**: Improve UI consistency, iconography, and overall layout based on user feedback.
|
||||
- **Beta Release**: Code freeze on major features to focus on bug fixing and final polish.
|
||||
- **1.0 Stable Release**: Final, production-ready version with a comprehensive changelog.
|
||||
- ✅ **Dungeon Editor Stability**: Fixed all critical crashes in the test suite by migrating to `TestRomManager`. The editor's core logic is now stable and production-ready.
|
||||
- ✅ **Windows Stability**: Resolved stack overflow crashes and file dialog issues, bringing Windows builds to parity with macOS/Linux.
|
||||
- ✅ **`z3ed` Learn Command**: Fully implemented the `learn` command, allowing the AI to persist user preferences, ROM patterns, and conversation history.
|
||||
- ✅ **Gemini Native Function Calling**: Upgraded from manual `curl` requests to the official Gemini function calling API for improved reliability.
|
||||
- ✅ **Tile16 Editor Refactor**: Fixed critical crashes, implemented a new three-column layout, and added dynamic zoom controls.
|
||||
|
||||
|
||||
524
docs/z3ed/NETWORKING.md
Normal file
524
docs/z3ed/NETWORKING.md
Normal file
@@ -0,0 +1,524 @@
|
||||
# Z3ED Networking & Collaboration
|
||||
|
||||
## Overview
|
||||
|
||||
Z3ED provides comprehensive networking capabilities across all three components:
|
||||
- **yaze app**: GUI application with real-time collaboration
|
||||
- **z3ed CLI**: Command-line interface for remote operations
|
||||
- **yaze-server**: WebSocket server for coordination
|
||||
|
||||
## Architecture
|
||||
|
||||
### Cross-Platform Design
|
||||
|
||||
All networking code is designed to work on:
|
||||
- ✅ **Windows** - Using native Win32 sockets (ws2_32)
|
||||
- ✅ **macOS** - Using native BSD sockets
|
||||
- ✅ **Linux** - Using native BSD sockets
|
||||
|
||||
### Components
|
||||
|
||||
```
|
||||
┌─────────────┐ WebSocket ┌──────────────┐
|
||||
│ yaze app │◄────────────────────────────►│ yaze-server │
|
||||
│ (GUI) │ │ (Node.js) │
|
||||
└─────────────┘ └──────────────┘
|
||||
▲ ▲
|
||||
│ │
|
||||
│ WebSocket │
|
||||
│ │
|
||||
└─────────────┐ │
|
||||
│ │
|
||||
┌──────▼──────┐ │
|
||||
│ z3ed CLI │◄──────────────────────┘
|
||||
│ │
|
||||
└─────────────┘
|
||||
|
||||
gRPC (for GUI testing)
|
||||
│
|
||||
│
|
||||
┌──────▼──────┐
|
||||
│ yaze app │
|
||||
│ (ImGui) │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
## WebSocket Protocol
|
||||
|
||||
### Connection
|
||||
|
||||
```cpp
|
||||
#include "app/net/websocket_client.h"
|
||||
|
||||
net::WebSocketClient client;
|
||||
|
||||
// Connect to server
|
||||
auto status = client.Connect("localhost", 8765);
|
||||
|
||||
// Set up callbacks
|
||||
client.OnMessage("rom_sync", [](const nlohmann::json& payload) {
|
||||
// Handle ROM sync
|
||||
});
|
||||
|
||||
client.OnStateChange([](net::ConnectionState state) {
|
||||
// Handle state changes
|
||||
});
|
||||
```
|
||||
|
||||
### Message Types
|
||||
|
||||
#### 1. Session Management
|
||||
|
||||
**Host Session**:
|
||||
```json
|
||||
{
|
||||
"type": "host_session",
|
||||
"payload": {
|
||||
"session_name": "My ROM Hack",
|
||||
"username": "host",
|
||||
"rom_hash": "abc123",
|
||||
"ai_enabled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Join Session**:
|
||||
```json
|
||||
{
|
||||
"type": "join_session",
|
||||
"payload": {
|
||||
"session_code": "ABC123",
|
||||
"username": "participant"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Proposal System (NEW)
|
||||
|
||||
**Share Proposal**:
|
||||
```json
|
||||
{
|
||||
"type": "proposal_share",
|
||||
"payload": {
|
||||
"sender": "username",
|
||||
"proposal_data": {
|
||||
"description": "Place tile 0x42 at (5,7)",
|
||||
"type": "tile_edit",
|
||||
"data": {...}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Vote on Proposal** (NEW):
|
||||
```json
|
||||
{
|
||||
"type": "proposal_vote",
|
||||
"payload": {
|
||||
"proposal_id": "prop_123",
|
||||
"approved": true,
|
||||
"username": "voter"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"type": "proposal_vote_received",
|
||||
"payload": {
|
||||
"proposal_id": "prop_123",
|
||||
"username": "voter",
|
||||
"approved": true,
|
||||
"votes": {
|
||||
"host": true,
|
||||
"user1": true,
|
||||
"user2": false
|
||||
},
|
||||
"timestamp": 1234567890
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Update Proposal Status**:
|
||||
```json
|
||||
{
|
||||
"type": "proposal_update",
|
||||
"payload": {
|
||||
"proposal_id": "prop_123",
|
||||
"status": "approved" // or "rejected", "applied"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. ROM Synchronization
|
||||
|
||||
**Send ROM Sync**:
|
||||
```json
|
||||
{
|
||||
"type": "rom_sync",
|
||||
"payload": {
|
||||
"sender": "username",
|
||||
"diff_data": "base64_encoded_diff",
|
||||
"rom_hash": "new_hash"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. Snapshots
|
||||
|
||||
**Share Snapshot**:
|
||||
```json
|
||||
{
|
||||
"type": "snapshot_share",
|
||||
"payload": {
|
||||
"sender": "username",
|
||||
"snapshot_data": "base64_encoded_image",
|
||||
"snapshot_type": "screenshot"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## YAZE App Integration
|
||||
|
||||
### Using WebSocketClient
|
||||
|
||||
```cpp
|
||||
#include "app/net/websocket_client.h"
|
||||
|
||||
// Create client
|
||||
auto client = std::make_unique<net::WebSocketClient>();
|
||||
|
||||
// Connect
|
||||
if (auto status = client->Connect("localhost", 8765); !status.ok()) {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Host a session
|
||||
auto session_info = client->HostSession(
|
||||
"My Hack",
|
||||
"username",
|
||||
rom->GetHash(),
|
||||
true // AI enabled
|
||||
);
|
||||
|
||||
// Set up proposal callback
|
||||
client->OnMessage("proposal_shared", [this](const nlohmann::json& payload) {
|
||||
std::string proposal_id = payload["proposal_id"];
|
||||
nlohmann::json proposal_data = payload["proposal_data"];
|
||||
|
||||
// Add to approval manager
|
||||
approval_mgr->SubmitProposal(
|
||||
proposal_id,
|
||||
payload["sender"],
|
||||
proposal_data["description"],
|
||||
proposal_data
|
||||
);
|
||||
});
|
||||
|
||||
// Vote on proposal
|
||||
client->VoteOnProposal(proposal_id, true, "my_username");
|
||||
```
|
||||
|
||||
### Using CollaborationService
|
||||
|
||||
```cpp
|
||||
#include "app/net/collaboration_service.h"
|
||||
|
||||
// High-level service that integrates everything
|
||||
auto collab_service = std::make_unique<net::CollaborationService>(rom);
|
||||
|
||||
// Initialize with version manager and approval manager
|
||||
collab_service->Initialize(config, version_mgr, approval_mgr);
|
||||
|
||||
// Connect and host
|
||||
collab_service->Connect("localhost", 8765);
|
||||
collab_service->HostSession("My Hack", "username");
|
||||
|
||||
// Submit local changes as proposal
|
||||
collab_service->SubmitChangesAsProposal(
|
||||
"Modified dungeon room 5",
|
||||
"username"
|
||||
);
|
||||
|
||||
// Auto-sync is handled automatically
|
||||
```
|
||||
|
||||
## Z3ED CLI Integration
|
||||
|
||||
### Connection Commands
|
||||
|
||||
```bash
|
||||
# Connect to collaboration server
|
||||
z3ed net connect --host localhost --port 8765
|
||||
|
||||
# Join session
|
||||
z3ed net join --code ABC123 --username myname
|
||||
|
||||
# Leave session
|
||||
z3ed net leave
|
||||
```
|
||||
|
||||
### Proposal Commands
|
||||
|
||||
```bash
|
||||
# Submit proposal from z3ed
|
||||
z3ed agent run --prompt "Place tile 42 at (5,7)" --submit-proposal
|
||||
|
||||
# Check proposal status
|
||||
z3ed net proposal status --id prop_123
|
||||
|
||||
# Wait for approval (blocking)
|
||||
z3ed net proposal wait --id prop_123 --timeout 60
|
||||
```
|
||||
|
||||
### Example Workflow
|
||||
|
||||
```bash
|
||||
# 1. Connect to server
|
||||
z3ed net connect --host localhost
|
||||
|
||||
# 2. Join session
|
||||
z3ed net join --code XYZ789 --username alice
|
||||
|
||||
# 3. Submit AI-generated proposal
|
||||
z3ed agent run --prompt "Make boss room more challenging" \
|
||||
--submit-proposal --wait-approval
|
||||
|
||||
# 4. If approved, changes are applied
|
||||
# If rejected, original ROM is preserved
|
||||
```
|
||||
|
||||
## Windows-Specific Notes
|
||||
|
||||
### Building on Windows
|
||||
|
||||
The networking library automatically links Windows socket support:
|
||||
|
||||
```cmake
|
||||
if(WIN32)
|
||||
target_link_libraries(yaze_net PUBLIC ws2_32)
|
||||
endif()
|
||||
```
|
||||
|
||||
### vcpkg Dependencies
|
||||
|
||||
For Windows with vcpkg:
|
||||
|
||||
```powershell
|
||||
# Install dependencies
|
||||
vcpkg install openssl:x64-windows
|
||||
|
||||
# CMake will automatically detect and use them
|
||||
```
|
||||
|
||||
### Windows Firewall
|
||||
|
||||
You may need to allow connections:
|
||||
|
||||
```powershell
|
||||
# Allow yaze-server
|
||||
netsh advfirewall firewall add rule name="YAZE Server" dir=in action=allow protocol=TCP localport=8765
|
||||
|
||||
# Or through UI: Windows Defender Firewall → Allow an app
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Transport Security
|
||||
|
||||
1. **Use WSS (WebSocket Secure)** in production:
|
||||
```cpp
|
||||
client->Connect("wss://server.example.com", 443);
|
||||
```
|
||||
|
||||
2. **Server configuration** with SSL:
|
||||
```javascript
|
||||
const https = require('https');
|
||||
const fs = require('fs');
|
||||
|
||||
const server = https.createServer({
|
||||
cert: fs.readFileSync('cert.pem'),
|
||||
key: fs.readFileSync('key.pem')
|
||||
});
|
||||
```
|
||||
|
||||
### Approval Security
|
||||
|
||||
1. **Host-only mode** (safest):
|
||||
```cpp
|
||||
approval_mgr->SetApprovalMode(ApprovalMode::kHostOnly);
|
||||
```
|
||||
|
||||
2. **Verify identities**: Use authentication tokens
|
||||
|
||||
3. **Rate limiting**: Server limits messages to 100/minute
|
||||
|
||||
### ROM Protection
|
||||
|
||||
1. **Always create snapshots** before applying proposals:
|
||||
```cpp
|
||||
config.create_snapshot_before_sync = true;
|
||||
```
|
||||
|
||||
2. **Mark safe points** after verification:
|
||||
```cpp
|
||||
version_mgr->MarkAsSafePoint(snapshot_id);
|
||||
```
|
||||
|
||||
3. **Auto-rollback** on errors:
|
||||
```cpp
|
||||
if (error) {
|
||||
version_mgr->RestoreSnapshot(snapshot_before);
|
||||
}
|
||||
```
|
||||
|
||||
## Platform-Specific Implementation
|
||||
|
||||
### httplib WebSocket Support
|
||||
|
||||
The implementation uses `cpp-httplib` for cross-platform support:
|
||||
|
||||
- **Windows**: Uses Winsock2 (ws2_32.dll)
|
||||
- **macOS/Linux**: Uses BSD sockets
|
||||
- **SSL/TLS**: Optional OpenSSL support
|
||||
|
||||
### Threading
|
||||
|
||||
All platforms use C++11 threads:
|
||||
|
||||
```cpp
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
std::thread receive_thread([this]() {
|
||||
// Platform-independent receive loop
|
||||
});
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Connection Errors
|
||||
|
||||
```cpp
|
||||
auto status = client->Connect(host, port);
|
||||
if (!status.ok()) {
|
||||
if (absl::IsUnavailable(status)) {
|
||||
// Server not reachable
|
||||
} else if (absl::IsDeadlineExceeded(status)) {
|
||||
// Connection timeout
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Network State
|
||||
|
||||
```cpp
|
||||
client->OnStateChange([](ConnectionState state) {
|
||||
switch (state) {
|
||||
case ConnectionState::kConnected:
|
||||
// Ready to use
|
||||
break;
|
||||
case ConnectionState::kDisconnected:
|
||||
// Clean shutdown
|
||||
break;
|
||||
case ConnectionState::kReconnecting:
|
||||
// Attempting reconnect
|
||||
break;
|
||||
case ConnectionState::kError:
|
||||
// Fatal error
|
||||
break;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
### Compression
|
||||
|
||||
Large messages are compressed:
|
||||
|
||||
```cpp
|
||||
// ROM diffs are compressed before sending
|
||||
std::string compressed = CompressDiff(diff_data);
|
||||
client->SendRomSync(compressed, hash, sender);
|
||||
```
|
||||
|
||||
### Batching
|
||||
|
||||
Small changes are batched:
|
||||
|
||||
```cpp
|
||||
config.sync_interval_ms = 5000; // Batch changes over 5 seconds
|
||||
```
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
Server enforces:
|
||||
- 100 messages per minute per client
|
||||
- 5MB max ROM diff size
|
||||
- 10MB max snapshot size
|
||||
|
||||
## Testing
|
||||
|
||||
### Unit Tests
|
||||
|
||||
```cpp
|
||||
TEST(WebSocketClientTest, ConnectAndDisconnect) {
|
||||
net::WebSocketClient client;
|
||||
ASSERT_TRUE(client.Connect("localhost", 8765).ok());
|
||||
EXPECT_TRUE(client.IsConnected());
|
||||
client.Disconnect();
|
||||
EXPECT_FALSE(client.IsConnected());
|
||||
}
|
||||
```
|
||||
|
||||
### Integration Tests
|
||||
|
||||
```bash
|
||||
# Start server
|
||||
cd yaze-server
|
||||
npm start
|
||||
|
||||
# Run tests
|
||||
cd yaze
|
||||
cmake --build build --target yaze_net_tests
|
||||
./build/bin/yaze_net_tests
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Failed to connect"
|
||||
- Check server is running: `ps aux | grep node`
|
||||
- Check port is available: `netstat -an | grep 8765`
|
||||
- Check firewall settings
|
||||
|
||||
### "Connection timeout"
|
||||
- Increase timeout: `client->SetTimeout(10);`
|
||||
- Check network connectivity
|
||||
- Verify server address
|
||||
|
||||
### "SSL handshake failed"
|
||||
- Verify OpenSSL is installed
|
||||
- Check certificate validity
|
||||
- Use WSS URL: `wss://` not `ws://`
|
||||
|
||||
### Windows-specific: "ws2_32.dll not found"
|
||||
- Reinstall Windows SDK
|
||||
- Check PATH environment variable
|
||||
- Use vcpkg for dependencies
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
- [ ] WebRTC for peer-to-peer connections
|
||||
- [ ] Binary protocol for faster ROM syncs
|
||||
- [ ] Automatic reconnection with exponential backoff
|
||||
- [ ] Connection pooling for multiple sessions
|
||||
- [ ] NAT traversal for home networks
|
||||
- [ ] End-to-end encryption for proposals
|
||||
|
||||
## See Also
|
||||
|
||||
- [Collaboration Guide](COLLABORATION.md) - Version management and approval
|
||||
- [Z3ED README](README.md) - Main documentation
|
||||
- [yaze-server README](../../../yaze-server/README.md) - Server setup
|
||||
Reference in New Issue
Block a user