placeholder-project

Temp project
git clone git://archive.git.mtrnord.blog/MTRNord/placeholder-project.git
Log | Files | Refs

main.rs (7570B)


      1 use std::net::{Ipv4Addr, SocketAddr};
      2 
      3 use bevy::{
      4     log::{Level, LogPlugin},
      5     prelude::*,
      6     scene::ron,
      7     window::PresentMode,
      8 };
      9 use bevy_ecs_ldtk::prelude::*;
     10 use clap::Parser;
     11 use iyes_perf_ui::{PerfUiCompleteBundle, PerfUiPlugin};
     12 use lightyear::{
     13     connection::netcode::ClientId,
     14     shared::log::add_log_layer,
     15     transport::{io::TransportConfig, LOCAL_SOCKET},
     16 };
     17 use networking::{
     18     client::ClientPluginGroup, server::ServerPluginGroup, ClientSettings, ClientTransports,
     19     ServerTransports, Settings,
     20 };
     21 use wall::WallBundle;
     22 
     23 mod networking;
     24 mod player;
     25 mod wall;
     26 
     27 #[derive(Parser, PartialEq, Debug)]
     28 enum Cli {
     29     #[cfg(not(target_family = "wasm"))]
     30     /// The program will act both as a server and as a client
     31     ListenServer,
     32     #[cfg(not(target_family = "wasm"))]
     33     /// Dedicated server
     34     Server,
     35     /// The program will act as a client
     36     Client,
     37 }
     38 
     39 fn main() {
     40     cfg_if::cfg_if! {
     41         if #[cfg(target_family = "wasm")] {
     42             let client_id = rand::random::<u64>();
     43             let cli = Cli::Client {
     44                 client_id: Some(client_id)
     45             };
     46         } else {
     47             let cli = Cli::parse();
     48         }
     49     }
     50     let settings_str = include_str!("../assets/settings.ron");
     51     let settings = ron::de::from_str::<Settings>(settings_str).unwrap();
     52     run(settings, cli);
     53 }
     54 
     55 fn run(settings: Settings, cli: Cli) {
     56     match cli {
     57         #[cfg(not(target_family = "wasm"))]
     58         Cli::ListenServer => {
     59             // create client app
     60             let (from_server_send, from_server_recv) = crossbeam_channel::unbounded();
     61             let (to_server_send, to_server_recv) = crossbeam_channel::unbounded();
     62             let transport_config = TransportConfig::LocalChannel {
     63                 recv: from_server_recv,
     64                 send: to_server_send,
     65             };
     66             // when communicating via channels, we need to use the address `LOCAL_SOCKET` for the server
     67             let client_id = rand::random::<u64>();
     68             let mut client_app =
     69                 client_app(settings.clone(), LOCAL_SOCKET, client_id, transport_config);
     70 
     71             // create server app
     72             let extra_transport_configs = vec![TransportConfig::Channels {
     73                 // even if we communicate via channels, we need to provide a socket address for the client
     74                 channels: vec![(LOCAL_SOCKET, to_server_recv, from_server_send)],
     75             }];
     76             let mut server_app = server_app(settings, extra_transport_configs);
     77 
     78             // run both the client and server apps
     79             std::thread::spawn(move || server_app.run());
     80             client_app.run();
     81         }
     82         #[cfg(not(target_family = "wasm"))]
     83         Cli::Server => {
     84             let mut app = server_app(settings, vec![]);
     85             app.run();
     86         }
     87         Cli::Client => {
     88             let server_addr = SocketAddr::new(
     89                 settings.client.server_addr.into(),
     90                 settings.client.server_port,
     91             );
     92             let transport_config = get_client_transport_config(settings.client.clone());
     93             let client_id = rand::random::<u64>();
     94             let mut app = client_app(settings, server_addr, client_id, transport_config);
     95             app.run();
     96         }
     97     }
     98 }
     99 
    100 /// Build the client app
    101 fn client_app(
    102     settings: Settings,
    103     server_addr: SocketAddr,
    104     client_id: ClientId,
    105     transport_config: TransportConfig,
    106 ) -> App {
    107     let mut app = App::new();
    108     // NOTE: create the default plugins first so that the async task pools are initialized
    109     // use the default bevy logger for now
    110     // (the lightyear logger doesn't handle wasm)
    111     app.add_plugins(
    112         DefaultPlugins
    113             .build()
    114             .set(LogPlugin {
    115                 level: Level::INFO,
    116                 filter: "wgpu=error,bevy_render=info".to_string(),
    117                 update_subscriber: Some(add_log_layer),
    118             })
    119             .set(WindowPlugin {
    120                 primary_window: Some(Window {
    121                     title: "Matrix RPG".into(),
    122                     present_mode: PresentMode::AutoVsync,
    123                     prevent_default_event_handling: false,
    124                     ..default()
    125                 }),
    126                 ..default()
    127             })
    128             .set(ImagePlugin::default_nearest()),
    129     );
    130     if settings.client.inspector {
    131         app.add_plugins(PerfUiPlugin);
    132     }
    133     app.add_plugins(LdtkPlugin)
    134         .insert_resource(LevelSelection::index(0))
    135         .insert_resource(LdtkSettings {
    136             set_clear_color: SetClearColor::FromLevelBackground,
    137             ..Default::default()
    138         })
    139         .add_systems(Startup, move |mut commands: Commands| {
    140             if settings.client.inspector {
    141                 commands.spawn(PerfUiCompleteBundle::default());
    142             }
    143         })
    144         .register_ldtk_int_cell::<WallBundle>(1)
    145         .add_plugins(player::PlayerPlugin);
    146     let client_plugin_group = ClientPluginGroup::new(
    147         // use the cli-provided client id if it exists, otherwise use the settings client id
    148         client_id,
    149         server_addr,
    150         transport_config,
    151         settings.shared,
    152     );
    153     app.add_plugins(client_plugin_group.build());
    154     app
    155 }
    156 
    157 /// Build the server app
    158 fn server_app(settings: Settings, extra_transport_configs: Vec<TransportConfig>) -> App {
    159     let mut app = App::new();
    160     if !settings.server.headless {
    161         app.add_plugins(DefaultPlugins.build().disable::<LogPlugin>());
    162     } else {
    163         app.add_plugins(MinimalPlugins);
    164     }
    165     app.add_plugins(LogPlugin {
    166         level: Level::INFO,
    167         filter: "wgpu=error,bevy_render=info".to_string(),
    168         update_subscriber: Some(add_log_layer),
    169     });
    170 
    171     if settings.server.inspector {
    172         app.add_plugins(PerfUiPlugin);
    173     }
    174     app.add_systems(Startup, move |mut commands: Commands| {
    175         if settings.client.inspector {
    176             commands.spawn(PerfUiCompleteBundle::default());
    177         }
    178     });
    179     let mut transport_configs = get_server_transport_configs(settings.server.transport);
    180     transport_configs.extend(extra_transport_configs);
    181     let server_plugin_group = ServerPluginGroup::new(transport_configs, settings.shared);
    182     app.add_plugins(server_plugin_group.build());
    183     app
    184 }
    185 
    186 /// Parse the server transport settings into a list of `TransportConfig` that are used to configure the lightyear server
    187 fn get_server_transport_configs(settings: Vec<ServerTransports>) -> Vec<TransportConfig> {
    188     settings
    189         .iter()
    190         .map(|t| match t {
    191             ServerTransports::Udp { local_port } => TransportConfig::UdpSocket(SocketAddr::new(
    192                 Ipv4Addr::UNSPECIFIED.into(),
    193                 *local_port,
    194             )),
    195             ServerTransports::WebSocket { local_port } => TransportConfig::WebSocketServer {
    196                 server_addr: SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), *local_port),
    197             },
    198         })
    199         .collect()
    200 }
    201 
    202 /// Parse the client transport settings into a `TransportConfig` that is used to configure the lightyear client
    203 fn get_client_transport_config(settings: ClientSettings) -> TransportConfig {
    204     let server_addr = SocketAddr::new(settings.server_addr.into(), settings.server_port);
    205     let client_addr = SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), settings.client_port);
    206     match settings.transport {
    207         #[cfg(not(target_family = "wasm"))]
    208         ClientTransports::Udp => TransportConfig::UdpSocket(client_addr),
    209         ClientTransports::WebSocket => TransportConfig::WebSocketClient { server_addr },
    210     }
    211 }