Initial commit: FunConnect project with server, relay, client and admin panel

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-24 20:56:36 +08:00
parent eb6e901440
commit b6891483ae
167 changed files with 16147 additions and 106 deletions

2
shared/src/lib.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod models;
pub mod protocol;

85
shared/src/models.rs Normal file
View File

@@ -0,0 +1,85 @@
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use chrono::{DateTime, Utc};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User {
pub id: Uuid,
pub username: String,
pub email: String,
pub avatar_seed: String,
pub last_seen: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum FriendshipStatus {
Pending,
Accepted,
Blocked,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Friendship {
pub requester_id: Uuid,
pub addressee_id: Uuid,
pub status: FriendshipStatus,
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum RoomStatus {
Open,
InGame,
Closed,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Room {
pub id: Uuid,
pub name: String,
pub owner_id: Uuid,
pub max_players: i32,
pub is_public: bool,
pub game_version: String,
pub status: RoomStatus,
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum MemberRole {
Owner,
Member,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RoomMember {
pub room_id: Uuid,
pub user_id: Uuid,
pub role: MemberRole,
pub joined_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum SessionType {
P2p,
Relay,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthResponse {
pub access_token: String,
pub refresh_token: String,
pub user: User,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectionStats {
pub session_type: SessionType,
pub latency_ms: u32,
pub bytes_sent: u64,
pub bytes_received: u64,
}

125
shared/src/protocol.rs Normal file
View File

@@ -0,0 +1,125 @@
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Messages sent over the WebSocket signaling channel
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum SignalingMessage {
/// Client registers itself with the signaling server
Register { user_id: Uuid },
/// ICE/NAT candidate exchange for P2P hole punching
Offer {
from: Uuid,
to: Uuid,
room_id: Uuid,
/// Serialized offer data (public IP, port, NAT type)
sdp: String,
},
Answer {
from: Uuid,
to: Uuid,
room_id: Uuid,
sdp: String,
},
IceCandidate {
from: Uuid,
to: Uuid,
candidate: String,
},
/// Presence events
UserOnline { user_id: Uuid },
UserOffline { user_id: Uuid },
/// Room events pushed by server
RoomInvite {
from: Uuid,
room_id: Uuid,
room_name: String,
},
MemberJoined {
room_id: Uuid,
user_id: Uuid,
username: String,
},
MemberLeft {
room_id: Uuid,
user_id: Uuid,
},
/// Member kicked from room
Kicked {
room_id: Uuid,
reason: String,
},
/// Room closed by owner
RoomClosed {
room_id: Uuid,
},
/// Friend events
FriendRequest { from: Uuid, username: String },
FriendAccepted { from: Uuid, username: String },
/// Chat messages in room
ChatMessage {
room_id: Uuid,
from: Uuid,
username: String,
content: String,
timestamp: i64,
},
/// Send chat message to room (client -> server)
SendChat {
room_id: Uuid,
content: String,
},
/// P2P connection negotiation result
P2pSuccess { room_id: Uuid, peer_id: Uuid },
P2pFailed { room_id: Uuid, peer_id: Uuid },
/// Relay session control
RelayJoin {
room_id: Uuid,
session_token: String,
},
/// Ping/pong for keepalive
Ping,
Pong,
/// Server error response
Error { code: u16, message: String },
}
/// QUIC relay packet header (prefix before Minecraft TCP data)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RelayPacket {
pub room_id: Uuid,
pub source_peer: Uuid,
pub dest_peer: Option<Uuid>, // None = broadcast to room
pub payload: Vec<u8>,
}
/// NAT type detected by STUN
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum NatType {
None,
FullCone,
RestrictedCone,
PortRestrictedCone,
Symmetric,
Unknown,
}
/// Peer connection info exchanged during signaling
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PeerInfo {
pub user_id: Uuid,
pub public_addr: String,
pub local_addrs: Vec<String>,
pub nat_type: NatType,
}