🚧 neat!
parent
f98d5138ff
commit
2059e5a237
File diff suppressed because it is too large
Load Diff
|
@ -11,14 +11,21 @@ edition = "2018"
|
|||
anyhow = "1.0.36"
|
||||
byteorder = "1.3.2"
|
||||
float-ord = "0.2.0"
|
||||
futures = "0.3.8"
|
||||
futures-util = "0.3.9"
|
||||
gl = "0.14.0"
|
||||
glam = "0.8.5"
|
||||
iota = "0.2.1"
|
||||
maplit = "1.0.2"
|
||||
partial-min-max = "0.4.0"
|
||||
png = "0.15.3"
|
||||
quinn = "0.7.2"
|
||||
rand = "0.6.5"
|
||||
rcgen = "0.8.11"
|
||||
rmp-serde = "0.15.4"
|
||||
serde = { version = "1.0.125", features = ["derive"] }
|
||||
sdl2 = "0.32.2"
|
||||
tokio = { version = "1.5.0", features = ["full"] }
|
||||
tracing = "0.1.22"
|
||||
tracing-subscriber = "0.2.15"
|
||||
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use futures::StreamExt;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use opengl_rust::{
|
||||
network_protocol::*,
|
||||
quinn_common::make_server_endpoint,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main () -> anyhow::Result <()> {
|
||||
let server_addr = "127.0.0.1:5000".parse().unwrap();
|
||||
let (mut incoming, server_cert) = make_server_endpoint(server_addr)?;
|
||||
|
||||
let state = NetworkedState {
|
||||
positions: vec! [
|
||||
(32.0, 32.0),
|
||||
],
|
||||
};
|
||||
let state = Arc::new (Mutex::new (state));
|
||||
// let connected_players = Arc::new (Mutex::new (vec! []));
|
||||
|
||||
// accept a single connection
|
||||
let server_task = tokio::spawn (async move {
|
||||
use opengl_rust::timestep::TimeStep;
|
||||
|
||||
let incoming_conn = incoming.next().await.unwrap();
|
||||
let new_conn = incoming_conn.await.unwrap();
|
||||
println!(
|
||||
"[server] connection accepted: addr={}",
|
||||
new_conn.connection.remote_address()
|
||||
);
|
||||
|
||||
let quinn::NewConnection {
|
||||
connection,
|
||||
mut datagrams,
|
||||
..
|
||||
} = new_conn;
|
||||
|
||||
let mut i = 0_u64;
|
||||
|
||||
let cmd = Arc::new (Mutex::new (NetworkCommand::default ()));
|
||||
let cmd_2 = Arc::clone (&cmd);
|
||||
|
||||
// Read player commands
|
||||
tokio::spawn (async move {
|
||||
while let Some (Ok (datagram)) = datagrams.next ().await {
|
||||
let cmd: NetworkCommand = rmp_serde::from_slice (&datagram)?;
|
||||
let mut guard = cmd_2.lock ().await;
|
||||
*guard = cmd;
|
||||
}
|
||||
|
||||
Ok::<_, anyhow::Error> (())
|
||||
});
|
||||
|
||||
let mut time_step = TimeStep::new (120, 1000);
|
||||
let mut state = NetworkedState {
|
||||
positions: vec! [
|
||||
(32.0, 32.0),
|
||||
],
|
||||
};
|
||||
|
||||
loop {
|
||||
let cmd = {
|
||||
let guard = cmd.lock ().await;
|
||||
guard.clone ()
|
||||
};
|
||||
let frames_to_do = time_step.step ();
|
||||
for _ in 0..frames_to_do {
|
||||
let speed = 0.25;
|
||||
if cmd.left {
|
||||
state.positions [0].0 -= speed;
|
||||
}
|
||||
if cmd.right {
|
||||
state.positions [0].0 += speed;
|
||||
}
|
||||
if cmd.up {
|
||||
state.positions [0].1 += speed;
|
||||
}
|
||||
if cmd.down {
|
||||
state.positions [0].1 -= speed;
|
||||
}
|
||||
}
|
||||
|
||||
let bytes = rmp_serde::to_vec (&state)?;
|
||||
connection.send_datagram (bytes.into ())?;
|
||||
|
||||
i += 1;
|
||||
tokio::time::sleep (std::time::Duration::from_millis(16)).await;
|
||||
}
|
||||
|
||||
// Dropping all handles associated with a connection implicitly closes it
|
||||
Ok::<_, anyhow::Error> (())
|
||||
});
|
||||
|
||||
tokio::fs::write ("quic_server.crt", &server_cert).await?;
|
||||
|
||||
/*
|
||||
let endpoint = make_client_endpoint("0.0.0.0:0".parse().unwrap(), &[&server_cert])?;
|
||||
// connect to server
|
||||
let quinn::NewConnection {
|
||||
connection,
|
||||
mut uni_streams,
|
||||
..
|
||||
} = endpoint
|
||||
.connect(&server_addr, "localhost")
|
||||
.unwrap()
|
||||
.await
|
||||
.unwrap();
|
||||
println!("[client] connected: addr={}", connection.remote_address());
|
||||
|
||||
// Waiting for a stream will complete with an error when the server closes the connection
|
||||
let _ = uni_streams.next().await;
|
||||
|
||||
// Give the server has a chance to clean up
|
||||
endpoint.wait_idle().await;
|
||||
*/
|
||||
|
||||
server_task.await??;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -27,6 +27,8 @@ use tracing::{
|
|||
use opengl_rust::{
|
||||
glezz,
|
||||
gpu_buffers,
|
||||
network_protocol::*,
|
||||
quinn_common::make_client_endpoint,
|
||||
shader,
|
||||
timestep::TimeStep,
|
||||
};
|
||||
|
@ -69,7 +71,11 @@ impl ShaderLocations {
|
|||
}
|
||||
|
||||
#[instrument (level = "trace", skip (ctx, state))]
|
||||
fn draw_graphics (ctx: &GraphicsContext, state: &GameState)
|
||||
fn draw_graphics (
|
||||
ctx: &GraphicsContext,
|
||||
state: &GameState,
|
||||
bumps: &[(f32, f32)],
|
||||
)
|
||||
-> anyhow::Result <()>
|
||||
{
|
||||
let shader_locs = &ctx.shader_locations;
|
||||
|
@ -94,7 +100,7 @@ fn draw_graphics (ctx: &GraphicsContext, state: &GameState)
|
|||
let view_mat = proj_mat *
|
||||
Mat4::from_translation (Vec3::from ((0.0, 0.0, -80.0))) *
|
||||
Mat4::from_rotation_x (-60.0 * 3.14159 / 180.0) *
|
||||
Mat4::from_rotation_z ((state.logic_frames % spin_period) as f32 * 3.1415926535 * 2.0 / spin_period as f32) *
|
||||
// Mat4::from_rotation_z ((state.logic_frames % spin_period) as f32 * 3.1415926535 * 2.0 / spin_period as f32) *
|
||||
Mat4::from_translation (Vec3::from ((-32.0, -32.0, -5.0)));
|
||||
|
||||
let mvp = view_mat;
|
||||
|
@ -115,10 +121,7 @@ fn draw_graphics (ctx: &GraphicsContext, state: &GameState)
|
|||
let ClientArrays {
|
||||
vertexes,
|
||||
indexes,
|
||||
} = make_heightmap_arrays (&[
|
||||
(32.0, 48.0),
|
||||
(32.0 + 16.0 * bump_theta.cos (), 32.0 + 16.0 * bump_theta.sin ()),
|
||||
]);
|
||||
} = make_heightmap_arrays (bumps);
|
||||
|
||||
upload_vertexes (&vertexes)?;
|
||||
|
||||
|
@ -241,7 +244,13 @@ fn upload_vertexes (vertexes: &[f32]) -> anyhow::Result <()> {
|
|||
Ok (())
|
||||
}
|
||||
|
||||
fn main () -> anyhow::Result <()> {
|
||||
#[tokio::main]
|
||||
async fn main () -> anyhow::Result <()> {
|
||||
use std::sync::Arc;
|
||||
|
||||
use futures_util::StreamExt;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
tracing_subscriber::fmt::fmt ()
|
||||
.with_env_filter (tracing_subscriber::EnvFilter::from_default_env())
|
||||
.with_span_events (tracing_subscriber::fmt::format::FmtSpan::CLOSE)
|
||||
|
@ -314,26 +323,86 @@ fn main () -> anyhow::Result <()> {
|
|||
logic_frames: 0,
|
||||
};
|
||||
|
||||
let server_cert = tokio::fs::read ("quic_server.crt").await?;
|
||||
let server_addr = "127.0.0.1:5000".parse().unwrap();
|
||||
let endpoint = make_client_endpoint("0.0.0.0:0".parse().unwrap(), &[&server_cert])?;
|
||||
// connect to server
|
||||
let quinn::NewConnection {
|
||||
connection,
|
||||
mut datagrams,
|
||||
..
|
||||
} = endpoint
|
||||
.connect(&server_addr, "localhost")
|
||||
.unwrap()
|
||||
.await
|
||||
.unwrap();
|
||||
println!("[client] connected: addr={}", connection.remote_address());
|
||||
|
||||
let networked_state = Arc::new (Mutex::new (NetworkedState::default ()));
|
||||
let networked_state_2 = Arc::clone (&networked_state);
|
||||
|
||||
tokio::spawn (async move {
|
||||
while let Some (Ok (datagram)) = datagrams.next ().await {
|
||||
let state = rmp_serde::from_slice (&datagram)?;
|
||||
let mut guard = networked_state_2.lock ().await;
|
||||
*guard = state;
|
||||
}
|
||||
|
||||
Ok::<_, anyhow::Error> (())
|
||||
});
|
||||
|
||||
'running: loop {
|
||||
let frames_to_do = time_step.step ();
|
||||
|
||||
let _mouse = event_pump.mouse_state ();
|
||||
|
||||
let mut cmd = NetworkCommand::default ();
|
||||
|
||||
for event in event_pump.poll_iter() {
|
||||
match event {
|
||||
Event::Quit {..} |
|
||||
Event::KeyDown { keycode: Some (Keycode::Escape), .. } => {
|
||||
break 'running
|
||||
},
|
||||
Event::KeyDown { keycode: Some (keycode), .. } => {
|
||||
match keycode {
|
||||
Keycode::Left => cmd.left = true,
|
||||
Keycode::Right => cmd.right = true,
|
||||
Keycode::Up => cmd.up = true,
|
||||
Keycode::Down => cmd.right = true,
|
||||
_ => (),
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
let keyboard_state = event_pump.keyboard_state ();
|
||||
if keyboard_state.is_scancode_pressed (Scancode::Left) {
|
||||
cmd.left = true
|
||||
}
|
||||
if keyboard_state.is_scancode_pressed (Scancode::Right) {
|
||||
cmd.right = true
|
||||
}
|
||||
if keyboard_state.is_scancode_pressed (Scancode::Up) {
|
||||
cmd.up = true
|
||||
}
|
||||
if keyboard_state.is_scancode_pressed (Scancode::Down) {
|
||||
cmd.down = true
|
||||
}
|
||||
|
||||
let bytes = rmp_serde::to_vec (&cmd)?;
|
||||
connection.send_datagram (bytes.into ())?;
|
||||
|
||||
for _ in 0..frames_to_do {
|
||||
game_state.logic_frames += 1;
|
||||
}
|
||||
|
||||
draw_graphics (&graphics_ctx, &game_state)?;
|
||||
let state = {
|
||||
let guard = networked_state.lock ().await;
|
||||
guard.clone ()
|
||||
};
|
||||
draw_graphics (&graphics_ctx, &game_state, &state.positions)?;
|
||||
graphics_frames += 1;
|
||||
|
||||
std::thread::sleep (Duration::from_millis (15));
|
||||
|
|
|
@ -8,7 +8,9 @@ pub mod file;
|
|||
pub mod glezz;
|
||||
pub mod gl_state;
|
||||
pub mod gpu_buffers;
|
||||
pub mod network_protocol;
|
||||
pub mod physics;
|
||||
pub mod quinn_common;
|
||||
pub mod renderable_model;
|
||||
pub mod shader;
|
||||
pub mod shader_closure;
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive (Clone, Default, Deserialize, Serialize)]
|
||||
pub struct NetworkedState {
|
||||
pub positions: Vec <(f32, f32)>,
|
||||
}
|
||||
|
||||
#[derive (Clone, Default, Deserialize, Serialize)]
|
||||
pub struct NetworkCommand {
|
||||
pub left: bool,
|
||||
pub right: bool,
|
||||
pub up: bool,
|
||||
pub down: bool,
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
use quinn::{
|
||||
Certificate, CertificateChain, ClientConfig, ClientConfigBuilder, Endpoint, Incoming,
|
||||
PrivateKey, ServerConfig, ServerConfigBuilder, TransportConfig,
|
||||
};
|
||||
use std::{error::Error, net::SocketAddr, sync::Arc};
|
||||
|
||||
/// Constructs a QUIC endpoint configured for use a client only.
|
||||
///
|
||||
/// ## Args
|
||||
///
|
||||
/// - server_certs: list of trusted certificates.
|
||||
#[allow(unused)]
|
||||
pub fn make_client_endpoint(
|
||||
bind_addr: SocketAddr,
|
||||
server_certs: &[&[u8]],
|
||||
) -> anyhow::Result<Endpoint> {
|
||||
let client_cfg = configure_client(server_certs)?;
|
||||
let mut endpoint_builder = Endpoint::builder();
|
||||
endpoint_builder.default_client_config(client_cfg);
|
||||
let (endpoint, _incoming) = endpoint_builder.bind(&bind_addr)?;
|
||||
Ok(endpoint)
|
||||
}
|
||||
|
||||
/// Constructs a QUIC endpoint configured to listen for incoming connections on a certain address
|
||||
/// and port.
|
||||
///
|
||||
/// ## Returns
|
||||
///
|
||||
/// - a stream of incoming QUIC connections
|
||||
/// - server certificate serialized into DER format
|
||||
#[allow(unused)]
|
||||
pub fn make_server_endpoint(bind_addr: SocketAddr) -> anyhow::Result<(Incoming, Vec<u8>)> {
|
||||
let (server_config, server_cert) = configure_server()?;
|
||||
let mut endpoint_builder = Endpoint::builder();
|
||||
endpoint_builder.listen(server_config);
|
||||
let (_endpoint, incoming) = endpoint_builder.bind(&bind_addr)?;
|
||||
Ok((incoming, server_cert))
|
||||
}
|
||||
|
||||
/// Builds default quinn client config and trusts given certificates.
|
||||
///
|
||||
/// ## Args
|
||||
///
|
||||
/// - server_certs: a list of trusted certificates in DER format.
|
||||
fn configure_client(server_certs: &[&[u8]]) -> anyhow::Result<ClientConfig> {
|
||||
let mut cfg_builder = ClientConfigBuilder::default();
|
||||
for cert in server_certs {
|
||||
cfg_builder.add_certificate_authority(Certificate::from_der(&cert)?)?;
|
||||
}
|
||||
Ok(cfg_builder.build())
|
||||
}
|
||||
|
||||
/// Returns default server configuration along with its certificate.
|
||||
#[allow(clippy::field_reassign_with_default)] // https://github.com/rust-lang/rust-clippy/issues/6527
|
||||
fn configure_server() -> anyhow::Result<(ServerConfig, Vec<u8>)> {
|
||||
let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap();
|
||||
let cert_der = cert.serialize_der().unwrap();
|
||||
let priv_key = cert.serialize_private_key_der();
|
||||
let priv_key = PrivateKey::from_der(&priv_key)?;
|
||||
|
||||
let mut transport_config = TransportConfig::default();
|
||||
transport_config.max_concurrent_uni_streams(0).unwrap();
|
||||
let mut server_config = ServerConfig::default();
|
||||
server_config.transport = Arc::new(transport_config);
|
||||
let mut cfg_builder = ServerConfigBuilder::new(server_config);
|
||||
let cert = Certificate::from_der(&cert_der)?;
|
||||
cfg_builder.certificate(CertificateChain::from_certs(vec![cert]), priv_key)?;
|
||||
|
||||
Ok((cfg_builder.build(), cert_der))
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub const ALPN_QUIC_HTTP: &[&[u8]] = &[b"hq-29"];
|
Loading…
Reference in New Issue