Implement very basic and bad and specific netcode
All checks were successful
CI / Formatting (push) Successful in 1m14s
All checks were successful
CI / Formatting (push) Successful in 1m14s
The game can now retrieve its seed from another game on the network
This commit is contained in:
parent
50ef78f7aa
commit
dad37262a5
7 changed files with 116 additions and 5 deletions
94
src/net.rs
Normal file
94
src/net.rs
Normal file
|
@ -0,0 +1,94 @@
|
|||
use std::{
|
||||
net::{Ipv6Addr, SocketAddr, UdpSocket},
|
||||
thread,
|
||||
};
|
||||
|
||||
use bevy::prelude::*;
|
||||
use crossbeam_channel::{Receiver, Sender, unbounded};
|
||||
|
||||
use crate::game::seed::Seed;
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct NetworkSend(Sender<(u64, SocketAddr)>);
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct NetworkReceive(Receiver<(u64, SocketAddr)>);
|
||||
|
||||
fn handle_network_io(
|
||||
receive: Res<NetworkReceive>,
|
||||
send: Res<NetworkSend>,
|
||||
seed: Option<Res<Seed>>,
|
||||
mut commands: Commands,
|
||||
) -> Result {
|
||||
let Ok((message, address)) = receive.0.try_recv() else {
|
||||
return Ok(());
|
||||
};
|
||||
if let Some(value) = seed {
|
||||
send.0.try_send((value.clone().into(), address))?;
|
||||
} else {
|
||||
commands.insert_resource::<Seed>(message.into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct NetIOPlugin {
|
||||
listen: u16,
|
||||
peer: Option<SocketAddr>,
|
||||
}
|
||||
|
||||
impl NetIOPlugin {
|
||||
pub fn new(listen: u16, peer: Option<SocketAddr>) -> Self {
|
||||
Self { listen, peer }
|
||||
}
|
||||
}
|
||||
|
||||
impl Plugin for NetIOPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(FixedUpdate, handle_network_io);
|
||||
|
||||
let (send, receive) = match UdpSocket::bind((Ipv6Addr::LOCALHOST, self.listen)) {
|
||||
Ok(socket) => {
|
||||
socket.set_read_timeout(None).unwrap();
|
||||
socket.set_write_timeout(None).unwrap();
|
||||
let (send_outbound, receive_outbound) = unbounded::<(u64, SocketAddr)>();
|
||||
let send_socket = socket.try_clone().unwrap();
|
||||
thread::spawn(move || {
|
||||
loop {
|
||||
match receive_outbound.recv() {
|
||||
Ok((message, address)) => send_socket
|
||||
.send_to(&message.to_le_bytes(), address)
|
||||
.unwrap(),
|
||||
Err(err) => {
|
||||
error!("{err}");
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
let (send_inbound, receive_inbound) = unbounded::<(u64, SocketAddr)>();
|
||||
thread::spawn(move || {
|
||||
loop {
|
||||
let mut message = [0u8; 8];
|
||||
let (len, address) = socket.recv_from(&mut message).unwrap();
|
||||
info!("Received {len} bytes");
|
||||
send_inbound
|
||||
.try_send((u64::from_le_bytes(message), address))
|
||||
.unwrap();
|
||||
}
|
||||
});
|
||||
(send_outbound, receive_inbound)
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Could not bind socket: {err}");
|
||||
todo!("bounded(0) is apparently meaningful so find another solution")
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(socket) = self.peer {
|
||||
send.try_send((0, socket)).unwrap();
|
||||
}
|
||||
|
||||
app.insert_resource(NetworkSend(send));
|
||||
app.insert_resource(NetworkReceive(receive));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue