diff --git a/kubi-shared/src/networking/state.rs b/kubi-shared/src/networking/state.rs index dbed8e1..dd9a8b5 100644 --- a/kubi-shared/src/networking/state.rs +++ b/kubi-shared/src/networking/state.rs @@ -1,13 +1,13 @@ use shipyard::{Unique, Component}; // disconnected => connect => join => load => ingame -#[derive(Unique, Component)] +#[derive(Unique, Component, PartialEq, Eq, Clone, Copy)] pub enum ClientJoinState { /// Not connected yet Disconnected, /// Client has connected to the game, but hasn't authenticated yet Connected, - /// Client has joined the game, but haven't loaded the world yet + /// Client has joined the game, but hasn't loaded the world yet Joined, /// Client is currently ingame InGame, diff --git a/kubi/src/connecting_screen.rs b/kubi/src/connecting_screen.rs new file mode 100644 index 0000000..047311b --- /dev/null +++ b/kubi/src/connecting_screen.rs @@ -0,0 +1,12 @@ +use kubi_shared::networking::state::ClientJoinState; +use shipyard::{UniqueViewMut, UniqueView}; +use crate::state::{NextState, GameState}; + +pub fn switch_to_loading_if_connected( + mut next_state: UniqueViewMut, + client_state: UniqueView, +) { + if *client_state == ClientJoinState::Joined { + next_state.0 = Some(GameState::LoadingWorld); + } +} diff --git a/kubi/src/main.rs b/kubi/src/main.rs index 2e8d9dd..c02f929 100644 --- a/kubi/src/main.rs +++ b/kubi/src/main.rs @@ -39,12 +39,14 @@ pub(crate) mod networking; pub(crate) mod init; pub(crate) mod color; pub(crate) mod loading_screen; +pub(crate) mod connecting_screen; use world::{ init_game_world, loading::update_loaded_world_around_player, raycast::update_raycasts, - queue::apply_queued_blocks + queue::apply_queued_blocks, + tasks::inject_network_responses_into_manager_queue }; use player::spawn_player; use prefabs::load_prefabs; @@ -74,11 +76,12 @@ use block_placement::block_placement_system; use delta_time::{DeltaTime, init_delta_time}; use cursor_lock::{insert_lock_state, update_cursor_lock_state, lock_cursor_now}; use control_flow::{exit_on_esc, insert_control_flow_unique, SetControlFlow}; -use state::{is_ingame, is_ingame_or_loading, is_loading, init_state, update_state}; +use state::{is_ingame, is_ingame_or_loading, is_loading, init_state, update_state, is_connecting}; use networking::{update_networking, is_multiplayer, disconnect_on_exit}; use init::initialize_from_args; use gui::{render_gui, init_gui, update_gui}; use loading_screen::update_loading_screen; +use connecting_screen::switch_to_loading_if_connected; fn startup() -> Workload { ( @@ -104,10 +107,13 @@ fn update() -> Workload { update_window_size, update_cursor_lock_state, process_inputs, - ( - update_networking + update_networking, + inject_network_responses_into_manager_queue, ).into_workload().run_if(is_multiplayer), + ( + switch_to_loading_if_connected + ).into_workload().run_if(is_connecting), ( update_loading_screen, ).into_workload().run_if(is_loading), diff --git a/kubi/src/state.rs b/kubi/src/state.rs index 3301964..7ab1b4c 100644 --- a/kubi/src/state.rs +++ b/kubi/src/state.rs @@ -35,6 +35,12 @@ pub fn is_changing_state( state.0.is_some() } +pub fn is_connecting( + state: UniqueView +) -> bool { + *state == GameState::Connecting +} + pub fn is_ingame( state: UniqueView ) -> bool { diff --git a/kubi/src/world/tasks.rs b/kubi/src/world/tasks.rs index 2c73c16..82da68a 100644 --- a/kubi/src/world/tasks.rs +++ b/kubi/src/world/tasks.rs @@ -1,13 +1,15 @@ use flume::{Sender, Receiver}; use glam::IVec3; -use shipyard::Unique; +use kubi_shared::networking::messages::{ClientToServerMessage, ServerToClientMessage}; +use shipyard::{Unique, UniqueView, View, IntoIter}; use rayon::{ThreadPool, ThreadPoolBuilder}; use super::{ chunk::BlockData, mesh::{generate_mesh, data::MeshGenData}, worldgen::generate_world, }; -use crate::rendering::world::ChunkVertex; +use crate::{rendering::world::ChunkVertex, networking::{UdpClient, NetworkEvent}}; +use kubi_udp::client::ClientEvent; pub enum ChunkTask { LoadChunk { @@ -43,6 +45,11 @@ impl ChunkTaskManager { pool: ThreadPoolBuilder::new().num_threads(4).build().unwrap() } } + pub fn add_sussy_response(&self, response: ChunkTaskResponse) { + // this WILL get stuck if the channel is bounded + // don't make the channel bounded ever + self.channel.0.send(response).unwrap() + } pub fn spawn_task(&self, task: ChunkTask) { let sender = self.channel.0.clone(); self.pool.spawn(move || { @@ -62,3 +69,36 @@ impl ChunkTaskManager { self.channel.1.try_recv().ok() } } + +pub fn spawn_task_or_get_from_network_if_possible(client: Option<&mut UdpClient>, manager: &mut ChunkTaskManager, task: ChunkTask) { + match &task { + ChunkTask::LoadChunk { seed, position } => { + match client { + Some(client) => { + client.0.send_message(ClientToServerMessage::ChunkRequest { chunk: position.to_array() }).unwrap(); + }, + None => { + manager.spawn_task(task) + } + } + }, + _ => { + manager.spawn_task(task) + } + } +} + +//TODO get rid of this, this is awfulll +pub fn inject_network_responses_into_manager_queue( + manager: UniqueView, + events: View +) { + for event in events.iter() { + if let ClientEvent::MessageReceived(ServerToClientMessage::ChunkResponse { chunk, data }) = &event.0 { + let position = IVec3::from_array(*chunk); + manager.add_sussy_response(ChunkTaskResponse::LoadedChunk { + position, chunk_data: data.clone() + }); + } + } +}