use async_std::sync::{Arc, RwLock};
use async_std::task;
use lnkit::prelude::*;
use std::collections::HashMap;
use std::thread;
mod input;
mod output;
use input::Input;
use output::Output;
#[async_std::main]
async fn main() {
let (contact_send, contact_recv) = crossbeam::channel::unbounded();
let (intersection_send, _) = crossbeam::channel::unbounded();
let event_handler = ChannelEventCollector::new(intersection_send, contact_send);
let players = Arc::new(RwLock::new(HashMap::new()));
let game = Arc::new(Game::<Input>::new());
game.set_event_handler(Some(event_handler)).await;
game.start_server_task().await;
game.start_physics_task().await;
game.add_mesh(Mesh {
shape: Shape::Cuboid(8.0, 0.25, 8.0),
material: Material::Standard(0xffffff),
body: RigidBodyBuilder::new_static()
.position(Isometry::translation(0.0, -10.0, 0.0))
.build(),
})
.await;
let mesh_handle = game
.add_mesh(Mesh {
shape: Shape::Cuboid(2.0, 0.25, 2.0),
material: Material::Standard(0x888888),
body: RigidBodyBuilder::new_static()
.position(Isometry::translation(-4.0, -8.0, -4.0))
.build(),
})
.await;
{
let game = game.clone();
thread::spawn(move || {
while let Ok(contact_event) = contact_recv.recv() {
match contact_event {
ContactEvent::Started(col0, col1) => {
if mesh_handle.collider_handle == col0
|| mesh_handle.collider_handle == col1
{
let game = game.clone();
task::block_on(async move {
thread::sleep(std::time::Duration::from_secs(1));
game.set_event_handler(None).await;
game.remove_mesh(mesh_handle.entity).await;
});
}
}
_ => {}
}
}
});
}
while let Ok(event) = game.next().await {
let game = game.clone();
let players = players.clone();
task::spawn(async move {
match event {
Event::Connected(id) => {
let mesh = game
.add_mesh(Mesh {
shape: Shape::Cuboid(1.0, 1.0, 1.0),
material: Material::Standard(0xffff00),
body: RigidBodyBuilder::new_dynamic()
.position(Isometry::translation(0.0, 10.0, 0.0))
.build(),
})
.await;
game.send(Some(id), Output::Player(mesh.entity)).await;
players.write().await.insert(id, mesh);
}
Event::Disconnected(id) | Event::Kicked(id, _) => {
if let Some(handle) = players.write().await.remove(&id) {
game.remove_mesh(handle.entity).await;
}
}
Event::Message(id, input) => {
let mesh = players.read().await.get(&id).map(|v| *v).unwrap();
match input {
Input::Jump => {
game.update_body(mesh.body_handle, |body| {
body.apply_force(Vector3::new(0.0, 4_000.0, 0.0), true)
})
.await
}
Input::Left(pressed) => {
game.update_body(mesh.body_handle, |body| {
body.set_linvel(
Vector3::x() * pressed.then(|| -10.0).unwrap_or(0.0),
true,
)
})
.await
}
Input::Down(pressed) => {
game.update_body(mesh.body_handle, |body| {
body.set_linvel(
Vector3::z() * pressed.then(|| 10.0).unwrap_or(0.0),
true,
)
})
.await
}
Input::Up(pressed) => {
game.update_body(mesh.body_handle, |body| {
body.set_linvel(
Vector3::z() * pressed.then(|| -10.0).unwrap_or(0.0),
true,
)
})
.await
}
Input::Right(pressed) => {
game.update_body(mesh.body_handle, |body| {
body.set_linvel(
Vector3::x() * pressed.then(|| 10.0).unwrap_or(0.0),
true,
)
})
.await
}
}
}
}
});
}
}