mod incoming_planets;
use std::net::{SocketAddr, UdpSocket};
use std::time::SystemTime;
use bevy::prelude::*;
use bevy::window::PrimaryWindow;
use bevy_rapier2d::prelude::RigidBody;
use bevy_replicon::prelude::RepliconChannels;
use bevy_replicon_renet2::netcode::{ClientAuthentication, NetcodeClientTransport, NativeSocket};
use bevy_replicon_renet2::renet2::{ConnectionConfig, RenetClient};
use bevy_replicon_renet2::RenetChannelsExt;
use crate::client::incoming_planets::incoming_planets_plugin;
use crate::ecs::{Ball, CursorWorldCoordinates, Ground, MainCamera, SendBallHere};
pub struct ClientPlugin {
pub server: SocketAddr
}
impl Plugin for ClientPlugin {
fn build(&self, app: &mut App) {
let server = self.server.clone();
app
.insert_resource(CursorWorldCoordinates(None))
.add_systems(Startup, move |mut commands: Commands, channels: Res<RepliconChannels>| {
let client = RenetClient::new(
ConnectionConfig::from_channels(channels.server_configs(), channels.client_configs()),
false
);
let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let client_id = current_time.as_millis() as u64;
let socket = UdpSocket::bind(SocketAddr::new("::1".parse().unwrap(), 0)).unwrap();
let authentication = ClientAuthentication::Unsecure {
client_id,
protocol_id: 0,
socket_id: 0,
server_addr: server,
user_data: None
};
let transport = NetcodeClientTransport::new(current_time, authentication, NativeSocket::new(socket).unwrap()).unwrap();
commands.insert_resource(client);
commands.insert_resource(transport);
info!(?client_id, "connected!");
})
.add_systems(Startup, setup_graphics)
//.add_systems(Update, add_ball_sprite)
//.add_systems(Update, add_ground_sprite)
.add_systems(Update, update_cursor_position)
.add_systems(Update, teleport_cube_around)
.add_plugins(incoming_planets_plugin);
}
}
fn setup_graphics(mut commands: Commands) {
commands.spawn(Camera2d::default())
.insert(MainCamera);
}
fn add_ball_sprite(mut commands: Commands, q: Query<Entity, Added<Ball>>, asset_server: Res<AssetServer>) {
for item in &q {
let mut sprite = Sprite::from_image(asset_server.load("textures/earth.png"));
sprite.custom_size = Some(Vec2::new(100.0, 100.0));
commands
.entity(item)
.insert(sprite);
}
}
fn add_ground_sprite(mut commands: Commands, q: Query<Entity, Added<Ground>>, asset_server: Res<AssetServer>) {
for item in &q {
let mut sprite = Sprite::from_image(asset_server.load("textures/hearty.png"));
sprite.custom_size = Some(Vec2::new(1000.0, 100.0));
commands
.entity(item)
.insert(sprite);
}
}
fn update_cursor_position(
q_windows: Query<&Window, With<PrimaryWindow>>,
q_camera: Query<(&Camera, &GlobalTransform), With<MainCamera>>,
mut coords: ResMut<CursorWorldCoordinates>
) {
let (camera, camera_transform) = q_camera.single().unwrap();
let window = q_windows.single().unwrap();
if let Some(world_position) = window.cursor_position()
.and_then(|cursor| camera.viewport_to_world(camera_transform, cursor).ok())
.map(|ray| ray.origin.truncate()) {
coords.0 = Some(world_position);
} else {
coords.0 = None;
}
}
fn teleport_cube_around(
cursor_world_coordinates: Res<CursorWorldCoordinates>,
button_input: Res<ButtonInput<MouseButton>>,
mut events: EventWriter<SendBallHere>
) {
if let Some(position) = cursor_world_coordinates.0 && button_input.pressed(MouseButton::Left) {
events.write(SendBallHere(position));
}
}