lnkit 0.2.1

Multiplayer game library
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
                        }
                    }
                }
            }
        });
    }
}