parent
138a218fc5
commit
df8cc62ece
16 changed files with 234 additions and 186 deletions
@ -0,0 +1,13 @@ |
||||
//! Common module to handle asset loading and adding visual components
|
||||
//! (such as [`Mesh`]) to entities when they are spawned from the server.
|
||||
//!
|
||||
//! This doesn't mean this is the only place assets are loaded.
|
||||
//! For example UI related assets may be loaded in `ui` plugins.
|
||||
|
||||
use bevy::prelude::*; |
||||
|
||||
mod block; |
||||
|
||||
pub fn plugin(app: &mut App) { |
||||
app.add_plugins(block::plugin); |
||||
} |
||||
@ -1,11 +1,14 @@ |
||||
//! Handles client-side input using [`lightyear`], updating the
|
||||
//! [`ActionState`] of the affected entities (such as the `Player`).
|
||||
|
||||
use bevy::prelude::*; |
||||
use common::prelude::*; |
||||
use lightyear::prelude::input::client::*; |
||||
use lightyear::prelude::input::native::*; |
||||
|
||||
use bevy::window::{CursorGrabMode, CursorOptions}; |
||||
|
||||
use crate::camera::CameraFreeLook; |
||||
use common::network::Inputs; |
||||
|
||||
pub fn plugin(app: &mut App) { |
||||
app.add_systems( |
||||
@ -0,0 +1,63 @@ |
||||
use bevy::prelude::*; |
||||
|
||||
use bevy::window::{CursorGrabMode, CursorOptions}; |
||||
|
||||
use crate::Screen; |
||||
|
||||
pub fn plugin(app: &mut App) { |
||||
app.add_systems( |
||||
PreUpdate, |
||||
update_cursor_grab.run_if(in_state(Screen::Gameplay)), |
||||
); |
||||
} |
||||
|
||||
fn update_cursor_grab( |
||||
mut mouse_button_input: ResMut<ButtonInput<MouseButton>>, |
||||
key_input: Res<ButtonInput<KeyCode>>, |
||||
window: Single<(&mut Window, &mut CursorOptions)>, |
||||
) { |
||||
let (mut window, mut cursor) = window.into_inner(); |
||||
|
||||
let is_grabbed = cursor.grab_mode != CursorGrabMode::None; |
||||
let request_grab = mouse_button_input.any_just_pressed([MouseButton::Left, MouseButton::Right]); |
||||
let request_ungrab = !window.focused || key_input.just_pressed(KeyCode::Escape); |
||||
|
||||
if !is_grabbed && request_grab && !request_ungrab { |
||||
cursor.grab_mode = CursorGrabMode::Locked; |
||||
|
||||
// To prevent other systems (such as `place_break_blocks`)
|
||||
// from seeing the mouse button inputs, clear the state here.
|
||||
mouse_button_input.clear(); |
||||
} |
||||
|
||||
if is_grabbed && request_ungrab && !request_grab { |
||||
cursor.grab_mode = CursorGrabMode::None; |
||||
} |
||||
|
||||
if is_grabbed && !request_ungrab { |
||||
// Set the cursor position to the center of the window, so that when
|
||||
// it is ungrabbed, it will reappear there. Because `is_grabbed` is
|
||||
// not updated on grab, this block is delayed by one frame.
|
||||
//
|
||||
// On Wayland, since the cursor is locked into place, this only needs
|
||||
// to be done once. Unfortunately, for some reason this doesn't work
|
||||
// in the same frame as setting `grab_mode`, and would log an error.
|
||||
//
|
||||
// On X11, the cursor can't be locked into place, only confined to the
|
||||
// window bounds, so we repeatedly move the cursor back to the center
|
||||
// while it's grabbed.
|
||||
//
|
||||
// On the web, the cursor can be locked, but setting its position is
|
||||
// not supported at all, so this would instead log a bunch of errors.
|
||||
let center = window.resolution.size() / 2.; |
||||
#[cfg(not(target_family = "wasm"))] // skip on web
|
||||
window.set_cursor_position(Some(center)); |
||||
} |
||||
|
||||
// Keep cursor visbility in sync with `grab_mode`.
|
||||
cursor.visible = cursor.grab_mode == CursorGrabMode::None; |
||||
} |
||||
|
||||
pub fn is_cursor_grabbed(cursor: Single<&CursorOptions>) -> bool { |
||||
cursor.grab_mode != CursorGrabMode::None |
||||
} |
||||
@ -0,0 +1,10 @@ |
||||
use bevy::prelude::*; |
||||
|
||||
mod client_inputs; |
||||
mod cursor_grab; |
||||
|
||||
pub use cursor_grab::is_cursor_grabbed; |
||||
|
||||
pub fn plugin(app: &mut App) { |
||||
app.add_plugins((client_inputs::plugin, cursor_grab::plugin)); |
||||
} |
||||
@ -0,0 +1,68 @@ |
||||
use bevy::prelude::*; |
||||
use common::prelude::*; |
||||
|
||||
use bevy::window::{CursorGrabMode, CursorOptions}; |
||||
|
||||
use crate::Screen; |
||||
|
||||
pub fn plugin(app: &mut App) { |
||||
app.load_resource::<CrosshairAssets>(); |
||||
app.add_systems(OnEnter(Screen::Gameplay), setup_crosshair); |
||||
app.add_systems(Update, update_crosshair_visibility); |
||||
} |
||||
|
||||
#[derive(Resource, Asset, Reflect, Clone)] |
||||
#[reflect(Resource)] |
||||
pub struct CrosshairAssets { |
||||
#[dependency] |
||||
image: Handle<Image>, |
||||
} |
||||
|
||||
impl FromWorld for CrosshairAssets { |
||||
fn from_world(world: &mut World) -> Self { |
||||
let assets = world.resource::<AssetServer>(); |
||||
Self { |
||||
image: assets.load("crosshair.png"), |
||||
} |
||||
} |
||||
} |
||||
|
||||
#[derive(Component)] |
||||
pub struct Crosshair; |
||||
|
||||
fn setup_crosshair(mut commands: Commands, assets: Res<CrosshairAssets>) { |
||||
commands.spawn(( |
||||
Node { |
||||
width: percent(100), |
||||
height: percent(100), |
||||
align_items: AlignItems::Center, |
||||
justify_content: JustifyContent::Center, |
||||
..default() |
||||
}, |
||||
children![( |
||||
Crosshair, |
||||
Node { |
||||
width: px(64), |
||||
height: px(64), |
||||
..default() |
||||
}, |
||||
ImageNode { |
||||
image: assets.image.clone(), |
||||
..default() |
||||
}, |
||||
// Hidden by default, because cursor shouldn't be grabbed at startup either.
|
||||
Visibility::Hidden, |
||||
)], |
||||
)); |
||||
} |
||||
|
||||
fn update_crosshair_visibility( |
||||
cursor: Single<&CursorOptions, Changed<CursorOptions>>, |
||||
crosshair: Single<&mut Visibility, With<Crosshair>>, |
||||
) { |
||||
let is_grabbed = cursor.grab_mode != CursorGrabMode::None; |
||||
let mut crosshair_visibility = crosshair.into_inner(); |
||||
*crosshair_visibility = (!is_grabbed || cursor.visible) |
||||
.then_some(Visibility::Hidden) |
||||
.unwrap_or_default(); |
||||
} |
||||
@ -0,0 +1,8 @@ |
||||
use bevy::prelude::*; |
||||
|
||||
mod crosshair; |
||||
mod loading_screen; |
||||
|
||||
pub fn plugin(app: &mut App) { |
||||
app.add_plugins((crosshair::plugin, loading_screen::plugin)); |
||||
} |
||||
@ -1,12 +1,19 @@ |
||||
mod client; |
||||
mod protocol; |
||||
mod server; |
||||
use bevy::prelude::*; |
||||
|
||||
pub(crate) mod protocol; |
||||
|
||||
mod client; |
||||
mod client_webtransport; |
||||
mod server; |
||||
mod server_webtransport; |
||||
|
||||
pub use client::*; |
||||
pub use protocol::*; |
||||
pub use server::*; |
||||
pub use crate::network::client_webtransport::ConnectWebTransportCommand; |
||||
pub use crate::network::server::StartLocalServerCommand; |
||||
#[cfg(not(target_family = "wasm"))] |
||||
pub use crate::network::server_webtransport::StartWebTransportServerCommand; |
||||
|
||||
pub const DEFAULT_PORT: u16 = 13580; |
||||
|
||||
pub fn plugin(app: &mut App) { |
||||
app.add_plugins((protocol::plugin, client::plugin, server::plugin)); |
||||
} |
||||
|
||||
Loading…
Reference in new issue