Compare commits
No commits in common. "dad37262a55a5a0aacc5e6a3589b709814db59c5" and "f0d690a9f862c9b685faf25a8384e8865614b8c9" have entirely different histories.
dad37262a5
...
f0d690a9f8
8 changed files with 7 additions and 124 deletions
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
@ -11,7 +11,7 @@
|
||||||
"cargo": {
|
"cargo": {
|
||||||
"args": ["build"]
|
"args": ["build"]
|
||||||
},
|
},
|
||||||
"args": ["--seed=:)"],
|
"args": ["--seed=gargamel"],
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"env": {
|
"env": {
|
||||||
"CARGO_MANIFEST_DIR": "${workspaceFolder}",
|
"CARGO_MANIFEST_DIR": "${workspaceFolder}",
|
||||||
|
|
2
.vscode/tasks.json
vendored
2
.vscode/tasks.json
vendored
|
@ -35,7 +35,7 @@
|
||||||
"problemMatcher": ["$rustc"],
|
"problemMatcher": ["$rustc"],
|
||||||
"group": {
|
"group": {
|
||||||
"kind": "build",
|
"kind": "build",
|
||||||
"isDefault": false
|
"isDefault": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1921,7 +1921,6 @@ dependencies = [
|
||||||
"bevy",
|
"bevy",
|
||||||
"bevy_rand",
|
"bevy_rand",
|
||||||
"clap",
|
"clap",
|
||||||
"crossbeam-channel",
|
|
||||||
"log",
|
"log",
|
||||||
"rand 0.9.1",
|
"rand 0.9.1",
|
||||||
"wyrand",
|
"wyrand",
|
||||||
|
|
|
@ -36,7 +36,6 @@ bevy = { version = "0.16.0", default-features = false, features = [
|
||||||
] }
|
] }
|
||||||
bevy_rand = { version = "0.11.0", features = ["wyrand", "std"] }
|
bevy_rand = { version = "0.11.0", features = ["wyrand", "std"] }
|
||||||
clap = { version = "4.5.32", features = ["derive"] }
|
clap = { version = "4.5.32", features = ["derive"] }
|
||||||
crossbeam-channel = "0.5.15"
|
|
||||||
log = { version = "*", features = [
|
log = { version = "*", features = [
|
||||||
"max_level_debug",
|
"max_level_debug",
|
||||||
"release_max_level_warn",
|
"release_max_level_warn",
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
use avian2d::prelude::*;
|
use avian2d::prelude::*;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::AppState;
|
|
||||||
|
|
||||||
/// Basic implementation of a physics object
|
/// Basic implementation of a physics object
|
||||||
#[derive(Component, Default)]
|
#[derive(Component, Default)]
|
||||||
#[require(Collider, Mesh2d, MeshMaterial2d<ColorMaterial>, Restitution = Restitution::new(1.0), RigidBody, TransformInterpolation, Transform, StateScoped<AppState> = StateScoped(AppState::InGame))]
|
#[require(Collider, Mesh2d, MeshMaterial2d<ColorMaterial>, Restitution = Restitution::new(1.0), RigidBody, TransformInterpolation, Transform)]
|
||||||
struct GameObject;
|
struct GameObject;
|
||||||
|
|
||||||
/// Radius of a ball
|
/// Radius of a ball
|
||||||
|
|
|
@ -8,7 +8,6 @@ use rand::random;
|
||||||
pub struct Seed(u64);
|
pub struct Seed(u64);
|
||||||
|
|
||||||
impl Seed {
|
impl Seed {
|
||||||
/// Use a random integer as the seed
|
|
||||||
pub fn random() -> Self {
|
pub fn random() -> Self {
|
||||||
Self(random())
|
Self(random())
|
||||||
}
|
}
|
||||||
|
@ -31,15 +30,3 @@ impl From<Seed> for [u8; 8] {
|
||||||
value.0.to_le_bytes()
|
value.0.to_le_bytes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u64> for Seed {
|
|
||||||
fn from(value: u64) -> Self {
|
|
||||||
Seed(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Seed> for u64 {
|
|
||||||
fn from(value: Seed) -> Self {
|
|
||||||
value.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
14
src/lib.rs
14
src/lib.rs
|
@ -14,8 +14,6 @@ use game::{
|
||||||
setup::{check_for_seed, setup_balls, setup_from_seed, setup_player, setup_ui, setup_walls},
|
setup::{check_for_seed, setup_balls, setup_from_seed, setup_player, setup_ui, setup_walls},
|
||||||
};
|
};
|
||||||
|
|
||||||
mod net;
|
|
||||||
|
|
||||||
/// The initial configuration passed to the game's setup functions.
|
/// The initial configuration passed to the game's setup functions.
|
||||||
/// Also functions as a Bevy plugin to pass the configuration into the app.
|
/// Also functions as a Bevy plugin to pass the configuration into the app.
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
|
@ -42,7 +40,6 @@ struct Source {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
#[states(scoped_entities)]
|
|
||||||
enum AppState {
|
enum AppState {
|
||||||
#[default]
|
#[default]
|
||||||
Loading,
|
Loading,
|
||||||
|
@ -65,7 +62,6 @@ impl Plugin for AppSettings {
|
||||||
PhysicsPlugins::default().with_length_unit(50.0),
|
PhysicsPlugins::default().with_length_unit(50.0),
|
||||||
#[cfg(feature = "dev")]
|
#[cfg(feature = "dev")]
|
||||||
dev::dev_tools,
|
dev::dev_tools,
|
||||||
net::NetIOPlugin::new(self.port, self.source.connect),
|
|
||||||
))
|
))
|
||||||
.init_state::<AppState>()
|
.init_state::<AppState>()
|
||||||
.add_systems(Startup, setup_ui)
|
.add_systems(Startup, setup_ui)
|
||||||
|
@ -76,14 +72,11 @@ impl Plugin for AppSettings {
|
||||||
(setup_player, setup_balls, setup_walls).after(setup_from_seed),
|
(setup_player, setup_balls, setup_walls).after(setup_from_seed),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_systems(
|
|
||||||
FixedUpdate,
|
|
||||||
check_for_seed.run_if(in_state(AppState::Loading)),
|
|
||||||
)
|
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
((move_player, move_camera).chain(), zoom_camera)
|
check_for_seed.run_if(in_state(AppState::Loading)),
|
||||||
|
(move_player, move_camera.after(move_player), zoom_camera)
|
||||||
.run_if(in_state(AppState::InGame)),
|
.run_if(in_state(AppState::InGame)),
|
||||||
quit.run_if(input_pressed(KeyCode::KeyQ)),
|
quit.run_if(input_pressed(KeyCode::KeyQ)),
|
||||||
),
|
),
|
||||||
|
@ -92,7 +85,8 @@ impl Plugin for AppSettings {
|
||||||
if let Some(ref seed) = self.source.seed {
|
if let Some(ref seed) = self.source.seed {
|
||||||
app.insert_resource(seed.clone());
|
app.insert_resource(seed.clone());
|
||||||
} else if let Some(ref peer) = self.source.connect {
|
} else if let Some(ref peer) = self.source.connect {
|
||||||
info!("Will retrieve seed from peer => {peer}");
|
info!("Got peer: {peer}");
|
||||||
|
todo!("Handle connecting to peer and retrieving seed");
|
||||||
} else {
|
} else {
|
||||||
app.insert_resource(Seed::random());
|
app.insert_resource(Seed::random());
|
||||||
}
|
}
|
||||||
|
|
94
src/net.rs
94
src/net.rs
|
@ -1,94 +0,0 @@
|
||||||
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