use bevy_app::{App, Plugin, FixedUpdate};
use bevy_connect::{events::MessageReceivedEvent, prelude::Channel};
use bevy_ecs::message::MessageWriter;
use bevy_ecs::prelude::resource_changed;
use bevy_ecs::prelude::resource_exists;
use bevy_ecs::prelude::resource_removed;
use bevy_ecs::schedule::IntoScheduleConfigs;
use bevy_ecs::schedule::SystemCondition;
use bevy_ecs::schedule::common_conditions::on_message;
use bevy_ecs::{
schedule::common_conditions::resource_added,
system::{Res, ResMut},
};
use bevy_state::{condition::in_state, state::NextState};
use tracing::info;
use crate::{
InitialSyncFinished, ServerState, proto::Message, server::initial_sync::send_initial_sync,
};
mod initial_sync;
mod receiver;
pub(crate) struct ServerSyncPlugin;
impl Plugin for ServerSyncPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
FixedUpdate,
server_connected.run_if(
in_state(ServerState::Disconnected).and_then(resource_added::<Channel<Message>>),
),
);
app.add_systems(
FixedUpdate,
server_disconnected
.run_if(in_state(ServerState::Connected).and_then(resource_removed::<Channel<Message>>)),
);
app.add_systems(
FixedUpdate,
server_update_state.run_if(
resource_exists::<Channel<Message>>.and_then(resource_changed::<Channel<Message>>),
),
);
app.add_systems(
FixedUpdate,
receiver::process_messages.run_if(
in_state(ServerState::Connected)
.and_then(resource_exists::<Channel<Message>>)
.and_then(on_message::<MessageReceivedEvent<Message>>),
),
);
}
}
fn server_disconnected(mut state: ResMut<NextState<ServerState>>) {
info!("Server is shut down.");
state.set(ServerState::Disconnected);
}
#[allow(clippy::needless_pass_by_value)]
fn server_update_state(channel: Res<Channel<Message>>, mut state: ResMut<NextState<ServerState>>) {
if !channel.is_host() {
state.set(ServerState::Disconnected);
return;
}
state.set(ServerState::Connected);
}
#[allow(clippy::needless_pass_by_value)]
fn server_connected(
channel: Res<Channel<Message>>,
mut state: ResMut<NextState<ServerState>>,
mut event: MessageWriter<InitialSyncFinished>,
) {
if !channel.is_host() {
state.set(ServerState::Disconnected);
return;
}
info!("Server ready to accept connections.");
state.set(ServerState::Connected);
event.write(InitialSyncFinished);
}