Skip to content

Conversation

@sharrlotte
Copy link
Member

@sharrlotte sharrlotte commented Jan 27, 2026

Summary by CodeRabbit

  • Chores

    • Migrated entire server architecture to a new runtime environment with updated dependencies and build system.
    • Reorganized GitHub Actions workflows for automated builds.
    • Updated Docker build configuration for the new runtime.
  • Documentation

    • Added architectural guidelines and project structure documentation.
  • Refactor

    • Completely refactored core server components while maintaining feature parity with HTTP room management, connection handling, and messaging.

✏️ Tip: You can customize this high-level summary in your review settings.

…ation

feat: add Rust implementation with multi-stage Docker build
feat: add new GitHub workflows for Rust builds
chore: remove Java/Gradle files and dependencies
docs: update Dockerfile for Rust deployment
Removed unnecessary empty lines and consolidated the /target ignore entry to make the file more concise and readable.
Add initial implementation of PlayerConnect server with HTTP API and proxy services for game connections. Includes:

- Configuration loading from environment variables
- HTTP server with room listing and info endpoints
- Proxy server handling TCP/UDP connections
- State management for rooms and connections
- Packet handling for game protocol
- Basic logging and error handling

The server provides a foundation for hosting multiplayer game sessions with room management and connection proxying.
Add ArcCloseReason enum to models and implement packet serialization logic in packets.rs.
The changes include reading/writing packet data, handling different packet types,
and adding helper functions for string and stats serialization.
- Extract room management logic into separate Rooms struct
- Add rate limiting for connections
- Improve packet handling and error management
- Split TCP/UDP handling into separate functions
- Add pending connection state for better connection lifecycle
- Update models to simplify serialization
- Add utility functions for time management
- Move constants from models.rs to new constant.rs module
- Rename packets::bytes() to to_bytes() for clarity
- Replace DashMap with RwLock for thread-safe state management
- Implement atomic rate limiting with AtomicRateLimiter
- Simplify connection handling with ConnectionActor pattern
- Improve room management with proper member tracking
- Add UDP routing support with rate limiting
- Clean up packet handling and error management
Move TCP and UDP writing logic into dedicated TcpWriter and UdpWriter structs to improve code organization and maintainability. This change also removes duplicate write tracking logic and centralizes UDP address handling.
- Remove unnecessary user creation in build stage
- Simplify dependency caching by using cargo fetch
- Remove redundant mkdir and echo commands
- Clean up formatting and comments
The tag was updated to include '-rust' suffix and use 'latest' tag instead of 'rust' to better reflect the image's purpose and version
Add read() method to Rooms struct to handle RwLock read operations and error checking.
Update all call sites to use the new helper method instead of directly accessing rooms field.
- Move room update broadcasting to AppState level
- Simplify Rooms struct by removing internal broadcast channel
- Add packet queue for connections joining rooms
- Implement proper room join/leave validation and error handling
- Add rate limiting checks for non-host connections
- Improve room closure and connection termination logic
Add RoomUpdate message sending when ro
…rganization

- Simplify SSE keep-alive initialization in http_server
- Add error logging for room updates and packet forwarding in proxy_server
Move connection logging after socket setup and include unique connection ID
to help track individual connections more effectively
- Increase broadcast channel capacity from 100 to 1024 for better performance
- Remove redundant logging for connection registration and cleanup
- Move connection logging to RegisterUDP action for more accurate timing
- Add duplicate registration check in RegisterUDP handler
- Clean up unused imports and variables
Add a receiver field to Rooms struct to maintain channel when clients disconnect
Improve real-time updates responsiveness by reducing the keep-alive interval from 10 to 3 seconds and adding keep-alive text
The read_stats function now uses serde_json for proper JSON parsing instead of returning a dummy Stats struct. This improves reliability and maintains consistency with the actual data format.
Replace Stream return type with IntoResponse and add required headers directly
Remove version prefix from API endpoints to make them more concise and consistent with current API design standards.
- Change created_at from i64 to u128 in Stats for consistency
- Add ping field to Room to track latency
- Introduce RoomView struct to encapsulate room data for API responses
- Update room update events to use RoomView instead of Stats
Add `#[serde(rename)]` attributes to fields to ensure proper JSON serialization. This matches the expected API contract where snake_case fields should be serialized as camelCase.
The RoomUpdateEvent was being sent as a single object in the SSE stream, but client expectations require it to be wrapped in a vector for consistency with other event types. This change aligns the data format with client-side processing requirements.
Add warning logs for unknown UDP senders, full packet queues, and unhandled framework/app packets to improve debugging visibility
Ensure room data is properly read and broadcasted after creation. Add error handling for room lookup and update broadcasting to prevent silent failures.
Add debug logging to track incoming UDP and TCP packets in proxy server for better debugging and monitoring
Replace match statement with if-let for RegisterUDP packets to flatten nested structure and improve readability.
When a connection attempts to join a non-existent room, the system now sends a "Room not found" popup message to the client before closing the connection. This provides clear user feedback. Also refactored UDP packet handling to use explicit match arms for better readability.
The info-level logs for every packet sent/received were generating significant
noise and performance overhead. These logs are not needed for normal operation
and can be enabled via debug logging when troubleshooting is required.
- Ensure packet parsing fails if buffer has remaining bytes after reading
- Add info log when reading AppPacket to aid debugging
- Refactor keep-alive condition to use else-if for clarity
- Replace RwLock-protected HashMaps with DashMap for rooms and connections to improve concurrent access performance
- Add connection_to_room mapping for O(1) room lookup by connection ID
- Implement vectored I/O for TCP writes to reduce syscall overhead
- Move rate limiting earlier in packet processing pipeline
- Simplify room state access patterns and eliminate lock poisoning concerns
Eliminate an info-level log statement that was executed on every packet read.
This improves performance by reducing I/O overhead in hot code paths.
- Store room membership directly in ConnectionActor to avoid separate lookup map
- Remove connection_to_room map and use direct room references
- Send room closed packets to all members when closing a room
- Fix idle detection to use stored room information
- Ensure proper cleanup when connections leave rooms
- Change connection error logging from error! to info! level for expected closures
- Simplify timeout handling by returning error directly instead of breaking loop
- Move UDP cleanup to RegisterUDP action to ensure proper state management
- Reorder UDP registration to prevent orphaned UDP mappings
- Remove redundant connection closed log when UDP cleanup occurs
- Move `notified_idle` flag from `ConnectionActor` to `TcpWriter` for better encapsulation
- Centralize idle notification check after batch writes to avoid duplication
- Increase packet rate limit from 1000 to 5000 per 3-second window
- Increase TCP batch processing capacity from 16 to 64 packets
- Remove redundant `notified_idle` resets in packet processing paths
- Add debug log for UDP connection closure
- Simplify JSON error formatting in stats parsing
The tick interval was changed from ~16.67ms (60Hz) to ~66.67ms (15Hz) to reduce CPU usage and improve overall system performance, especially under high connection loads.
The ConnectionId type is used in network packets and must match the signed integer type used by the underlying protocol. This ensures proper serialization/deserialization when handling negative values that may be used as special identifiers.
Process up to PACKET_BATCH_SIZE messages per iteration instead of using
try_recv in a potentially unbounded loop. This reduces vector reallocations
and improves memory efficiency during high message volume.
- Only log connection closure when UDP writer address exists
- Rename `notified_idle` to `idling` for clarity in TCP writer
- Move idle notification from action handler to tick interval
- Increase tick frequency from 15Hz to 60Hz for better responsiveness
- Fix indentation in packet batch processing loop
The idling flag was incorrectly set to false after writes, causing premature idle notifications. Set it to true after successful writes and adjust the idle check condition to match. Also increase tick frequency from 60Hz to 120Hz for more responsive idle detection.
Add packet ID constants for stream packets and detect them in incoming data.
When a stream packet is received, mark the TCP writer as idling to prevent
the server from timing out the connection while stream data is being sent.
- Remove unnecessary info log for stream packets to reduce noise
- Change default log level from INFO to DEBUG for better debugging
The PACKET_BACTH_SIZE constant is doubled from 16 to 32 to allow more packets to be processed in each batch, reducing overhead and improving network throughput.
- Rename `ArcCloseReason` to `ConnectionCloseReason` and add `PacketSpam` variant
- Rename `CloseReason` to `RoomCloseReason` and remove unused variants
- Update all references to use new enum names
- Simplify connection close logic by removing redundant packet sends
- Remove obsolete packet spam handling in connection actor
…kets

Remove obsolete popup and message packets for unsupported version and failed room joins. Replace with direct error returns to streamline error flow and reduce unnecessary packet construction.
Instead of returning generic error messages when room join fails, send localized message packets to the client. This provides better user feedback and allows for internationalization.

Also remove redundant connection closed packet sending when closing a connection, as the close action itself handles termination.
…re reason

- Use ConnectionId(0) instead of self.id for UDP registration to match proxy handling
- Include closure reason in debug log for better diagnostics
- Remove unused SocketAddr import and inline handle_register_udp function
Send room closed packet to host before notifying members to ensure
host receives closure notification even if member notifications fail.
Ensure RoomCloseReason::Closed is explicitly passed to room_state.close() calls to maintain consistency and provide proper logging context.
The previous limit of 1000 packets per 3 seconds was too restrictive for high-traffic scenarios, causing legitimate packets to be dropped. This increase allows the proxy to handle higher loads while still maintaining rate limiting protection.
- Define new PingPacket struct with send_at timestamp
- Add Ping variant to AppPacket enum with serialization/deserialization
- Implement ping packet handling in connection actor to echo back ping packets
- Make `rooms`, `connections`, and `udp_routes` fields private
- Extract stats update logic into `RoomState::update_state` method
- Extract join validation logic into `RoomState::can_join` method
- Broadcast room updates immediately upon room creation
- Fix error message order for join failures
The info log for connection timeout was unnecessary as the error is already
propagated and logged elsewhere. This cleanup reduces log noise while
maintaining the same error handling behavior.
- Remove the `/rooms/:roomId` GET endpoint and its associated HTML generation
- Extract room iteration logic into `RoomState::into_views()` method
- Simplify SSE initialization by using the new method
- Clean up unused imports in http module
@coderabbitai
Copy link

coderabbitai bot commented Jan 27, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

The pull request performs a complete migration of the PlayerConnect server from Java/Gradle to Rust/Cargo. All Java source code, Gradle build configuration, and associated tooling are removed. A new async Rust implementation is introduced with Tokio-based networking, an Axum HTTP server, comprehensive packet protocol handling, room management, and supporting infrastructure for CI/CD and documentation.

Changes

Cohort / File(s) Summary
Build System Migration
build.gradle, gradle.properties, gradle/wrapper/gradle-wrapper.properties, gradlew, gradlew.bat, settings.gradle, Cargo.toml
Removes entire Gradle configuration and wrapper scripts; introduces Rust Cargo manifest with tokio, axum, serde, tracing, and related async ecosystem dependencies.
GitHub Actions Workflows
.github/workflows/gradle.yml, .github/workflows/release.yml, .github/workflows/rust-release.yml
Removes Java/Gradle CI pipeline; adds release workflow for main branch and separate rust-release workflow for v2 branch, both targeting Docker image builds to ghcr.io.
Docker Containerization
Dockerfile
Replaces Java/Gradle build stage with Rust compilation (rust:1.85-slim); updates runtime stage to distroless cc-debian12; changes entrypoint from Java to compiled binary.
Java Source Code Removal
src/playerconnect/Configs.java, src/playerconnect/HttpServer.java, src/playerconnect/NetworkRelay.java, src/playerconnect/PlayerConnect.java, src/playerconnect/PlayerConnectEvents.java, src/playerconnect/ServerRoom.java, src/playerconnect/Utils.java
Deletes all Java implementations including HTTP server, network relay, room management, event definitions, and utility functions.
Rust Core Implementation
src/main.rs, src/config.rs, src/error.rs, src/constant.rs
Establishes main entrypoint with async runtime initialization, configuration loading from environment, and centralized error and constant type definitions (enums with TryFrom conversions).
Rust Networking & Protocol
src/proxy.rs, src/connection.rs, src/packet.rs, src/writer.rs
Implements TCP/UDP proxy server with per-connection actors, comprehensive binary packet serialization/deserialization, and vectored write utilities for efficient I/O.
Rust State & Room Management
src/state.rs, src/models.rs
Provides global application state with room, connection, and UDP route management; defines serializable data models for stats, players, and room views with serde rename support.
Rust Utilities
src/rate.rs, src/utils.rs, src/http.rs
Adds lock-free atomic rate limiting, system time utilities, and Axum-based HTTP server with SSE streaming for live room updates and health check endpoints.
Documentation & Configuration
README.md, .trae/rules/base.md, structure.md, dev.env, .gitignore
Removes existing README; adds project guidelines (coding conventions, ownership, async patterns), architectural structure document, environment variables, and target directory to gitignore.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120+ minutes


🐰 From Java's realm to async Rust we hop,
With tokio threads and packets that don't stop,
Rooms dance through channels, UDP takes flight,
HTTP streams glow in the digital night,
A rewrite complete—our server takes stride! 🚀

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch v2

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f2ba0e and 9a2d669.

⛔ Files ignored due to path filters (3)
  • Cargo.lock is excluded by !**/*.lock
  • gradle/wrapper/gradle-wrapper.jar is excluded by !**/*.jar
  • libs/PlayerConnectShared.jar is excluded by !**/*.jar
📒 Files selected for processing (36)
  • .github/workflows/gradle.yml
  • .github/workflows/release.yml
  • .github/workflows/rust-release.yml
  • .gitignore
  • .trae/rules/base.md
  • Cargo.toml
  • Dockerfile
  • README.md
  • build.gradle
  • dev.env
  • gradle.properties
  • gradle/wrapper/gradle-wrapper.properties
  • gradlew
  • gradlew.bat
  • settings.gradle
  • src/config.rs
  • src/connection.rs
  • src/constant.rs
  • src/error.rs
  • src/http.rs
  • src/main.rs
  • src/models.rs
  • src/packet.rs
  • src/playerconnect/Configs.java
  • src/playerconnect/HttpServer.java
  • src/playerconnect/NetworkRelay.java
  • src/playerconnect/PlayerConnect.java
  • src/playerconnect/PlayerConnectEvents.java
  • src/playerconnect/ServerRoom.java
  • src/playerconnect/Utils.java
  • src/proxy.rs
  • src/rate.rs
  • src/state.rs
  • src/utils.rs
  • src/writer.rs
  • structure.md

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sharrlotte sharrlotte merged commit dd8870c into main Jan 27, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants