use avian2d::prelude::{AngularInertia, AngularVelocity, Collider, LinearVelocity, Mass, Position, Rotation}; use bevy::ecs::entity::MapEntities; use bevy::prelude::*; use crate::prelude::{App, Message}; use bevy_replicon::prelude::*; use serde::{Deserialize, Serialize}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; use url::{Host, Url}; use crate::shared::attachment::{Joint, JointOf, PartInShip, Peer, Ship, SnapOf, SnapOfJoint}; use crate::shared::config::planet::{Planet, PlanetSpring, PlanetSpringJoint}; use crate::shared::ecs::{CanCraft, CraftPartRequest, DragRequestEvent, Drill, Part, Player, PlayerStorage, SingleStorage, Temperature, ToggleDrillEvent}; use crate::shared::ecs::clock_sync::{ClientTiming, ServerTiming}; use crate::shared::ecs::thruster::{Thruster, ThrusterOfPart}; use crate::shared::thrust::ThrustSolution; pub const STARKINGDOMS_PROTOCOL_MAGIC: u64 = 0x5a5a_e37e_4aaa; pub fn register_replication(app: &mut App) { app .add_mapped_server_message::(Channel::Ordered) .add_client_message::(Channel::Ordered) .add_server_message::(Channel::Ordered) .add_mapped_client_message::(Channel::Ordered) .add_mapped_client_message::(Channel::Ordered) .add_mapped_client_message::(Channel::Ordered) .add_mapped_client_message::(Channel::Ordered) .replicate_once::() .replicate_once::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::() .replicate::(); } #[derive(Message, Deserialize, Serialize, MapEntities)] pub struct Hi { #[entities] pub you_are: Entity, pub time_offset: f64, pub server_time: f64, } #[derive(Serialize, Deserialize)] pub struct ManagementInfo { pub native_port: u16, pub wt_port: u16, pub cert_hash: String, } /// wasm is hard pub fn parse_management_address(s: &str) -> Result { let url = Url::parse(s).map_err(|err| format!("invalid server URL: {err}"))?; let ip = match url.host() { Some(Host::Ipv4(ip)) => IpAddr::V4(ip), Some(Host::Ipv6(ip)) => IpAddr::V6(ip), Some(Host::Domain(domain)) => domain.parse::() .map_err(|_| format!("server host must be an IP address, got `{domain}`"))?, None => return Err("server URL is missing a host".to_string()), }; let port = url.port().ok_or("server URL is missing a port")?; Ok(SocketAddr::new(ip, port)) } pub fn encode_cert_hash(hash: &[u8; 32]) -> String { hash.iter().map(|byte| format!("{byte:02x}")).collect() } pub fn decode_cert_hash(s: &str) -> Result<[u8; 32], String> { if s.len() != 64 { return Err(format!("cert_hash must be 64 hex chars, got {}", s.len())); } let mut hash = [0u8; 32]; for (byte, chunk) in hash.iter_mut().zip(s.as_bytes().chunks_exact(2)) { let chunk = std::str::from_utf8(chunk).unwrap(); *byte = u8::from_str_radix(chunk, 16).map_err(|err| format!("invalid cert_hash: {err}"))?; } Ok(hash) }