Initial commit: FunConnect project with server, relay, client and admin panel
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
10
shared/Cargo.toml
Normal file
10
shared/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "funmc-shared"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
2
shared/src/lib.rs
Normal file
2
shared/src/lib.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod models;
|
||||
pub mod protocol;
|
||||
85
shared/src/models.rs
Normal file
85
shared/src/models.rs
Normal 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
125
shared/src/protocol.rs
Normal 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,
|
||||
}
|
||||
Reference in New Issue
Block a user