bevy client send messages
This commit is contained in:
parent
dcf52503ac
commit
7985adb216
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -3349,6 +3349,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bevy",
|
"bevy",
|
||||||
"bevy_renet",
|
"bevy_renet",
|
||||||
|
"bincode",
|
||||||
"renet",
|
"renet",
|
||||||
"store",
|
"store",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,6 @@ edition = "2021"
|
||||||
anyhow = "1.0.75"
|
anyhow = "1.0.75"
|
||||||
bevy = { version = "0.11.3" }
|
bevy = { version = "0.11.3" }
|
||||||
bevy_renet = "0.0.9"
|
bevy_renet = "0.0.9"
|
||||||
|
bincode = "1.3.3"
|
||||||
renet = "0.0.13"
|
renet = "0.0.13"
|
||||||
store = { path = "../store" }
|
store = { path = "../store" }
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,39 @@
|
||||||
use std::{net::UdpSocket, time::SystemTime};
|
use std::{net::UdpSocket, time::SystemTime};
|
||||||
|
|
||||||
use store::{EndGameReason, GameEvent, GameState};
|
|
||||||
use renet::transport::{NetcodeClientTransport, NetcodeTransportError, NETCODE_USER_DATA_BYTES};
|
use renet::transport::{NetcodeClientTransport, NetcodeTransportError, NETCODE_USER_DATA_BYTES};
|
||||||
|
use store::{EndGameReason, GameEvent, GameState};
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::window::PrimaryWindow;
|
use bevy::window::PrimaryWindow;
|
||||||
use bevy_renet::{
|
use bevy_renet::{
|
||||||
renet::{transport::ClientAuthentication, ConnectionConfig, RenetClient},
|
renet::{transport::ClientAuthentication, ConnectionConfig, RenetClient},
|
||||||
transport::NetcodeClientPlugin,
|
transport::{client_connected, NetcodeClientPlugin},
|
||||||
RenetClientPlugin,
|
RenetClientPlugin,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Resource)]
|
||||||
|
struct CurrentClientId(u64);
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
struct BevyGameState(GameState);
|
struct BevyGameState(GameState);
|
||||||
|
|
||||||
impl Default for BevyGameState {
|
impl Default for BevyGameState {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
0: GameState::default()
|
0: GameState::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Resource, Deref, DerefMut)]
|
||||||
|
struct GameUIState {
|
||||||
|
selected_tile: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for GameUIState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
selected_tile: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -34,7 +49,7 @@ fn main() {
|
||||||
let args = std::env::args().collect::<Vec<String>>();
|
let args = std::env::args().collect::<Vec<String>>();
|
||||||
let username = &args[1];
|
let username = &args[1];
|
||||||
|
|
||||||
let (client, transport) = new_renet_client(&username).unwrap();
|
let (client, transport, client_id) = new_renet_client(&username).unwrap();
|
||||||
App::new()
|
App::new()
|
||||||
// Lets add a nice dark grey background color
|
// Lets add a nice dark grey background color
|
||||||
.insert_resource(ClearColor(Color::hex("282828").unwrap()))
|
.insert_resource(ClearColor(Color::hex("282828").unwrap()))
|
||||||
|
|
@ -49,16 +64,20 @@ fn main() {
|
||||||
}))
|
}))
|
||||||
// Add our game state and register GameEvent as a bevy event
|
// Add our game state and register GameEvent as a bevy event
|
||||||
.insert_resource(BevyGameState::default())
|
.insert_resource(BevyGameState::default())
|
||||||
|
.insert_resource(GameUIState::default())
|
||||||
.add_event::<BevyGameEvent>()
|
.add_event::<BevyGameEvent>()
|
||||||
// Renet setup
|
// Renet setup
|
||||||
.add_plugins(RenetClientPlugin)
|
.add_plugins(RenetClientPlugin)
|
||||||
.add_plugins(NetcodeClientPlugin)
|
.add_plugins(NetcodeClientPlugin)
|
||||||
.insert_resource(client)
|
.insert_resource(client)
|
||||||
.insert_resource(transport)
|
.insert_resource(transport)
|
||||||
|
.insert_resource(CurrentClientId(client_id))
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
.add_systems(Update, update_waiting_text)
|
.add_systems(Update, (update_waiting_text, input, panic_on_error_system))
|
||||||
.add_systems(Update, input)
|
.add_systems(
|
||||||
.add_systems(Update, panic_on_error_system)
|
PostUpdate,
|
||||||
|
receive_events_from_server.run_if(client_connected()),
|
||||||
|
)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,12 +106,20 @@ fn input(
|
||||||
// windows: Res<Windows>,
|
// windows: Res<Windows>,
|
||||||
input: Res<Input<MouseButton>>,
|
input: Res<Input<MouseButton>>,
|
||||||
game_state: Res<BevyGameState>,
|
game_state: Res<BevyGameState>,
|
||||||
|
mut game_ui_state: ResMut<GameUIState>,
|
||||||
|
mut client: ResMut<RenetClient>,
|
||||||
|
client_id: Res<CurrentClientId>,
|
||||||
) {
|
) {
|
||||||
|
// We only want to handle inputs once we are ingame
|
||||||
|
if game_state.0.stage != store::Stage::InGame {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// let window = windows.get_primary().unwrap();
|
// let window = windows.get_primary().unwrap();
|
||||||
let window = primary_query.get_single().unwrap();
|
let window = primary_query.get_single().unwrap();
|
||||||
if let Some(mouse_position) = window.cursor_position() {
|
if let Some(mouse_position) = window.cursor_position() {
|
||||||
// Determine the index of the tile that the mouse is currently over
|
// Determine the index of the tile that the mouse is currently over
|
||||||
// NOTE: This calculation assumes a fixed window size.
|
// NOTE: This calculation assumes a fixed window size.
|
||||||
// That's fine for now, but consider using the windows size instead.
|
// That's fine for now, but consider using the windows size instead.
|
||||||
let x_tile: usize = (mouse_position.x / 83.0).floor() as usize;
|
let x_tile: usize = (mouse_position.x / 83.0).floor() as usize;
|
||||||
let y_tile: usize = (mouse_position.y / 540.0).floor() as usize;
|
let y_tile: usize = (mouse_position.y / 540.0).floor() as usize;
|
||||||
|
|
@ -106,6 +133,21 @@ fn input(
|
||||||
// If left mouse button is pressed, send a place tile event to the server
|
// If left mouse button is pressed, send a place tile event to the server
|
||||||
if input.just_pressed(MouseButton::Left) {
|
if input.just_pressed(MouseButton::Left) {
|
||||||
info!("select piece at tile {:?}", tile);
|
info!("select piece at tile {:?}", tile);
|
||||||
|
if game_ui_state.selected_tile.is_some() {
|
||||||
|
let from_tile = game_ui_state.selected_tile.unwrap();
|
||||||
|
info!("sending movement from: {:?} to: {:?} ", from_tile, tile);
|
||||||
|
let event = GameEvent::Move {
|
||||||
|
player_id: client_id.0,
|
||||||
|
from: from_tile,
|
||||||
|
to: tile,
|
||||||
|
};
|
||||||
|
client.send_message(0, bincode::serialize(&event).unwrap());
|
||||||
|
}
|
||||||
|
game_ui_state.selected_tile = if game_ui_state.selected_tile.is_some() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(tile)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -161,7 +203,9 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
////////// RENET NETWORKING //////////
|
////////// RENET NETWORKING //////////
|
||||||
// Creates a RenetClient thats already connected to a server.
|
// Creates a RenetClient thats already connected to a server.
|
||||||
// Returns an Err if connection fails
|
// Returns an Err if connection fails
|
||||||
fn new_renet_client(username: &String) -> anyhow::Result<(RenetClient, NetcodeClientTransport)> {
|
fn new_renet_client(
|
||||||
|
username: &String,
|
||||||
|
) -> anyhow::Result<(RenetClient, NetcodeClientTransport, u64)> {
|
||||||
let client = RenetClient::new(ConnectionConfig::default());
|
let client = RenetClient::new(ConnectionConfig::default());
|
||||||
let server_addr = "127.0.0.1:5000".parse()?;
|
let server_addr = "127.0.0.1:5000".parse()?;
|
||||||
let socket = UdpSocket::bind("127.0.0.1:0")?;
|
let socket = UdpSocket::bind("127.0.0.1:0")?;
|
||||||
|
|
@ -184,7 +228,26 @@ fn new_renet_client(username: &String) -> anyhow::Result<(RenetClient, NetcodeCl
|
||||||
};
|
};
|
||||||
let transport = NetcodeClientTransport::new(current_time, authentication, socket).unwrap();
|
let transport = NetcodeClientTransport::new(current_time, authentication, socket).unwrap();
|
||||||
|
|
||||||
Ok((client, transport))
|
Ok((client, transport, client_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive_events_from_server(
|
||||||
|
mut client: ResMut<RenetClient>,
|
||||||
|
mut game_state: ResMut<BevyGameState>,
|
||||||
|
mut game_events: EventWriter<BevyGameEvent>,
|
||||||
|
) {
|
||||||
|
while let Some(message) = client.receive_message(0) {
|
||||||
|
// Whenever the server sends a message we know that it must be a game event
|
||||||
|
let event: GameEvent = bincode::deserialize(&message).unwrap();
|
||||||
|
trace!("{:#?}", event);
|
||||||
|
|
||||||
|
// We trust the server - It's always been good to us!
|
||||||
|
// No need to validate the events it is sending us
|
||||||
|
game_state.0.consume(&event);
|
||||||
|
|
||||||
|
// Send the event into the bevy event system so systems can react to it
|
||||||
|
game_events.send(BevyGameEvent(event));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any error is found we just panic
|
// If any error is found we just panic
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
mod game;
|
mod game;
|
||||||
pub use game::{ GameState, GameEvent, EndGameReason };
|
pub use game::{EndGameReason, GameEvent, GameState, Stage};
|
||||||
|
|
||||||
mod player;
|
mod player;
|
||||||
pub use player::Player;
|
pub use player::Player;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue